xref: /dflybsd-src/contrib/gcc-8.0/gcc/final.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Convert RTL to assembler code and output it, for GNU compiler.
2*38fd1498Szrj    Copyright (C) 1987-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 /* This is the final pass of the compiler.
21*38fd1498Szrj    It looks at the rtl code for a function and outputs assembler code.
22*38fd1498Szrj 
23*38fd1498Szrj    Call `final_start_function' to output the assembler code for function entry,
24*38fd1498Szrj    `final' to output assembler code for some RTL code,
25*38fd1498Szrj    `final_end_function' to output assembler code for function exit.
26*38fd1498Szrj    If a function is compiled in several pieces, each piece is
27*38fd1498Szrj    output separately with `final'.
28*38fd1498Szrj 
29*38fd1498Szrj    Some optimizations are also done at this level.
30*38fd1498Szrj    Move instructions that were made unnecessary by good register allocation
31*38fd1498Szrj    are detected and omitted from the output.  (Though most of these
32*38fd1498Szrj    are removed by the last jump pass.)
33*38fd1498Szrj 
34*38fd1498Szrj    Instructions to set the condition codes are omitted when it can be
35*38fd1498Szrj    seen that the condition codes already had the desired values.
36*38fd1498Szrj 
37*38fd1498Szrj    In some cases it is sufficient if the inherited condition codes
38*38fd1498Szrj    have related values, but this may require the following insn
39*38fd1498Szrj    (the one that tests the condition codes) to be modified.
40*38fd1498Szrj 
41*38fd1498Szrj    The code for the function prologue and epilogue are generated
42*38fd1498Szrj    directly in assembler by the target functions function_prologue and
43*38fd1498Szrj    function_epilogue.  Those instructions never exist as rtl.  */
44*38fd1498Szrj 
45*38fd1498Szrj #include "config.h"
46*38fd1498Szrj #define INCLUDE_ALGORITHM /* reverse */
47*38fd1498Szrj #include "system.h"
48*38fd1498Szrj #include "coretypes.h"
49*38fd1498Szrj #include "backend.h"
50*38fd1498Szrj #include "target.h"
51*38fd1498Szrj #include "rtl.h"
52*38fd1498Szrj #include "tree.h"
53*38fd1498Szrj #include "cfghooks.h"
54*38fd1498Szrj #include "df.h"
55*38fd1498Szrj #include "memmodel.h"
56*38fd1498Szrj #include "tm_p.h"
57*38fd1498Szrj #include "insn-config.h"
58*38fd1498Szrj #include "regs.h"
59*38fd1498Szrj #include "emit-rtl.h"
60*38fd1498Szrj #include "recog.h"
61*38fd1498Szrj #include "cgraph.h"
62*38fd1498Szrj #include "tree-pretty-print.h" /* for dump_function_header */
63*38fd1498Szrj #include "varasm.h"
64*38fd1498Szrj #include "insn-attr.h"
65*38fd1498Szrj #include "conditions.h"
66*38fd1498Szrj #include "flags.h"
67*38fd1498Szrj #include "output.h"
68*38fd1498Szrj #include "except.h"
69*38fd1498Szrj #include "rtl-error.h"
70*38fd1498Szrj #include "toplev.h" /* exact_log2, floor_log2 */
71*38fd1498Szrj #include "reload.h"
72*38fd1498Szrj #include "intl.h"
73*38fd1498Szrj #include "cfgrtl.h"
74*38fd1498Szrj #include "debug.h"
75*38fd1498Szrj #include "tree-pass.h"
76*38fd1498Szrj #include "tree-ssa.h"
77*38fd1498Szrj #include "cfgloop.h"
78*38fd1498Szrj #include "params.h"
79*38fd1498Szrj #include "stringpool.h"
80*38fd1498Szrj #include "attribs.h"
81*38fd1498Szrj #include "asan.h"
82*38fd1498Szrj #include "rtl-iter.h"
83*38fd1498Szrj #include "print-rtl.h"
84*38fd1498Szrj 
85*38fd1498Szrj #ifdef XCOFF_DEBUGGING_INFO
86*38fd1498Szrj #include "xcoffout.h"		/* Needed for external data declarations.  */
87*38fd1498Szrj #endif
88*38fd1498Szrj 
89*38fd1498Szrj #include "dwarf2out.h"
90*38fd1498Szrj 
91*38fd1498Szrj #ifdef DBX_DEBUGGING_INFO
92*38fd1498Szrj #include "dbxout.h"
93*38fd1498Szrj #endif
94*38fd1498Szrj 
95*38fd1498Szrj /* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT.
96*38fd1498Szrj    So define a null default for it to save conditionalization later.  */
97*38fd1498Szrj #ifndef CC_STATUS_INIT
98*38fd1498Szrj #define CC_STATUS_INIT
99*38fd1498Szrj #endif
100*38fd1498Szrj 
101*38fd1498Szrj /* Is the given character a logical line separator for the assembler?  */
102*38fd1498Szrj #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
103*38fd1498Szrj #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == ';')
104*38fd1498Szrj #endif
105*38fd1498Szrj 
106*38fd1498Szrj #ifndef JUMP_TABLES_IN_TEXT_SECTION
107*38fd1498Szrj #define JUMP_TABLES_IN_TEXT_SECTION 0
108*38fd1498Szrj #endif
109*38fd1498Szrj 
110*38fd1498Szrj /* Bitflags used by final_scan_insn.  */
111*38fd1498Szrj #define SEEN_NOTE	1
112*38fd1498Szrj #define SEEN_EMITTED	2
113*38fd1498Szrj #define SEEN_NEXT_VIEW	4
114*38fd1498Szrj 
115*38fd1498Szrj /* Last insn processed by final_scan_insn.  */
116*38fd1498Szrj static rtx_insn *debug_insn;
117*38fd1498Szrj rtx_insn *current_output_insn;
118*38fd1498Szrj 
119*38fd1498Szrj /* Line number of last NOTE.  */
120*38fd1498Szrj static int last_linenum;
121*38fd1498Szrj 
122*38fd1498Szrj /* Column number of last NOTE.  */
123*38fd1498Szrj static int last_columnnum;
124*38fd1498Szrj 
125*38fd1498Szrj /* Last discriminator written to assembly.  */
126*38fd1498Szrj static int last_discriminator;
127*38fd1498Szrj 
128*38fd1498Szrj /* Discriminator of current block.  */
129*38fd1498Szrj static int discriminator;
130*38fd1498Szrj 
131*38fd1498Szrj /* Highest line number in current block.  */
132*38fd1498Szrj static int high_block_linenum;
133*38fd1498Szrj 
134*38fd1498Szrj /* Likewise for function.  */
135*38fd1498Szrj static int high_function_linenum;
136*38fd1498Szrj 
137*38fd1498Szrj /* Filename of last NOTE.  */
138*38fd1498Szrj static const char *last_filename;
139*38fd1498Szrj 
140*38fd1498Szrj /* Override filename, line and column number.  */
141*38fd1498Szrj static const char *override_filename;
142*38fd1498Szrj static int override_linenum;
143*38fd1498Szrj static int override_columnnum;
144*38fd1498Szrj 
145*38fd1498Szrj /* Whether to force emission of a line note before the next insn.  */
146*38fd1498Szrj static bool force_source_line = false;
147*38fd1498Szrj 
148*38fd1498Szrj extern const int length_unit_log; /* This is defined in insn-attrtab.c.  */
149*38fd1498Szrj 
150*38fd1498Szrj /* Nonzero while outputting an `asm' with operands.
151*38fd1498Szrj    This means that inconsistencies are the user's fault, so don't die.
152*38fd1498Szrj    The precise value is the insn being output, to pass to error_for_asm.  */
153*38fd1498Szrj const rtx_insn *this_is_asm_operands;
154*38fd1498Szrj 
155*38fd1498Szrj /* Number of operands of this insn, for an `asm' with operands.  */
156*38fd1498Szrj static unsigned int insn_noperands;
157*38fd1498Szrj 
158*38fd1498Szrj /* Compare optimization flag.  */
159*38fd1498Szrj 
160*38fd1498Szrj static rtx last_ignored_compare = 0;
161*38fd1498Szrj 
162*38fd1498Szrj /* Assign a unique number to each insn that is output.
163*38fd1498Szrj    This can be used to generate unique local labels.  */
164*38fd1498Szrj 
165*38fd1498Szrj static int insn_counter = 0;
166*38fd1498Szrj 
167*38fd1498Szrj /* This variable contains machine-dependent flags (defined in tm.h)
168*38fd1498Szrj    set and examined by output routines
169*38fd1498Szrj    that describe how to interpret the condition codes properly.  */
170*38fd1498Szrj 
171*38fd1498Szrj CC_STATUS cc_status;
172*38fd1498Szrj 
173*38fd1498Szrj /* During output of an insn, this contains a copy of cc_status
174*38fd1498Szrj    from before the insn.  */
175*38fd1498Szrj 
176*38fd1498Szrj CC_STATUS cc_prev_status;
177*38fd1498Szrj 
178*38fd1498Szrj /* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen.  */
179*38fd1498Szrj 
180*38fd1498Szrj static int block_depth;
181*38fd1498Szrj 
182*38fd1498Szrj /* Nonzero if have enabled APP processing of our assembler output.  */
183*38fd1498Szrj 
184*38fd1498Szrj static int app_on;
185*38fd1498Szrj 
186*38fd1498Szrj /* If we are outputting an insn sequence, this contains the sequence rtx.
187*38fd1498Szrj    Zero otherwise.  */
188*38fd1498Szrj 
189*38fd1498Szrj rtx_sequence *final_sequence;
190*38fd1498Szrj 
191*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
192*38fd1498Szrj 
193*38fd1498Szrj /* Number of the assembler dialect to use, starting at 0.  */
194*38fd1498Szrj static int dialect_number;
195*38fd1498Szrj #endif
196*38fd1498Szrj 
197*38fd1498Szrj /* Nonnull if the insn currently being emitted was a COND_EXEC pattern.  */
198*38fd1498Szrj rtx current_insn_predicate;
199*38fd1498Szrj 
200*38fd1498Szrj /* True if printing into -fdump-final-insns= dump.  */
201*38fd1498Szrj bool final_insns_dump_p;
202*38fd1498Szrj 
203*38fd1498Szrj /* True if profile_function should be called, but hasn't been called yet.  */
204*38fd1498Szrj static bool need_profile_function;
205*38fd1498Szrj 
206*38fd1498Szrj static int asm_insn_count (rtx);
207*38fd1498Szrj static void profile_function (FILE *);
208*38fd1498Szrj static void profile_after_prologue (FILE *);
209*38fd1498Szrj static bool notice_source_line (rtx_insn *, bool *);
210*38fd1498Szrj static rtx walk_alter_subreg (rtx *, bool *);
211*38fd1498Szrj static void output_asm_name (void);
212*38fd1498Szrj static void output_alternate_entry_point (FILE *, rtx_insn *);
213*38fd1498Szrj static tree get_mem_expr_from_op (rtx, int *);
214*38fd1498Szrj static void output_asm_operand_names (rtx *, int *, int);
215*38fd1498Szrj #ifdef LEAF_REGISTERS
216*38fd1498Szrj static void leaf_renumber_regs (rtx_insn *);
217*38fd1498Szrj #endif
218*38fd1498Szrj #if HAVE_cc0
219*38fd1498Szrj static int alter_cond (rtx);
220*38fd1498Szrj #endif
221*38fd1498Szrj static int align_fuzz (rtx, rtx, int, unsigned);
222*38fd1498Szrj static void collect_fn_hard_reg_usage (void);
223*38fd1498Szrj static tree get_call_fndecl (rtx_insn *);
224*38fd1498Szrj 
225*38fd1498Szrj /* Initialize data in final at the beginning of a compilation.  */
226*38fd1498Szrj 
227*38fd1498Szrj void
228*38fd1498Szrj init_final (const char *filename ATTRIBUTE_UNUSED)
229*38fd1498Szrj {
230*38fd1498Szrj   app_on = 0;
231*38fd1498Szrj   final_sequence = 0;
232*38fd1498Szrj 
233*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
234*38fd1498Szrj   dialect_number = ASSEMBLER_DIALECT;
235*38fd1498Szrj #endif
236*38fd1498Szrj }
237*38fd1498Szrj 
238*38fd1498Szrj /* Default target function prologue and epilogue assembler output.
239*38fd1498Szrj 
240*38fd1498Szrj    If not overridden for epilogue code, then the function body itself
241*38fd1498Szrj    contains return instructions wherever needed.  */
242*38fd1498Szrj void
243*38fd1498Szrj default_function_pro_epilogue (FILE *)
244*38fd1498Szrj {
245*38fd1498Szrj }
246*38fd1498Szrj 
247*38fd1498Szrj void
248*38fd1498Szrj default_function_switched_text_sections (FILE *file ATTRIBUTE_UNUSED,
249*38fd1498Szrj 					 tree decl ATTRIBUTE_UNUSED,
250*38fd1498Szrj 					 bool new_is_cold ATTRIBUTE_UNUSED)
251*38fd1498Szrj {
252*38fd1498Szrj }
253*38fd1498Szrj 
254*38fd1498Szrj /* Default target hook that outputs nothing to a stream.  */
255*38fd1498Szrj void
256*38fd1498Szrj no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED)
257*38fd1498Szrj {
258*38fd1498Szrj }
259*38fd1498Szrj 
260*38fd1498Szrj /* Enable APP processing of subsequent output.
261*38fd1498Szrj    Used before the output from an `asm' statement.  */
262*38fd1498Szrj 
263*38fd1498Szrj void
264*38fd1498Szrj app_enable (void)
265*38fd1498Szrj {
266*38fd1498Szrj   if (! app_on)
267*38fd1498Szrj     {
268*38fd1498Szrj       fputs (ASM_APP_ON, asm_out_file);
269*38fd1498Szrj       app_on = 1;
270*38fd1498Szrj     }
271*38fd1498Szrj }
272*38fd1498Szrj 
273*38fd1498Szrj /* Disable APP processing of subsequent output.
274*38fd1498Szrj    Called from varasm.c before most kinds of output.  */
275*38fd1498Szrj 
276*38fd1498Szrj void
277*38fd1498Szrj app_disable (void)
278*38fd1498Szrj {
279*38fd1498Szrj   if (app_on)
280*38fd1498Szrj     {
281*38fd1498Szrj       fputs (ASM_APP_OFF, asm_out_file);
282*38fd1498Szrj       app_on = 0;
283*38fd1498Szrj     }
284*38fd1498Szrj }
285*38fd1498Szrj 
286*38fd1498Szrj /* Return the number of slots filled in the current
287*38fd1498Szrj    delayed branch sequence (we don't count the insn needing the
288*38fd1498Szrj    delay slot).   Zero if not in a delayed branch sequence.  */
289*38fd1498Szrj 
290*38fd1498Szrj int
291*38fd1498Szrj dbr_sequence_length (void)
292*38fd1498Szrj {
293*38fd1498Szrj   if (final_sequence != 0)
294*38fd1498Szrj     return XVECLEN (final_sequence, 0) - 1;
295*38fd1498Szrj   else
296*38fd1498Szrj     return 0;
297*38fd1498Szrj }
298*38fd1498Szrj 
299*38fd1498Szrj /* The next two pages contain routines used to compute the length of an insn
300*38fd1498Szrj    and to shorten branches.  */
301*38fd1498Szrj 
302*38fd1498Szrj /* Arrays for insn lengths, and addresses.  The latter is referenced by
303*38fd1498Szrj    `insn_current_length'.  */
304*38fd1498Szrj 
305*38fd1498Szrj static int *insn_lengths;
306*38fd1498Szrj 
307*38fd1498Szrj vec<int> insn_addresses_;
308*38fd1498Szrj 
309*38fd1498Szrj /* Max uid for which the above arrays are valid.  */
310*38fd1498Szrj static int insn_lengths_max_uid;
311*38fd1498Szrj 
312*38fd1498Szrj /* Address of insn being processed.  Used by `insn_current_length'.  */
313*38fd1498Szrj int insn_current_address;
314*38fd1498Szrj 
315*38fd1498Szrj /* Address of insn being processed in previous iteration.  */
316*38fd1498Szrj int insn_last_address;
317*38fd1498Szrj 
318*38fd1498Szrj /* known invariant alignment of insn being processed.  */
319*38fd1498Szrj int insn_current_align;
320*38fd1498Szrj 
321*38fd1498Szrj /* After shorten_branches, for any insn, uid_align[INSN_UID (insn)]
322*38fd1498Szrj    gives the next following alignment insn that increases the known
323*38fd1498Szrj    alignment, or NULL_RTX if there is no such insn.
324*38fd1498Szrj    For any alignment obtained this way, we can again index uid_align with
325*38fd1498Szrj    its uid to obtain the next following align that in turn increases the
326*38fd1498Szrj    alignment, till we reach NULL_RTX; the sequence obtained this way
327*38fd1498Szrj    for each insn we'll call the alignment chain of this insn in the following
328*38fd1498Szrj    comments.  */
329*38fd1498Szrj 
330*38fd1498Szrj struct label_alignment
331*38fd1498Szrj {
332*38fd1498Szrj   short alignment;
333*38fd1498Szrj   short max_skip;
334*38fd1498Szrj };
335*38fd1498Szrj 
336*38fd1498Szrj static rtx *uid_align;
337*38fd1498Szrj static int *uid_shuid;
338*38fd1498Szrj static struct label_alignment *label_align;
339*38fd1498Szrj 
340*38fd1498Szrj /* Indicate that branch shortening hasn't yet been done.  */
341*38fd1498Szrj 
342*38fd1498Szrj void
343*38fd1498Szrj init_insn_lengths (void)
344*38fd1498Szrj {
345*38fd1498Szrj   if (uid_shuid)
346*38fd1498Szrj     {
347*38fd1498Szrj       free (uid_shuid);
348*38fd1498Szrj       uid_shuid = 0;
349*38fd1498Szrj     }
350*38fd1498Szrj   if (insn_lengths)
351*38fd1498Szrj     {
352*38fd1498Szrj       free (insn_lengths);
353*38fd1498Szrj       insn_lengths = 0;
354*38fd1498Szrj       insn_lengths_max_uid = 0;
355*38fd1498Szrj     }
356*38fd1498Szrj   if (HAVE_ATTR_length)
357*38fd1498Szrj     INSN_ADDRESSES_FREE ();
358*38fd1498Szrj   if (uid_align)
359*38fd1498Szrj     {
360*38fd1498Szrj       free (uid_align);
361*38fd1498Szrj       uid_align = 0;
362*38fd1498Szrj     }
363*38fd1498Szrj }
364*38fd1498Szrj 
365*38fd1498Szrj /* Obtain the current length of an insn.  If branch shortening has been done,
366*38fd1498Szrj    get its actual length.  Otherwise, use FALLBACK_FN to calculate the
367*38fd1498Szrj    length.  */
368*38fd1498Szrj static int
369*38fd1498Szrj get_attr_length_1 (rtx_insn *insn, int (*fallback_fn) (rtx_insn *))
370*38fd1498Szrj {
371*38fd1498Szrj   rtx body;
372*38fd1498Szrj   int i;
373*38fd1498Szrj   int length = 0;
374*38fd1498Szrj 
375*38fd1498Szrj   if (!HAVE_ATTR_length)
376*38fd1498Szrj     return 0;
377*38fd1498Szrj 
378*38fd1498Szrj   if (insn_lengths_max_uid > INSN_UID (insn))
379*38fd1498Szrj     return insn_lengths[INSN_UID (insn)];
380*38fd1498Szrj   else
381*38fd1498Szrj     switch (GET_CODE (insn))
382*38fd1498Szrj       {
383*38fd1498Szrj       case NOTE:
384*38fd1498Szrj       case BARRIER:
385*38fd1498Szrj       case CODE_LABEL:
386*38fd1498Szrj       case DEBUG_INSN:
387*38fd1498Szrj 	return 0;
388*38fd1498Szrj 
389*38fd1498Szrj       case CALL_INSN:
390*38fd1498Szrj       case JUMP_INSN:
391*38fd1498Szrj 	length = fallback_fn (insn);
392*38fd1498Szrj 	break;
393*38fd1498Szrj 
394*38fd1498Szrj       case INSN:
395*38fd1498Szrj 	body = PATTERN (insn);
396*38fd1498Szrj 	if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
397*38fd1498Szrj 	  return 0;
398*38fd1498Szrj 
399*38fd1498Szrj 	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
400*38fd1498Szrj 	  length = asm_insn_count (body) * fallback_fn (insn);
401*38fd1498Szrj 	else if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (body))
402*38fd1498Szrj 	  for (i = 0; i < seq->len (); i++)
403*38fd1498Szrj 	    length += get_attr_length_1 (seq->insn (i), fallback_fn);
404*38fd1498Szrj 	else
405*38fd1498Szrj 	  length = fallback_fn (insn);
406*38fd1498Szrj 	break;
407*38fd1498Szrj 
408*38fd1498Szrj       default:
409*38fd1498Szrj 	break;
410*38fd1498Szrj       }
411*38fd1498Szrj 
412*38fd1498Szrj #ifdef ADJUST_INSN_LENGTH
413*38fd1498Szrj   ADJUST_INSN_LENGTH (insn, length);
414*38fd1498Szrj #endif
415*38fd1498Szrj   return length;
416*38fd1498Szrj }
417*38fd1498Szrj 
418*38fd1498Szrj /* Obtain the current length of an insn.  If branch shortening has been done,
419*38fd1498Szrj    get its actual length.  Otherwise, get its maximum length.  */
420*38fd1498Szrj int
421*38fd1498Szrj get_attr_length (rtx_insn *insn)
422*38fd1498Szrj {
423*38fd1498Szrj   return get_attr_length_1 (insn, insn_default_length);
424*38fd1498Szrj }
425*38fd1498Szrj 
426*38fd1498Szrj /* Obtain the current length of an insn.  If branch shortening has been done,
427*38fd1498Szrj    get its actual length.  Otherwise, get its minimum length.  */
428*38fd1498Szrj int
429*38fd1498Szrj get_attr_min_length (rtx_insn *insn)
430*38fd1498Szrj {
431*38fd1498Szrj   return get_attr_length_1 (insn, insn_min_length);
432*38fd1498Szrj }
433*38fd1498Szrj 
434*38fd1498Szrj /* Code to handle alignment inside shorten_branches.  */
435*38fd1498Szrj 
436*38fd1498Szrj /* Here is an explanation how the algorithm in align_fuzz can give
437*38fd1498Szrj    proper results:
438*38fd1498Szrj 
439*38fd1498Szrj    Call a sequence of instructions beginning with alignment point X
440*38fd1498Szrj    and continuing until the next alignment point `block X'.  When `X'
441*38fd1498Szrj    is used in an expression, it means the alignment value of the
442*38fd1498Szrj    alignment point.
443*38fd1498Szrj 
444*38fd1498Szrj    Call the distance between the start of the first insn of block X, and
445*38fd1498Szrj    the end of the last insn of block X `IX', for the `inner size of X'.
446*38fd1498Szrj    This is clearly the sum of the instruction lengths.
447*38fd1498Szrj 
448*38fd1498Szrj    Likewise with the next alignment-delimited block following X, which we
449*38fd1498Szrj    shall call block Y.
450*38fd1498Szrj 
451*38fd1498Szrj    Call the distance between the start of the first insn of block X, and
452*38fd1498Szrj    the start of the first insn of block Y `OX', for the `outer size of X'.
453*38fd1498Szrj 
454*38fd1498Szrj    The estimated padding is then OX - IX.
455*38fd1498Szrj 
456*38fd1498Szrj    OX can be safely estimated as
457*38fd1498Szrj 
458*38fd1498Szrj            if (X >= Y)
459*38fd1498Szrj                    OX = round_up(IX, Y)
460*38fd1498Szrj            else
461*38fd1498Szrj                    OX = round_up(IX, X) + Y - X
462*38fd1498Szrj 
463*38fd1498Szrj    Clearly est(IX) >= real(IX), because that only depends on the
464*38fd1498Szrj    instruction lengths, and those being overestimated is a given.
465*38fd1498Szrj 
466*38fd1498Szrj    Clearly round_up(foo, Z) >= round_up(bar, Z) if foo >= bar, so
467*38fd1498Szrj    we needn't worry about that when thinking about OX.
468*38fd1498Szrj 
469*38fd1498Szrj    When X >= Y, the alignment provided by Y adds no uncertainty factor
470*38fd1498Szrj    for branch ranges starting before X, so we can just round what we have.
471*38fd1498Szrj    But when X < Y, we don't know anything about the, so to speak,
472*38fd1498Szrj    `middle bits', so we have to assume the worst when aligning up from an
473*38fd1498Szrj    address mod X to one mod Y, which is Y - X.  */
474*38fd1498Szrj 
475*38fd1498Szrj #ifndef LABEL_ALIGN
476*38fd1498Szrj #define LABEL_ALIGN(LABEL) align_labels_log
477*38fd1498Szrj #endif
478*38fd1498Szrj 
479*38fd1498Szrj #ifndef LOOP_ALIGN
480*38fd1498Szrj #define LOOP_ALIGN(LABEL) align_loops_log
481*38fd1498Szrj #endif
482*38fd1498Szrj 
483*38fd1498Szrj #ifndef LABEL_ALIGN_AFTER_BARRIER
484*38fd1498Szrj #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
485*38fd1498Szrj #endif
486*38fd1498Szrj 
487*38fd1498Szrj #ifndef JUMP_ALIGN
488*38fd1498Szrj #define JUMP_ALIGN(LABEL) align_jumps_log
489*38fd1498Szrj #endif
490*38fd1498Szrj 
491*38fd1498Szrj int
492*38fd1498Szrj default_label_align_after_barrier_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
493*38fd1498Szrj {
494*38fd1498Szrj   return 0;
495*38fd1498Szrj }
496*38fd1498Szrj 
497*38fd1498Szrj int
498*38fd1498Szrj default_loop_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
499*38fd1498Szrj {
500*38fd1498Szrj   return align_loops_max_skip;
501*38fd1498Szrj }
502*38fd1498Szrj 
503*38fd1498Szrj int
504*38fd1498Szrj default_label_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
505*38fd1498Szrj {
506*38fd1498Szrj   return align_labels_max_skip;
507*38fd1498Szrj }
508*38fd1498Szrj 
509*38fd1498Szrj int
510*38fd1498Szrj default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
511*38fd1498Szrj {
512*38fd1498Szrj   return align_jumps_max_skip;
513*38fd1498Szrj }
514*38fd1498Szrj 
515*38fd1498Szrj #ifndef ADDR_VEC_ALIGN
516*38fd1498Szrj static int
517*38fd1498Szrj final_addr_vec_align (rtx_jump_table_data *addr_vec)
518*38fd1498Szrj {
519*38fd1498Szrj   int align = GET_MODE_SIZE (addr_vec->get_data_mode ());
520*38fd1498Szrj 
521*38fd1498Szrj   if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
522*38fd1498Szrj     align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
523*38fd1498Szrj   return exact_log2 (align);
524*38fd1498Szrj 
525*38fd1498Szrj }
526*38fd1498Szrj 
527*38fd1498Szrj #define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC)
528*38fd1498Szrj #endif
529*38fd1498Szrj 
530*38fd1498Szrj #ifndef INSN_LENGTH_ALIGNMENT
531*38fd1498Szrj #define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log
532*38fd1498Szrj #endif
533*38fd1498Szrj 
534*38fd1498Szrj #define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
535*38fd1498Szrj 
536*38fd1498Szrj static int min_labelno, max_labelno;
537*38fd1498Szrj 
538*38fd1498Szrj #define LABEL_TO_ALIGNMENT(LABEL) \
539*38fd1498Szrj   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment)
540*38fd1498Szrj 
541*38fd1498Szrj #define LABEL_TO_MAX_SKIP(LABEL) \
542*38fd1498Szrj   (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip)
543*38fd1498Szrj 
544*38fd1498Szrj /* For the benefit of port specific code do this also as a function.  */
545*38fd1498Szrj 
546*38fd1498Szrj int
547*38fd1498Szrj label_to_alignment (rtx label)
548*38fd1498Szrj {
549*38fd1498Szrj   if (CODE_LABEL_NUMBER (label) <= max_labelno)
550*38fd1498Szrj     return LABEL_TO_ALIGNMENT (label);
551*38fd1498Szrj   return 0;
552*38fd1498Szrj }
553*38fd1498Szrj 
554*38fd1498Szrj int
555*38fd1498Szrj label_to_max_skip (rtx label)
556*38fd1498Szrj {
557*38fd1498Szrj   if (CODE_LABEL_NUMBER (label) <= max_labelno)
558*38fd1498Szrj     return LABEL_TO_MAX_SKIP (label);
559*38fd1498Szrj   return 0;
560*38fd1498Szrj }
561*38fd1498Szrj 
562*38fd1498Szrj /* The differences in addresses
563*38fd1498Szrj    between a branch and its target might grow or shrink depending on
564*38fd1498Szrj    the alignment the start insn of the range (the branch for a forward
565*38fd1498Szrj    branch or the label for a backward branch) starts out on; if these
566*38fd1498Szrj    differences are used naively, they can even oscillate infinitely.
567*38fd1498Szrj    We therefore want to compute a 'worst case' address difference that
568*38fd1498Szrj    is independent of the alignment the start insn of the range end
569*38fd1498Szrj    up on, and that is at least as large as the actual difference.
570*38fd1498Szrj    The function align_fuzz calculates the amount we have to add to the
571*38fd1498Szrj    naively computed difference, by traversing the part of the alignment
572*38fd1498Szrj    chain of the start insn of the range that is in front of the end insn
573*38fd1498Szrj    of the range, and considering for each alignment the maximum amount
574*38fd1498Szrj    that it might contribute to a size increase.
575*38fd1498Szrj 
576*38fd1498Szrj    For casesi tables, we also want to know worst case minimum amounts of
577*38fd1498Szrj    address difference, in case a machine description wants to introduce
578*38fd1498Szrj    some common offset that is added to all offsets in a table.
579*38fd1498Szrj    For this purpose, align_fuzz with a growth argument of 0 computes the
580*38fd1498Szrj    appropriate adjustment.  */
581*38fd1498Szrj 
582*38fd1498Szrj /* Compute the maximum delta by which the difference of the addresses of
583*38fd1498Szrj    START and END might grow / shrink due to a different address for start
584*38fd1498Szrj    which changes the size of alignment insns between START and END.
585*38fd1498Szrj    KNOWN_ALIGN_LOG is the alignment known for START.
586*38fd1498Szrj    GROWTH should be ~0 if the objective is to compute potential code size
587*38fd1498Szrj    increase, and 0 if the objective is to compute potential shrink.
588*38fd1498Szrj    The return value is undefined for any other value of GROWTH.  */
589*38fd1498Szrj 
590*38fd1498Szrj static int
591*38fd1498Szrj align_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth)
592*38fd1498Szrj {
593*38fd1498Szrj   int uid = INSN_UID (start);
594*38fd1498Szrj   rtx align_label;
595*38fd1498Szrj   int known_align = 1 << known_align_log;
596*38fd1498Szrj   int end_shuid = INSN_SHUID (end);
597*38fd1498Szrj   int fuzz = 0;
598*38fd1498Szrj 
599*38fd1498Szrj   for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
600*38fd1498Szrj     {
601*38fd1498Szrj       int align_addr, new_align;
602*38fd1498Szrj 
603*38fd1498Szrj       uid = INSN_UID (align_label);
604*38fd1498Szrj       align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid];
605*38fd1498Szrj       if (uid_shuid[uid] > end_shuid)
606*38fd1498Szrj 	break;
607*38fd1498Szrj       known_align_log = LABEL_TO_ALIGNMENT (align_label);
608*38fd1498Szrj       new_align = 1 << known_align_log;
609*38fd1498Szrj       if (new_align < known_align)
610*38fd1498Szrj 	continue;
611*38fd1498Szrj       fuzz += (-align_addr ^ growth) & (new_align - known_align);
612*38fd1498Szrj       known_align = new_align;
613*38fd1498Szrj     }
614*38fd1498Szrj   return fuzz;
615*38fd1498Szrj }
616*38fd1498Szrj 
617*38fd1498Szrj /* Compute a worst-case reference address of a branch so that it
618*38fd1498Szrj    can be safely used in the presence of aligned labels.  Since the
619*38fd1498Szrj    size of the branch itself is unknown, the size of the branch is
620*38fd1498Szrj    not included in the range.  I.e. for a forward branch, the reference
621*38fd1498Szrj    address is the end address of the branch as known from the previous
622*38fd1498Szrj    branch shortening pass, minus a value to account for possible size
623*38fd1498Szrj    increase due to alignment.  For a backward branch, it is the start
624*38fd1498Szrj    address of the branch as known from the current pass, plus a value
625*38fd1498Szrj    to account for possible size increase due to alignment.
626*38fd1498Szrj    NB.: Therefore, the maximum offset allowed for backward branches needs
627*38fd1498Szrj    to exclude the branch size.  */
628*38fd1498Szrj 
629*38fd1498Szrj int
630*38fd1498Szrj insn_current_reference_address (rtx_insn *branch)
631*38fd1498Szrj {
632*38fd1498Szrj   rtx dest;
633*38fd1498Szrj   int seq_uid;
634*38fd1498Szrj 
635*38fd1498Szrj   if (! INSN_ADDRESSES_SET_P ())
636*38fd1498Szrj     return 0;
637*38fd1498Szrj 
638*38fd1498Szrj   rtx_insn *seq = NEXT_INSN (PREV_INSN (branch));
639*38fd1498Szrj   seq_uid = INSN_UID (seq);
640*38fd1498Szrj   if (!JUMP_P (branch))
641*38fd1498Szrj     /* This can happen for example on the PA; the objective is to know the
642*38fd1498Szrj        offset to address something in front of the start of the function.
643*38fd1498Szrj        Thus, we can treat it like a backward branch.
644*38fd1498Szrj        We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than
645*38fd1498Szrj        any alignment we'd encounter, so we skip the call to align_fuzz.  */
646*38fd1498Szrj     return insn_current_address;
647*38fd1498Szrj   dest = JUMP_LABEL (branch);
648*38fd1498Szrj 
649*38fd1498Szrj   /* BRANCH has no proper alignment chain set, so use SEQ.
650*38fd1498Szrj      BRANCH also has no INSN_SHUID.  */
651*38fd1498Szrj   if (INSN_SHUID (seq) < INSN_SHUID (dest))
652*38fd1498Szrj     {
653*38fd1498Szrj       /* Forward branch.  */
654*38fd1498Szrj       return (insn_last_address + insn_lengths[seq_uid]
655*38fd1498Szrj 	      - align_fuzz (seq, dest, length_unit_log, ~0));
656*38fd1498Szrj     }
657*38fd1498Szrj   else
658*38fd1498Szrj     {
659*38fd1498Szrj       /* Backward branch.  */
660*38fd1498Szrj       return (insn_current_address
661*38fd1498Szrj 	      + align_fuzz (dest, seq, length_unit_log, ~0));
662*38fd1498Szrj     }
663*38fd1498Szrj }
664*38fd1498Szrj 
665*38fd1498Szrj /* Compute branch alignments based on CFG profile.  */
666*38fd1498Szrj 
667*38fd1498Szrj unsigned int
668*38fd1498Szrj compute_alignments (void)
669*38fd1498Szrj {
670*38fd1498Szrj   int log, max_skip, max_log;
671*38fd1498Szrj   basic_block bb;
672*38fd1498Szrj 
673*38fd1498Szrj   if (label_align)
674*38fd1498Szrj     {
675*38fd1498Szrj       free (label_align);
676*38fd1498Szrj       label_align = 0;
677*38fd1498Szrj     }
678*38fd1498Szrj 
679*38fd1498Szrj   max_labelno = max_label_num ();
680*38fd1498Szrj   min_labelno = get_first_label_num ();
681*38fd1498Szrj   label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1);
682*38fd1498Szrj 
683*38fd1498Szrj   /* If not optimizing or optimizing for size, don't assign any alignments.  */
684*38fd1498Szrj   if (! optimize || optimize_function_for_size_p (cfun))
685*38fd1498Szrj     return 0;
686*38fd1498Szrj 
687*38fd1498Szrj   if (dump_file)
688*38fd1498Szrj     {
689*38fd1498Szrj       dump_reg_info (dump_file);
690*38fd1498Szrj       dump_flow_info (dump_file, TDF_DETAILS);
691*38fd1498Szrj       flow_loops_dump (dump_file, NULL, 1);
692*38fd1498Szrj     }
693*38fd1498Szrj   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
694*38fd1498Szrj   profile_count count_threshold = cfun->cfg->count_max.apply_scale
695*38fd1498Szrj 		 (1, PARAM_VALUE (PARAM_ALIGN_THRESHOLD));
696*38fd1498Szrj 
697*38fd1498Szrj   if (dump_file)
698*38fd1498Szrj     {
699*38fd1498Szrj       fprintf (dump_file, "count_max: ");
700*38fd1498Szrj       cfun->cfg->count_max.dump (dump_file);
701*38fd1498Szrj       fprintf (dump_file, "\n");
702*38fd1498Szrj     }
703*38fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
704*38fd1498Szrj     {
705*38fd1498Szrj       rtx_insn *label = BB_HEAD (bb);
706*38fd1498Szrj       bool has_fallthru = 0;
707*38fd1498Szrj       edge e;
708*38fd1498Szrj       edge_iterator ei;
709*38fd1498Szrj 
710*38fd1498Szrj       if (!LABEL_P (label)
711*38fd1498Szrj 	  || optimize_bb_for_size_p (bb))
712*38fd1498Szrj 	{
713*38fd1498Szrj 	  if (dump_file)
714*38fd1498Szrj 	    fprintf (dump_file,
715*38fd1498Szrj 		     "BB %4i loop %2i loop_depth %2i skipped.\n",
716*38fd1498Szrj 		     bb->index,
717*38fd1498Szrj 		     bb->loop_father->num,
718*38fd1498Szrj 		     bb_loop_depth (bb));
719*38fd1498Szrj 	  continue;
720*38fd1498Szrj 	}
721*38fd1498Szrj       max_log = LABEL_ALIGN (label);
722*38fd1498Szrj       max_skip = targetm.asm_out.label_align_max_skip (label);
723*38fd1498Szrj       profile_count fallthru_count = profile_count::zero ();
724*38fd1498Szrj       profile_count branch_count = profile_count::zero ();
725*38fd1498Szrj 
726*38fd1498Szrj       FOR_EACH_EDGE (e, ei, bb->preds)
727*38fd1498Szrj 	{
728*38fd1498Szrj 	  if (e->flags & EDGE_FALLTHRU)
729*38fd1498Szrj 	    has_fallthru = 1, fallthru_count += e->count ();
730*38fd1498Szrj 	  else
731*38fd1498Szrj 	    branch_count += e->count ();
732*38fd1498Szrj 	}
733*38fd1498Szrj       if (dump_file)
734*38fd1498Szrj 	{
735*38fd1498Szrj 	  fprintf (dump_file, "BB %4i loop %2i loop_depth"
736*38fd1498Szrj 		   " %2i fall ",
737*38fd1498Szrj 		   bb->index, bb->loop_father->num,
738*38fd1498Szrj 		   bb_loop_depth (bb));
739*38fd1498Szrj 	  fallthru_count.dump (dump_file);
740*38fd1498Szrj 	  fprintf (dump_file, " branch ");
741*38fd1498Szrj 	  branch_count.dump (dump_file);
742*38fd1498Szrj 	  if (!bb->loop_father->inner && bb->loop_father->num)
743*38fd1498Szrj 	    fprintf (dump_file, " inner_loop");
744*38fd1498Szrj 	  if (bb->loop_father->header == bb)
745*38fd1498Szrj 	    fprintf (dump_file, " loop_header");
746*38fd1498Szrj 	  fprintf (dump_file, "\n");
747*38fd1498Szrj 	}
748*38fd1498Szrj       if (!fallthru_count.initialized_p () || !branch_count.initialized_p ())
749*38fd1498Szrj 	continue;
750*38fd1498Szrj 
751*38fd1498Szrj       /* There are two purposes to align block with no fallthru incoming edge:
752*38fd1498Szrj 	 1) to avoid fetch stalls when branch destination is near cache boundary
753*38fd1498Szrj 	 2) to improve cache efficiency in case the previous block is not executed
754*38fd1498Szrj 	    (so it does not need to be in the cache).
755*38fd1498Szrj 
756*38fd1498Szrj 	 We to catch first case, we align frequently executed blocks.
757*38fd1498Szrj 	 To catch the second, we align blocks that are executed more frequently
758*38fd1498Szrj 	 than the predecessor and the predecessor is likely to not be executed
759*38fd1498Szrj 	 when function is called.  */
760*38fd1498Szrj 
761*38fd1498Szrj       if (!has_fallthru
762*38fd1498Szrj 	  && (branch_count > count_threshold
763*38fd1498Szrj 	      || (bb->count > bb->prev_bb->count.apply_scale (10, 1)
764*38fd1498Szrj 		  && (bb->prev_bb->count
765*38fd1498Szrj 		      <= ENTRY_BLOCK_PTR_FOR_FN (cfun)
766*38fd1498Szrj 			   ->count.apply_scale (1, 2)))))
767*38fd1498Szrj 	{
768*38fd1498Szrj 	  log = JUMP_ALIGN (label);
769*38fd1498Szrj 	  if (dump_file)
770*38fd1498Szrj 	    fprintf (dump_file, "  jump alignment added.\n");
771*38fd1498Szrj 	  if (max_log < log)
772*38fd1498Szrj 	    {
773*38fd1498Szrj 	      max_log = log;
774*38fd1498Szrj 	      max_skip = targetm.asm_out.jump_align_max_skip (label);
775*38fd1498Szrj 	    }
776*38fd1498Szrj 	}
777*38fd1498Szrj       /* In case block is frequent and reached mostly by non-fallthru edge,
778*38fd1498Szrj 	 align it.  It is most likely a first block of loop.  */
779*38fd1498Szrj       if (has_fallthru
780*38fd1498Szrj 	  && !(single_succ_p (bb)
781*38fd1498Szrj 	       && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
782*38fd1498Szrj 	  && optimize_bb_for_speed_p (bb)
783*38fd1498Szrj 	  && branch_count + fallthru_count > count_threshold
784*38fd1498Szrj 	  && (branch_count
785*38fd1498Szrj 	      > fallthru_count.apply_scale
786*38fd1498Szrj 		    (PARAM_VALUE (PARAM_ALIGN_LOOP_ITERATIONS), 1)))
787*38fd1498Szrj 	{
788*38fd1498Szrj 	  log = LOOP_ALIGN (label);
789*38fd1498Szrj 	  if (dump_file)
790*38fd1498Szrj 	    fprintf (dump_file, "  internal loop alignment added.\n");
791*38fd1498Szrj 	  if (max_log < log)
792*38fd1498Szrj 	    {
793*38fd1498Szrj 	      max_log = log;
794*38fd1498Szrj 	      max_skip = targetm.asm_out.loop_align_max_skip (label);
795*38fd1498Szrj 	    }
796*38fd1498Szrj 	}
797*38fd1498Szrj       LABEL_TO_ALIGNMENT (label) = max_log;
798*38fd1498Szrj       LABEL_TO_MAX_SKIP (label) = max_skip;
799*38fd1498Szrj     }
800*38fd1498Szrj 
801*38fd1498Szrj   loop_optimizer_finalize ();
802*38fd1498Szrj   free_dominance_info (CDI_DOMINATORS);
803*38fd1498Szrj   return 0;
804*38fd1498Szrj }
805*38fd1498Szrj 
806*38fd1498Szrj /* Grow the LABEL_ALIGN array after new labels are created.  */
807*38fd1498Szrj 
808*38fd1498Szrj static void
809*38fd1498Szrj grow_label_align (void)
810*38fd1498Szrj {
811*38fd1498Szrj   int old = max_labelno;
812*38fd1498Szrj   int n_labels;
813*38fd1498Szrj   int n_old_labels;
814*38fd1498Szrj 
815*38fd1498Szrj   max_labelno = max_label_num ();
816*38fd1498Szrj 
817*38fd1498Szrj   n_labels = max_labelno - min_labelno + 1;
818*38fd1498Szrj   n_old_labels = old - min_labelno + 1;
819*38fd1498Szrj 
820*38fd1498Szrj   label_align = XRESIZEVEC (struct label_alignment, label_align, n_labels);
821*38fd1498Szrj 
822*38fd1498Szrj   /* Range of labels grows monotonically in the function.  Failing here
823*38fd1498Szrj      means that the initialization of array got lost.  */
824*38fd1498Szrj   gcc_assert (n_old_labels <= n_labels);
825*38fd1498Szrj 
826*38fd1498Szrj   memset (label_align + n_old_labels, 0,
827*38fd1498Szrj           (n_labels - n_old_labels) * sizeof (struct label_alignment));
828*38fd1498Szrj }
829*38fd1498Szrj 
830*38fd1498Szrj /* Update the already computed alignment information.  LABEL_PAIRS is a vector
831*38fd1498Szrj    made up of pairs of labels for which the alignment information of the first
832*38fd1498Szrj    element will be copied from that of the second element.  */
833*38fd1498Szrj 
834*38fd1498Szrj void
835*38fd1498Szrj update_alignments (vec<rtx> &label_pairs)
836*38fd1498Szrj {
837*38fd1498Szrj   unsigned int i = 0;
838*38fd1498Szrj   rtx iter, label = NULL_RTX;
839*38fd1498Szrj 
840*38fd1498Szrj   if (max_labelno != max_label_num ())
841*38fd1498Szrj     grow_label_align ();
842*38fd1498Szrj 
843*38fd1498Szrj   FOR_EACH_VEC_ELT (label_pairs, i, iter)
844*38fd1498Szrj     if (i & 1)
845*38fd1498Szrj       {
846*38fd1498Szrj 	LABEL_TO_ALIGNMENT (label) = LABEL_TO_ALIGNMENT (iter);
847*38fd1498Szrj 	LABEL_TO_MAX_SKIP (label) = LABEL_TO_MAX_SKIP (iter);
848*38fd1498Szrj       }
849*38fd1498Szrj     else
850*38fd1498Szrj       label = iter;
851*38fd1498Szrj }
852*38fd1498Szrj 
853*38fd1498Szrj namespace {
854*38fd1498Szrj 
855*38fd1498Szrj const pass_data pass_data_compute_alignments =
856*38fd1498Szrj {
857*38fd1498Szrj   RTL_PASS, /* type */
858*38fd1498Szrj   "alignments", /* name */
859*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
860*38fd1498Szrj   TV_NONE, /* tv_id */
861*38fd1498Szrj   0, /* properties_required */
862*38fd1498Szrj   0, /* properties_provided */
863*38fd1498Szrj   0, /* properties_destroyed */
864*38fd1498Szrj   0, /* todo_flags_start */
865*38fd1498Szrj   0, /* todo_flags_finish */
866*38fd1498Szrj };
867*38fd1498Szrj 
868*38fd1498Szrj class pass_compute_alignments : public rtl_opt_pass
869*38fd1498Szrj {
870*38fd1498Szrj public:
871*38fd1498Szrj   pass_compute_alignments (gcc::context *ctxt)
872*38fd1498Szrj     : rtl_opt_pass (pass_data_compute_alignments, ctxt)
873*38fd1498Szrj   {}
874*38fd1498Szrj 
875*38fd1498Szrj   /* opt_pass methods: */
876*38fd1498Szrj   virtual unsigned int execute (function *) { return compute_alignments (); }
877*38fd1498Szrj 
878*38fd1498Szrj }; // class pass_compute_alignments
879*38fd1498Szrj 
880*38fd1498Szrj } // anon namespace
881*38fd1498Szrj 
882*38fd1498Szrj rtl_opt_pass *
883*38fd1498Szrj make_pass_compute_alignments (gcc::context *ctxt)
884*38fd1498Szrj {
885*38fd1498Szrj   return new pass_compute_alignments (ctxt);
886*38fd1498Szrj }
887*38fd1498Szrj 
888*38fd1498Szrj 
889*38fd1498Szrj /* Make a pass over all insns and compute their actual lengths by shortening
890*38fd1498Szrj    any branches of variable length if possible.  */
891*38fd1498Szrj 
892*38fd1498Szrj /* shorten_branches might be called multiple times:  for example, the SH
893*38fd1498Szrj    port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG.
894*38fd1498Szrj    In order to do this, it needs proper length information, which it obtains
895*38fd1498Szrj    by calling shorten_branches.  This cannot be collapsed with
896*38fd1498Szrj    shorten_branches itself into a single pass unless we also want to integrate
897*38fd1498Szrj    reorg.c, since the branch splitting exposes new instructions with delay
898*38fd1498Szrj    slots.  */
899*38fd1498Szrj 
900*38fd1498Szrj void
901*38fd1498Szrj shorten_branches (rtx_insn *first)
902*38fd1498Szrj {
903*38fd1498Szrj   rtx_insn *insn;
904*38fd1498Szrj   int max_uid;
905*38fd1498Szrj   int i;
906*38fd1498Szrj   int max_log;
907*38fd1498Szrj   int max_skip;
908*38fd1498Szrj #define MAX_CODE_ALIGN 16
909*38fd1498Szrj   rtx_insn *seq;
910*38fd1498Szrj   int something_changed = 1;
911*38fd1498Szrj   char *varying_length;
912*38fd1498Szrj   rtx body;
913*38fd1498Szrj   int uid;
914*38fd1498Szrj   rtx align_tab[MAX_CODE_ALIGN + 1];
915*38fd1498Szrj 
916*38fd1498Szrj   /* Compute maximum UID and allocate label_align / uid_shuid.  */
917*38fd1498Szrj   max_uid = get_max_uid ();
918*38fd1498Szrj 
919*38fd1498Szrj   /* Free uid_shuid before reallocating it.  */
920*38fd1498Szrj   free (uid_shuid);
921*38fd1498Szrj 
922*38fd1498Szrj   uid_shuid = XNEWVEC (int, max_uid);
923*38fd1498Szrj 
924*38fd1498Szrj   if (max_labelno != max_label_num ())
925*38fd1498Szrj     grow_label_align ();
926*38fd1498Szrj 
927*38fd1498Szrj   /* Initialize label_align and set up uid_shuid to be strictly
928*38fd1498Szrj      monotonically rising with insn order.  */
929*38fd1498Szrj   /* We use max_log here to keep track of the maximum alignment we want to
930*38fd1498Szrj      impose on the next CODE_LABEL (or the current one if we are processing
931*38fd1498Szrj      the CODE_LABEL itself).  */
932*38fd1498Szrj 
933*38fd1498Szrj   max_log = 0;
934*38fd1498Szrj   max_skip = 0;
935*38fd1498Szrj 
936*38fd1498Szrj   for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
937*38fd1498Szrj     {
938*38fd1498Szrj       int log;
939*38fd1498Szrj 
940*38fd1498Szrj       INSN_SHUID (insn) = i++;
941*38fd1498Szrj       if (INSN_P (insn))
942*38fd1498Szrj 	continue;
943*38fd1498Szrj 
944*38fd1498Szrj       if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
945*38fd1498Szrj 	{
946*38fd1498Szrj 	  /* Merge in alignments computed by compute_alignments.  */
947*38fd1498Szrj 	  log = LABEL_TO_ALIGNMENT (label);
948*38fd1498Szrj 	  if (max_log < log)
949*38fd1498Szrj 	    {
950*38fd1498Szrj 	      max_log = log;
951*38fd1498Szrj 	      max_skip = LABEL_TO_MAX_SKIP (label);
952*38fd1498Szrj 	    }
953*38fd1498Szrj 
954*38fd1498Szrj 	  rtx_jump_table_data *table = jump_table_for_label (label);
955*38fd1498Szrj 	  if (!table)
956*38fd1498Szrj 	    {
957*38fd1498Szrj 	      log = LABEL_ALIGN (label);
958*38fd1498Szrj 	      if (max_log < log)
959*38fd1498Szrj 		{
960*38fd1498Szrj 		  max_log = log;
961*38fd1498Szrj 		  max_skip = targetm.asm_out.label_align_max_skip (label);
962*38fd1498Szrj 		}
963*38fd1498Szrj 	    }
964*38fd1498Szrj 	  /* ADDR_VECs only take room if read-only data goes into the text
965*38fd1498Szrj 	     section.  */
966*38fd1498Szrj 	  if ((JUMP_TABLES_IN_TEXT_SECTION
967*38fd1498Szrj 	       || readonly_data_section == text_section)
968*38fd1498Szrj 	      && table)
969*38fd1498Szrj 	    {
970*38fd1498Szrj 	      log = ADDR_VEC_ALIGN (table);
971*38fd1498Szrj 	      if (max_log < log)
972*38fd1498Szrj 		{
973*38fd1498Szrj 		  max_log = log;
974*38fd1498Szrj 		  max_skip = targetm.asm_out.label_align_max_skip (label);
975*38fd1498Szrj 		}
976*38fd1498Szrj 	    }
977*38fd1498Szrj 	  LABEL_TO_ALIGNMENT (label) = max_log;
978*38fd1498Szrj 	  LABEL_TO_MAX_SKIP (label) = max_skip;
979*38fd1498Szrj 	  max_log = 0;
980*38fd1498Szrj 	  max_skip = 0;
981*38fd1498Szrj 	}
982*38fd1498Szrj       else if (BARRIER_P (insn))
983*38fd1498Szrj 	{
984*38fd1498Szrj 	  rtx_insn *label;
985*38fd1498Szrj 
986*38fd1498Szrj 	  for (label = insn; label && ! INSN_P (label);
987*38fd1498Szrj 	       label = NEXT_INSN (label))
988*38fd1498Szrj 	    if (LABEL_P (label))
989*38fd1498Szrj 	      {
990*38fd1498Szrj 		log = LABEL_ALIGN_AFTER_BARRIER (insn);
991*38fd1498Szrj 		if (max_log < log)
992*38fd1498Szrj 		  {
993*38fd1498Szrj 		    max_log = log;
994*38fd1498Szrj 		    max_skip = targetm.asm_out.label_align_after_barrier_max_skip (label);
995*38fd1498Szrj 		  }
996*38fd1498Szrj 		break;
997*38fd1498Szrj 	      }
998*38fd1498Szrj 	}
999*38fd1498Szrj     }
1000*38fd1498Szrj   if (!HAVE_ATTR_length)
1001*38fd1498Szrj     return;
1002*38fd1498Szrj 
1003*38fd1498Szrj   /* Allocate the rest of the arrays.  */
1004*38fd1498Szrj   insn_lengths = XNEWVEC (int, max_uid);
1005*38fd1498Szrj   insn_lengths_max_uid = max_uid;
1006*38fd1498Szrj   /* Syntax errors can lead to labels being outside of the main insn stream.
1007*38fd1498Szrj      Initialize insn_addresses, so that we get reproducible results.  */
1008*38fd1498Szrj   INSN_ADDRESSES_ALLOC (max_uid);
1009*38fd1498Szrj 
1010*38fd1498Szrj   varying_length = XCNEWVEC (char, max_uid);
1011*38fd1498Szrj 
1012*38fd1498Szrj   /* Initialize uid_align.  We scan instructions
1013*38fd1498Szrj      from end to start, and keep in align_tab[n] the last seen insn
1014*38fd1498Szrj      that does an alignment of at least n+1, i.e. the successor
1015*38fd1498Szrj      in the alignment chain for an insn that does / has a known
1016*38fd1498Szrj      alignment of n.  */
1017*38fd1498Szrj   uid_align = XCNEWVEC (rtx, max_uid);
1018*38fd1498Szrj 
1019*38fd1498Szrj   for (i = MAX_CODE_ALIGN + 1; --i >= 0;)
1020*38fd1498Szrj     align_tab[i] = NULL_RTX;
1021*38fd1498Szrj   seq = get_last_insn ();
1022*38fd1498Szrj   for (; seq; seq = PREV_INSN (seq))
1023*38fd1498Szrj     {
1024*38fd1498Szrj       int uid = INSN_UID (seq);
1025*38fd1498Szrj       int log;
1026*38fd1498Szrj       log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0);
1027*38fd1498Szrj       uid_align[uid] = align_tab[0];
1028*38fd1498Szrj       if (log)
1029*38fd1498Szrj 	{
1030*38fd1498Szrj 	  /* Found an alignment label.  */
1031*38fd1498Szrj 	  uid_align[uid] = align_tab[log];
1032*38fd1498Szrj 	  for (i = log - 1; i >= 0; i--)
1033*38fd1498Szrj 	    align_tab[i] = seq;
1034*38fd1498Szrj 	}
1035*38fd1498Szrj     }
1036*38fd1498Szrj 
1037*38fd1498Szrj   /* When optimizing, we start assuming minimum length, and keep increasing
1038*38fd1498Szrj      lengths as we find the need for this, till nothing changes.
1039*38fd1498Szrj      When not optimizing, we start assuming maximum lengths, and
1040*38fd1498Szrj      do a single pass to update the lengths.  */
1041*38fd1498Szrj   bool increasing = optimize != 0;
1042*38fd1498Szrj 
1043*38fd1498Szrj #ifdef CASE_VECTOR_SHORTEN_MODE
1044*38fd1498Szrj   if (optimize)
1045*38fd1498Szrj     {
1046*38fd1498Szrj       /* Look for ADDR_DIFF_VECs, and initialize their minimum and maximum
1047*38fd1498Szrj          label fields.  */
1048*38fd1498Szrj 
1049*38fd1498Szrj       int min_shuid = INSN_SHUID (get_insns ()) - 1;
1050*38fd1498Szrj       int max_shuid = INSN_SHUID (get_last_insn ()) + 1;
1051*38fd1498Szrj       int rel;
1052*38fd1498Szrj 
1053*38fd1498Szrj       for (insn = first; insn != 0; insn = NEXT_INSN (insn))
1054*38fd1498Szrj 	{
1055*38fd1498Szrj 	  rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat;
1056*38fd1498Szrj 	  int len, i, min, max, insn_shuid;
1057*38fd1498Szrj 	  int min_align;
1058*38fd1498Szrj 	  addr_diff_vec_flags flags;
1059*38fd1498Szrj 
1060*38fd1498Szrj 	  if (! JUMP_TABLE_DATA_P (insn)
1061*38fd1498Szrj 	      || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
1062*38fd1498Szrj 	    continue;
1063*38fd1498Szrj 	  pat = PATTERN (insn);
1064*38fd1498Szrj 	  len = XVECLEN (pat, 1);
1065*38fd1498Szrj 	  gcc_assert (len > 0);
1066*38fd1498Szrj 	  min_align = MAX_CODE_ALIGN;
1067*38fd1498Szrj 	  for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
1068*38fd1498Szrj 	    {
1069*38fd1498Szrj 	      rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
1070*38fd1498Szrj 	      int shuid = INSN_SHUID (lab);
1071*38fd1498Szrj 	      if (shuid < min)
1072*38fd1498Szrj 		{
1073*38fd1498Szrj 		  min = shuid;
1074*38fd1498Szrj 		  min_lab = lab;
1075*38fd1498Szrj 		}
1076*38fd1498Szrj 	      if (shuid > max)
1077*38fd1498Szrj 		{
1078*38fd1498Szrj 		  max = shuid;
1079*38fd1498Szrj 		  max_lab = lab;
1080*38fd1498Szrj 		}
1081*38fd1498Szrj 	      if (min_align > LABEL_TO_ALIGNMENT (lab))
1082*38fd1498Szrj 		min_align = LABEL_TO_ALIGNMENT (lab);
1083*38fd1498Szrj 	    }
1084*38fd1498Szrj 	  XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab);
1085*38fd1498Szrj 	  XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab);
1086*38fd1498Szrj 	  insn_shuid = INSN_SHUID (insn);
1087*38fd1498Szrj 	  rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
1088*38fd1498Szrj 	  memset (&flags, 0, sizeof (flags));
1089*38fd1498Szrj 	  flags.min_align = min_align;
1090*38fd1498Szrj 	  flags.base_after_vec = rel > insn_shuid;
1091*38fd1498Szrj 	  flags.min_after_vec  = min > insn_shuid;
1092*38fd1498Szrj 	  flags.max_after_vec  = max > insn_shuid;
1093*38fd1498Szrj 	  flags.min_after_base = min > rel;
1094*38fd1498Szrj 	  flags.max_after_base = max > rel;
1095*38fd1498Szrj 	  ADDR_DIFF_VEC_FLAGS (pat) = flags;
1096*38fd1498Szrj 
1097*38fd1498Szrj 	  if (increasing)
1098*38fd1498Szrj 	    PUT_MODE (pat, CASE_VECTOR_SHORTEN_MODE (0, 0, pat));
1099*38fd1498Szrj 	}
1100*38fd1498Szrj     }
1101*38fd1498Szrj #endif /* CASE_VECTOR_SHORTEN_MODE */
1102*38fd1498Szrj 
1103*38fd1498Szrj   /* Compute initial lengths, addresses, and varying flags for each insn.  */
1104*38fd1498Szrj   int (*length_fun) (rtx_insn *) = increasing ? insn_min_length : insn_default_length;
1105*38fd1498Szrj 
1106*38fd1498Szrj   for (insn_current_address = 0, insn = first;
1107*38fd1498Szrj        insn != 0;
1108*38fd1498Szrj        insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
1109*38fd1498Szrj     {
1110*38fd1498Szrj       uid = INSN_UID (insn);
1111*38fd1498Szrj 
1112*38fd1498Szrj       insn_lengths[uid] = 0;
1113*38fd1498Szrj 
1114*38fd1498Szrj       if (LABEL_P (insn))
1115*38fd1498Szrj 	{
1116*38fd1498Szrj 	  int log = LABEL_TO_ALIGNMENT (insn);
1117*38fd1498Szrj 	  if (log)
1118*38fd1498Szrj 	    {
1119*38fd1498Szrj 	      int align = 1 << log;
1120*38fd1498Szrj 	      int new_address = (insn_current_address + align - 1) & -align;
1121*38fd1498Szrj 	      insn_lengths[uid] = new_address - insn_current_address;
1122*38fd1498Szrj 	    }
1123*38fd1498Szrj 	}
1124*38fd1498Szrj 
1125*38fd1498Szrj       INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
1126*38fd1498Szrj 
1127*38fd1498Szrj       if (NOTE_P (insn) || BARRIER_P (insn)
1128*38fd1498Szrj 	  || LABEL_P (insn) || DEBUG_INSN_P (insn))
1129*38fd1498Szrj 	continue;
1130*38fd1498Szrj       if (insn->deleted ())
1131*38fd1498Szrj 	continue;
1132*38fd1498Szrj 
1133*38fd1498Szrj       body = PATTERN (insn);
1134*38fd1498Szrj       if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
1135*38fd1498Szrj 	{
1136*38fd1498Szrj 	  /* This only takes room if read-only data goes into the text
1137*38fd1498Szrj 	     section.  */
1138*38fd1498Szrj 	  if (JUMP_TABLES_IN_TEXT_SECTION
1139*38fd1498Szrj 	      || readonly_data_section == text_section)
1140*38fd1498Szrj 	    insn_lengths[uid] = (XVECLEN (body,
1141*38fd1498Szrj 					  GET_CODE (body) == ADDR_DIFF_VEC)
1142*38fd1498Szrj 				 * GET_MODE_SIZE (table->get_data_mode ()));
1143*38fd1498Szrj 	  /* Alignment is handled by ADDR_VEC_ALIGN.  */
1144*38fd1498Szrj 	}
1145*38fd1498Szrj       else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
1146*38fd1498Szrj 	insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
1147*38fd1498Szrj       else if (rtx_sequence *body_seq = dyn_cast <rtx_sequence *> (body))
1148*38fd1498Szrj 	{
1149*38fd1498Szrj 	  int i;
1150*38fd1498Szrj 	  int const_delay_slots;
1151*38fd1498Szrj 	  if (DELAY_SLOTS)
1152*38fd1498Szrj 	    const_delay_slots = const_num_delay_slots (body_seq->insn (0));
1153*38fd1498Szrj 	  else
1154*38fd1498Szrj 	    const_delay_slots = 0;
1155*38fd1498Szrj 
1156*38fd1498Szrj 	  int (*inner_length_fun) (rtx_insn *)
1157*38fd1498Szrj 	    = const_delay_slots ? length_fun : insn_default_length;
1158*38fd1498Szrj 	  /* Inside a delay slot sequence, we do not do any branch shortening
1159*38fd1498Szrj 	     if the shortening could change the number of delay slots
1160*38fd1498Szrj 	     of the branch.  */
1161*38fd1498Szrj 	  for (i = 0; i < body_seq->len (); i++)
1162*38fd1498Szrj 	    {
1163*38fd1498Szrj 	      rtx_insn *inner_insn = body_seq->insn (i);
1164*38fd1498Szrj 	      int inner_uid = INSN_UID (inner_insn);
1165*38fd1498Szrj 	      int inner_length;
1166*38fd1498Szrj 
1167*38fd1498Szrj 	      if (GET_CODE (PATTERN (inner_insn)) == ASM_INPUT
1168*38fd1498Szrj 		  || asm_noperands (PATTERN (inner_insn)) >= 0)
1169*38fd1498Szrj 		inner_length = (asm_insn_count (PATTERN (inner_insn))
1170*38fd1498Szrj 				* insn_default_length (inner_insn));
1171*38fd1498Szrj 	      else
1172*38fd1498Szrj 		inner_length = inner_length_fun (inner_insn);
1173*38fd1498Szrj 
1174*38fd1498Szrj 	      insn_lengths[inner_uid] = inner_length;
1175*38fd1498Szrj 	      if (const_delay_slots)
1176*38fd1498Szrj 		{
1177*38fd1498Szrj 		  if ((varying_length[inner_uid]
1178*38fd1498Szrj 		       = insn_variable_length_p (inner_insn)) != 0)
1179*38fd1498Szrj 		    varying_length[uid] = 1;
1180*38fd1498Szrj 		  INSN_ADDRESSES (inner_uid) = (insn_current_address
1181*38fd1498Szrj 						+ insn_lengths[uid]);
1182*38fd1498Szrj 		}
1183*38fd1498Szrj 	      else
1184*38fd1498Szrj 		varying_length[inner_uid] = 0;
1185*38fd1498Szrj 	      insn_lengths[uid] += inner_length;
1186*38fd1498Szrj 	    }
1187*38fd1498Szrj 	}
1188*38fd1498Szrj       else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
1189*38fd1498Szrj 	{
1190*38fd1498Szrj 	  insn_lengths[uid] = length_fun (insn);
1191*38fd1498Szrj 	  varying_length[uid] = insn_variable_length_p (insn);
1192*38fd1498Szrj 	}
1193*38fd1498Szrj 
1194*38fd1498Szrj       /* If needed, do any adjustment.  */
1195*38fd1498Szrj #ifdef ADJUST_INSN_LENGTH
1196*38fd1498Szrj       ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
1197*38fd1498Szrj       if (insn_lengths[uid] < 0)
1198*38fd1498Szrj 	fatal_insn ("negative insn length", insn);
1199*38fd1498Szrj #endif
1200*38fd1498Szrj     }
1201*38fd1498Szrj 
1202*38fd1498Szrj   /* Now loop over all the insns finding varying length insns.  For each,
1203*38fd1498Szrj      get the current insn length.  If it has changed, reflect the change.
1204*38fd1498Szrj      When nothing changes for a full pass, we are done.  */
1205*38fd1498Szrj 
1206*38fd1498Szrj   while (something_changed)
1207*38fd1498Szrj     {
1208*38fd1498Szrj       something_changed = 0;
1209*38fd1498Szrj       insn_current_align = MAX_CODE_ALIGN - 1;
1210*38fd1498Szrj       for (insn_current_address = 0, insn = first;
1211*38fd1498Szrj 	   insn != 0;
1212*38fd1498Szrj 	   insn = NEXT_INSN (insn))
1213*38fd1498Szrj 	{
1214*38fd1498Szrj 	  int new_length;
1215*38fd1498Szrj #ifdef ADJUST_INSN_LENGTH
1216*38fd1498Szrj 	  int tmp_length;
1217*38fd1498Szrj #endif
1218*38fd1498Szrj 	  int length_align;
1219*38fd1498Szrj 
1220*38fd1498Szrj 	  uid = INSN_UID (insn);
1221*38fd1498Szrj 
1222*38fd1498Szrj 	  if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
1223*38fd1498Szrj 	    {
1224*38fd1498Szrj 	      int log = LABEL_TO_ALIGNMENT (label);
1225*38fd1498Szrj 
1226*38fd1498Szrj #ifdef CASE_VECTOR_SHORTEN_MODE
1227*38fd1498Szrj 	      /* If the mode of a following jump table was changed, we
1228*38fd1498Szrj 		 may need to update the alignment of this label.  */
1229*38fd1498Szrj 
1230*38fd1498Szrj 	      if (JUMP_TABLES_IN_TEXT_SECTION
1231*38fd1498Szrj 		  || readonly_data_section == text_section)
1232*38fd1498Szrj 		{
1233*38fd1498Szrj 		  rtx_jump_table_data *table = jump_table_for_label (label);
1234*38fd1498Szrj 		  if (table)
1235*38fd1498Szrj 		    {
1236*38fd1498Szrj 		      int newlog = ADDR_VEC_ALIGN (table);
1237*38fd1498Szrj 		      if (newlog != log)
1238*38fd1498Szrj 			{
1239*38fd1498Szrj 			  log = newlog;
1240*38fd1498Szrj 			  LABEL_TO_ALIGNMENT (insn) = log;
1241*38fd1498Szrj 			  something_changed = 1;
1242*38fd1498Szrj 			}
1243*38fd1498Szrj 		    }
1244*38fd1498Szrj 		}
1245*38fd1498Szrj #endif
1246*38fd1498Szrj 
1247*38fd1498Szrj 	      if (log > insn_current_align)
1248*38fd1498Szrj 		{
1249*38fd1498Szrj 		  int align = 1 << log;
1250*38fd1498Szrj 		  int new_address= (insn_current_address + align - 1) & -align;
1251*38fd1498Szrj 		  insn_lengths[uid] = new_address - insn_current_address;
1252*38fd1498Szrj 		  insn_current_align = log;
1253*38fd1498Szrj 		  insn_current_address = new_address;
1254*38fd1498Szrj 		}
1255*38fd1498Szrj 	      else
1256*38fd1498Szrj 		insn_lengths[uid] = 0;
1257*38fd1498Szrj 	      INSN_ADDRESSES (uid) = insn_current_address;
1258*38fd1498Szrj 	      continue;
1259*38fd1498Szrj 	    }
1260*38fd1498Szrj 
1261*38fd1498Szrj 	  length_align = INSN_LENGTH_ALIGNMENT (insn);
1262*38fd1498Szrj 	  if (length_align < insn_current_align)
1263*38fd1498Szrj 	    insn_current_align = length_align;
1264*38fd1498Szrj 
1265*38fd1498Szrj 	  insn_last_address = INSN_ADDRESSES (uid);
1266*38fd1498Szrj 	  INSN_ADDRESSES (uid) = insn_current_address;
1267*38fd1498Szrj 
1268*38fd1498Szrj #ifdef CASE_VECTOR_SHORTEN_MODE
1269*38fd1498Szrj 	  if (optimize
1270*38fd1498Szrj 	      && JUMP_TABLE_DATA_P (insn)
1271*38fd1498Szrj 	      && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
1272*38fd1498Szrj 	    {
1273*38fd1498Szrj 	      rtx_jump_table_data *table = as_a <rtx_jump_table_data *> (insn);
1274*38fd1498Szrj 	      rtx body = PATTERN (insn);
1275*38fd1498Szrj 	      int old_length = insn_lengths[uid];
1276*38fd1498Szrj 	      rtx_insn *rel_lab =
1277*38fd1498Szrj 		safe_as_a <rtx_insn *> (XEXP (XEXP (body, 0), 0));
1278*38fd1498Szrj 	      rtx min_lab = XEXP (XEXP (body, 2), 0);
1279*38fd1498Szrj 	      rtx max_lab = XEXP (XEXP (body, 3), 0);
1280*38fd1498Szrj 	      int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab));
1281*38fd1498Szrj 	      int min_addr = INSN_ADDRESSES (INSN_UID (min_lab));
1282*38fd1498Szrj 	      int max_addr = INSN_ADDRESSES (INSN_UID (max_lab));
1283*38fd1498Szrj 	      rtx_insn *prev;
1284*38fd1498Szrj 	      int rel_align = 0;
1285*38fd1498Szrj 	      addr_diff_vec_flags flags;
1286*38fd1498Szrj 	      scalar_int_mode vec_mode;
1287*38fd1498Szrj 
1288*38fd1498Szrj 	      /* Avoid automatic aggregate initialization.  */
1289*38fd1498Szrj 	      flags = ADDR_DIFF_VEC_FLAGS (body);
1290*38fd1498Szrj 
1291*38fd1498Szrj 	      /* Try to find a known alignment for rel_lab.  */
1292*38fd1498Szrj 	      for (prev = rel_lab;
1293*38fd1498Szrj 		   prev
1294*38fd1498Szrj 		   && ! insn_lengths[INSN_UID (prev)]
1295*38fd1498Szrj 		   && ! (varying_length[INSN_UID (prev)] & 1);
1296*38fd1498Szrj 		   prev = PREV_INSN (prev))
1297*38fd1498Szrj 		if (varying_length[INSN_UID (prev)] & 2)
1298*38fd1498Szrj 		  {
1299*38fd1498Szrj 		    rel_align = LABEL_TO_ALIGNMENT (prev);
1300*38fd1498Szrj 		    break;
1301*38fd1498Szrj 		  }
1302*38fd1498Szrj 
1303*38fd1498Szrj 	      /* See the comment on addr_diff_vec_flags in rtl.h for the
1304*38fd1498Szrj 		 meaning of the flags values.  base: REL_LAB   vec: INSN  */
1305*38fd1498Szrj 	      /* Anything after INSN has still addresses from the last
1306*38fd1498Szrj 		 pass; adjust these so that they reflect our current
1307*38fd1498Szrj 		 estimate for this pass.  */
1308*38fd1498Szrj 	      if (flags.base_after_vec)
1309*38fd1498Szrj 		rel_addr += insn_current_address - insn_last_address;
1310*38fd1498Szrj 	      if (flags.min_after_vec)
1311*38fd1498Szrj 		min_addr += insn_current_address - insn_last_address;
1312*38fd1498Szrj 	      if (flags.max_after_vec)
1313*38fd1498Szrj 		max_addr += insn_current_address - insn_last_address;
1314*38fd1498Szrj 	      /* We want to know the worst case, i.e. lowest possible value
1315*38fd1498Szrj 		 for the offset of MIN_LAB.  If MIN_LAB is after REL_LAB,
1316*38fd1498Szrj 		 its offset is positive, and we have to be wary of code shrink;
1317*38fd1498Szrj 		 otherwise, it is negative, and we have to be vary of code
1318*38fd1498Szrj 		 size increase.  */
1319*38fd1498Szrj 	      if (flags.min_after_base)
1320*38fd1498Szrj 		{
1321*38fd1498Szrj 		  /* If INSN is between REL_LAB and MIN_LAB, the size
1322*38fd1498Szrj 		     changes we are about to make can change the alignment
1323*38fd1498Szrj 		     within the observed offset, therefore we have to break
1324*38fd1498Szrj 		     it up into two parts that are independent.  */
1325*38fd1498Szrj 		  if (! flags.base_after_vec && flags.min_after_vec)
1326*38fd1498Szrj 		    {
1327*38fd1498Szrj 		      min_addr -= align_fuzz (rel_lab, insn, rel_align, 0);
1328*38fd1498Szrj 		      min_addr -= align_fuzz (insn, min_lab, 0, 0);
1329*38fd1498Szrj 		    }
1330*38fd1498Szrj 		  else
1331*38fd1498Szrj 		    min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0);
1332*38fd1498Szrj 		}
1333*38fd1498Szrj 	      else
1334*38fd1498Szrj 		{
1335*38fd1498Szrj 		  if (flags.base_after_vec && ! flags.min_after_vec)
1336*38fd1498Szrj 		    {
1337*38fd1498Szrj 		      min_addr -= align_fuzz (min_lab, insn, 0, ~0);
1338*38fd1498Szrj 		      min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
1339*38fd1498Szrj 		    }
1340*38fd1498Szrj 		  else
1341*38fd1498Szrj 		    min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0);
1342*38fd1498Szrj 		}
1343*38fd1498Szrj 	      /* Likewise, determine the highest lowest possible value
1344*38fd1498Szrj 		 for the offset of MAX_LAB.  */
1345*38fd1498Szrj 	      if (flags.max_after_base)
1346*38fd1498Szrj 		{
1347*38fd1498Szrj 		  if (! flags.base_after_vec && flags.max_after_vec)
1348*38fd1498Szrj 		    {
1349*38fd1498Szrj 		      max_addr += align_fuzz (rel_lab, insn, rel_align, ~0);
1350*38fd1498Szrj 		      max_addr += align_fuzz (insn, max_lab, 0, ~0);
1351*38fd1498Szrj 		    }
1352*38fd1498Szrj 		  else
1353*38fd1498Szrj 		    max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0);
1354*38fd1498Szrj 		}
1355*38fd1498Szrj 	      else
1356*38fd1498Szrj 		{
1357*38fd1498Szrj 		  if (flags.base_after_vec && ! flags.max_after_vec)
1358*38fd1498Szrj 		    {
1359*38fd1498Szrj 		      max_addr += align_fuzz (max_lab, insn, 0, 0);
1360*38fd1498Szrj 		      max_addr += align_fuzz (insn, rel_lab, 0, 0);
1361*38fd1498Szrj 		    }
1362*38fd1498Szrj 		  else
1363*38fd1498Szrj 		    max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
1364*38fd1498Szrj 		}
1365*38fd1498Szrj 	      vec_mode = CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
1366*38fd1498Szrj 						   max_addr - rel_addr, body);
1367*38fd1498Szrj 	      if (!increasing
1368*38fd1498Szrj 		  || (GET_MODE_SIZE (vec_mode)
1369*38fd1498Szrj 		      >= GET_MODE_SIZE (table->get_data_mode ())))
1370*38fd1498Szrj 		PUT_MODE (body, vec_mode);
1371*38fd1498Szrj 	      if (JUMP_TABLES_IN_TEXT_SECTION
1372*38fd1498Szrj 		  || readonly_data_section == text_section)
1373*38fd1498Szrj 		{
1374*38fd1498Szrj 		  insn_lengths[uid]
1375*38fd1498Szrj 		    = (XVECLEN (body, 1)
1376*38fd1498Szrj 		       * GET_MODE_SIZE (table->get_data_mode ()));
1377*38fd1498Szrj 		  insn_current_address += insn_lengths[uid];
1378*38fd1498Szrj 		  if (insn_lengths[uid] != old_length)
1379*38fd1498Szrj 		    something_changed = 1;
1380*38fd1498Szrj 		}
1381*38fd1498Szrj 
1382*38fd1498Szrj 	      continue;
1383*38fd1498Szrj 	    }
1384*38fd1498Szrj #endif /* CASE_VECTOR_SHORTEN_MODE */
1385*38fd1498Szrj 
1386*38fd1498Szrj 	  if (! (varying_length[uid]))
1387*38fd1498Szrj 	    {
1388*38fd1498Szrj 	      if (NONJUMP_INSN_P (insn)
1389*38fd1498Szrj 		  && GET_CODE (PATTERN (insn)) == SEQUENCE)
1390*38fd1498Szrj 		{
1391*38fd1498Szrj 		  int i;
1392*38fd1498Szrj 
1393*38fd1498Szrj 		  body = PATTERN (insn);
1394*38fd1498Szrj 		  for (i = 0; i < XVECLEN (body, 0); i++)
1395*38fd1498Szrj 		    {
1396*38fd1498Szrj 		      rtx inner_insn = XVECEXP (body, 0, i);
1397*38fd1498Szrj 		      int inner_uid = INSN_UID (inner_insn);
1398*38fd1498Szrj 
1399*38fd1498Szrj 		      INSN_ADDRESSES (inner_uid) = insn_current_address;
1400*38fd1498Szrj 
1401*38fd1498Szrj 		      insn_current_address += insn_lengths[inner_uid];
1402*38fd1498Szrj 		    }
1403*38fd1498Szrj 		}
1404*38fd1498Szrj 	      else
1405*38fd1498Szrj 		insn_current_address += insn_lengths[uid];
1406*38fd1498Szrj 
1407*38fd1498Szrj 	      continue;
1408*38fd1498Szrj 	    }
1409*38fd1498Szrj 
1410*38fd1498Szrj 	  if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
1411*38fd1498Szrj 	    {
1412*38fd1498Szrj 	      rtx_sequence *seqn = as_a <rtx_sequence *> (PATTERN (insn));
1413*38fd1498Szrj 	      int i;
1414*38fd1498Szrj 
1415*38fd1498Szrj 	      body = PATTERN (insn);
1416*38fd1498Szrj 	      new_length = 0;
1417*38fd1498Szrj 	      for (i = 0; i < seqn->len (); i++)
1418*38fd1498Szrj 		{
1419*38fd1498Szrj 		  rtx_insn *inner_insn = seqn->insn (i);
1420*38fd1498Szrj 		  int inner_uid = INSN_UID (inner_insn);
1421*38fd1498Szrj 		  int inner_length;
1422*38fd1498Szrj 
1423*38fd1498Szrj 		  INSN_ADDRESSES (inner_uid) = insn_current_address;
1424*38fd1498Szrj 
1425*38fd1498Szrj 		  /* insn_current_length returns 0 for insns with a
1426*38fd1498Szrj 		     non-varying length.  */
1427*38fd1498Szrj 		  if (! varying_length[inner_uid])
1428*38fd1498Szrj 		    inner_length = insn_lengths[inner_uid];
1429*38fd1498Szrj 		  else
1430*38fd1498Szrj 		    inner_length = insn_current_length (inner_insn);
1431*38fd1498Szrj 
1432*38fd1498Szrj 		  if (inner_length != insn_lengths[inner_uid])
1433*38fd1498Szrj 		    {
1434*38fd1498Szrj 		      if (!increasing || inner_length > insn_lengths[inner_uid])
1435*38fd1498Szrj 			{
1436*38fd1498Szrj 			  insn_lengths[inner_uid] = inner_length;
1437*38fd1498Szrj 			  something_changed = 1;
1438*38fd1498Szrj 			}
1439*38fd1498Szrj 		      else
1440*38fd1498Szrj 			inner_length = insn_lengths[inner_uid];
1441*38fd1498Szrj 		    }
1442*38fd1498Szrj 		  insn_current_address += inner_length;
1443*38fd1498Szrj 		  new_length += inner_length;
1444*38fd1498Szrj 		}
1445*38fd1498Szrj 	    }
1446*38fd1498Szrj 	  else
1447*38fd1498Szrj 	    {
1448*38fd1498Szrj 	      new_length = insn_current_length (insn);
1449*38fd1498Szrj 	      insn_current_address += new_length;
1450*38fd1498Szrj 	    }
1451*38fd1498Szrj 
1452*38fd1498Szrj #ifdef ADJUST_INSN_LENGTH
1453*38fd1498Szrj 	  /* If needed, do any adjustment.  */
1454*38fd1498Szrj 	  tmp_length = new_length;
1455*38fd1498Szrj 	  ADJUST_INSN_LENGTH (insn, new_length);
1456*38fd1498Szrj 	  insn_current_address += (new_length - tmp_length);
1457*38fd1498Szrj #endif
1458*38fd1498Szrj 
1459*38fd1498Szrj 	  if (new_length != insn_lengths[uid]
1460*38fd1498Szrj 	      && (!increasing || new_length > insn_lengths[uid]))
1461*38fd1498Szrj 	    {
1462*38fd1498Szrj 	      insn_lengths[uid] = new_length;
1463*38fd1498Szrj 	      something_changed = 1;
1464*38fd1498Szrj 	    }
1465*38fd1498Szrj 	  else
1466*38fd1498Szrj 	    insn_current_address += insn_lengths[uid] - new_length;
1467*38fd1498Szrj 	}
1468*38fd1498Szrj       /* For a non-optimizing compile, do only a single pass.  */
1469*38fd1498Szrj       if (!increasing)
1470*38fd1498Szrj 	break;
1471*38fd1498Szrj     }
1472*38fd1498Szrj   crtl->max_insn_address = insn_current_address;
1473*38fd1498Szrj   free (varying_length);
1474*38fd1498Szrj }
1475*38fd1498Szrj 
1476*38fd1498Szrj /* Given the body of an INSN known to be generated by an ASM statement, return
1477*38fd1498Szrj    the number of machine instructions likely to be generated for this insn.
1478*38fd1498Szrj    This is used to compute its length.  */
1479*38fd1498Szrj 
1480*38fd1498Szrj static int
1481*38fd1498Szrj asm_insn_count (rtx body)
1482*38fd1498Szrj {
1483*38fd1498Szrj   const char *templ;
1484*38fd1498Szrj 
1485*38fd1498Szrj   if (GET_CODE (body) == ASM_INPUT)
1486*38fd1498Szrj     templ = XSTR (body, 0);
1487*38fd1498Szrj   else
1488*38fd1498Szrj     templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
1489*38fd1498Szrj 
1490*38fd1498Szrj   return asm_str_count (templ);
1491*38fd1498Szrj }
1492*38fd1498Szrj 
1493*38fd1498Szrj /* Return the number of machine instructions likely to be generated for the
1494*38fd1498Szrj    inline-asm template. */
1495*38fd1498Szrj int
1496*38fd1498Szrj asm_str_count (const char *templ)
1497*38fd1498Szrj {
1498*38fd1498Szrj   int count = 1;
1499*38fd1498Szrj 
1500*38fd1498Szrj   if (!*templ)
1501*38fd1498Szrj     return 0;
1502*38fd1498Szrj 
1503*38fd1498Szrj   for (; *templ; templ++)
1504*38fd1498Szrj     if (IS_ASM_LOGICAL_LINE_SEPARATOR (*templ, templ)
1505*38fd1498Szrj 	|| *templ == '\n')
1506*38fd1498Szrj       count++;
1507*38fd1498Szrj 
1508*38fd1498Szrj   return count;
1509*38fd1498Szrj }
1510*38fd1498Szrj 
1511*38fd1498Szrj /* Return true if DWARF2 debug info can be emitted for DECL.  */
1512*38fd1498Szrj 
1513*38fd1498Szrj static bool
1514*38fd1498Szrj dwarf2_debug_info_emitted_p (tree decl)
1515*38fd1498Szrj {
1516*38fd1498Szrj   if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
1517*38fd1498Szrj     return false;
1518*38fd1498Szrj 
1519*38fd1498Szrj   if (DECL_IGNORED_P (decl))
1520*38fd1498Szrj     return false;
1521*38fd1498Szrj 
1522*38fd1498Szrj   return true;
1523*38fd1498Szrj }
1524*38fd1498Szrj 
1525*38fd1498Szrj /* Return scope resulting from combination of S1 and S2.  */
1526*38fd1498Szrj static tree
1527*38fd1498Szrj choose_inner_scope (tree s1, tree s2)
1528*38fd1498Szrj {
1529*38fd1498Szrj    if (!s1)
1530*38fd1498Szrj      return s2;
1531*38fd1498Szrj    if (!s2)
1532*38fd1498Szrj      return s1;
1533*38fd1498Szrj    if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
1534*38fd1498Szrj      return s1;
1535*38fd1498Szrj    return s2;
1536*38fd1498Szrj }
1537*38fd1498Szrj 
1538*38fd1498Szrj /* Emit lexical block notes needed to change scope from S1 to S2.  */
1539*38fd1498Szrj 
1540*38fd1498Szrj static void
1541*38fd1498Szrj change_scope (rtx_insn *orig_insn, tree s1, tree s2)
1542*38fd1498Szrj {
1543*38fd1498Szrj   rtx_insn *insn = orig_insn;
1544*38fd1498Szrj   tree com = NULL_TREE;
1545*38fd1498Szrj   tree ts1 = s1, ts2 = s2;
1546*38fd1498Szrj   tree s;
1547*38fd1498Szrj 
1548*38fd1498Szrj   while (ts1 != ts2)
1549*38fd1498Szrj     {
1550*38fd1498Szrj       gcc_assert (ts1 && ts2);
1551*38fd1498Szrj       if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
1552*38fd1498Szrj 	ts1 = BLOCK_SUPERCONTEXT (ts1);
1553*38fd1498Szrj       else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
1554*38fd1498Szrj 	ts2 = BLOCK_SUPERCONTEXT (ts2);
1555*38fd1498Szrj       else
1556*38fd1498Szrj 	{
1557*38fd1498Szrj 	  ts1 = BLOCK_SUPERCONTEXT (ts1);
1558*38fd1498Szrj 	  ts2 = BLOCK_SUPERCONTEXT (ts2);
1559*38fd1498Szrj 	}
1560*38fd1498Szrj     }
1561*38fd1498Szrj   com = ts1;
1562*38fd1498Szrj 
1563*38fd1498Szrj   /* Close scopes.  */
1564*38fd1498Szrj   s = s1;
1565*38fd1498Szrj   while (s != com)
1566*38fd1498Szrj     {
1567*38fd1498Szrj       rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
1568*38fd1498Szrj       NOTE_BLOCK (note) = s;
1569*38fd1498Szrj       s = BLOCK_SUPERCONTEXT (s);
1570*38fd1498Szrj     }
1571*38fd1498Szrj 
1572*38fd1498Szrj   /* Open scopes.  */
1573*38fd1498Szrj   s = s2;
1574*38fd1498Szrj   while (s != com)
1575*38fd1498Szrj     {
1576*38fd1498Szrj       insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
1577*38fd1498Szrj       NOTE_BLOCK (insn) = s;
1578*38fd1498Szrj       s = BLOCK_SUPERCONTEXT (s);
1579*38fd1498Szrj     }
1580*38fd1498Szrj }
1581*38fd1498Szrj 
1582*38fd1498Szrj /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
1583*38fd1498Szrj    on the scope tree and the newly reordered instructions.  */
1584*38fd1498Szrj 
1585*38fd1498Szrj static void
1586*38fd1498Szrj reemit_insn_block_notes (void)
1587*38fd1498Szrj {
1588*38fd1498Szrj   tree cur_block = DECL_INITIAL (cfun->decl);
1589*38fd1498Szrj   rtx_insn *insn;
1590*38fd1498Szrj 
1591*38fd1498Szrj   insn = get_insns ();
1592*38fd1498Szrj   for (; insn; insn = NEXT_INSN (insn))
1593*38fd1498Szrj     {
1594*38fd1498Szrj       tree this_block;
1595*38fd1498Szrj 
1596*38fd1498Szrj       /* Prevent lexical blocks from straddling section boundaries.  */
1597*38fd1498Szrj       if (NOTE_P (insn))
1598*38fd1498Szrj 	switch (NOTE_KIND (insn))
1599*38fd1498Szrj 	  {
1600*38fd1498Szrj 	  case NOTE_INSN_SWITCH_TEXT_SECTIONS:
1601*38fd1498Szrj 	    {
1602*38fd1498Szrj 	      for (tree s = cur_block; s != DECL_INITIAL (cfun->decl);
1603*38fd1498Szrj 		   s = BLOCK_SUPERCONTEXT (s))
1604*38fd1498Szrj 		{
1605*38fd1498Szrj 		  rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
1606*38fd1498Szrj 		  NOTE_BLOCK (note) = s;
1607*38fd1498Szrj 		  note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn);
1608*38fd1498Szrj 		  NOTE_BLOCK (note) = s;
1609*38fd1498Szrj 		}
1610*38fd1498Szrj 	    }
1611*38fd1498Szrj 	    break;
1612*38fd1498Szrj 
1613*38fd1498Szrj 	  case NOTE_INSN_BEGIN_STMT:
1614*38fd1498Szrj 	  case NOTE_INSN_INLINE_ENTRY:
1615*38fd1498Szrj 	    this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn));
1616*38fd1498Szrj 	    goto set_cur_block_to_this_block;
1617*38fd1498Szrj 
1618*38fd1498Szrj 	  default:
1619*38fd1498Szrj 	    continue;
1620*38fd1498Szrj 	}
1621*38fd1498Szrj 
1622*38fd1498Szrj       if (!active_insn_p (insn))
1623*38fd1498Szrj         continue;
1624*38fd1498Szrj 
1625*38fd1498Szrj       /* Avoid putting scope notes between jump table and its label.  */
1626*38fd1498Szrj       if (JUMP_TABLE_DATA_P (insn))
1627*38fd1498Szrj 	continue;
1628*38fd1498Szrj 
1629*38fd1498Szrj       this_block = insn_scope (insn);
1630*38fd1498Szrj       /* For sequences compute scope resulting from merging all scopes
1631*38fd1498Szrj 	 of instructions nested inside.  */
1632*38fd1498Szrj       if (rtx_sequence *body = dyn_cast <rtx_sequence *> (PATTERN (insn)))
1633*38fd1498Szrj 	{
1634*38fd1498Szrj 	  int i;
1635*38fd1498Szrj 
1636*38fd1498Szrj 	  this_block = NULL;
1637*38fd1498Szrj 	  for (i = 0; i < body->len (); i++)
1638*38fd1498Szrj 	    this_block = choose_inner_scope (this_block,
1639*38fd1498Szrj 					     insn_scope (body->insn (i)));
1640*38fd1498Szrj 	}
1641*38fd1498Szrj     set_cur_block_to_this_block:
1642*38fd1498Szrj       if (! this_block)
1643*38fd1498Szrj 	{
1644*38fd1498Szrj 	  if (INSN_LOCATION (insn) == UNKNOWN_LOCATION)
1645*38fd1498Szrj 	    continue;
1646*38fd1498Szrj 	  else
1647*38fd1498Szrj 	    this_block = DECL_INITIAL (cfun->decl);
1648*38fd1498Szrj 	}
1649*38fd1498Szrj 
1650*38fd1498Szrj       if (this_block != cur_block)
1651*38fd1498Szrj 	{
1652*38fd1498Szrj 	  change_scope (insn, cur_block, this_block);
1653*38fd1498Szrj 	  cur_block = this_block;
1654*38fd1498Szrj 	}
1655*38fd1498Szrj     }
1656*38fd1498Szrj 
1657*38fd1498Szrj   /* change_scope emits before the insn, not after.  */
1658*38fd1498Szrj   rtx_note *note = emit_note (NOTE_INSN_DELETED);
1659*38fd1498Szrj   change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
1660*38fd1498Szrj   delete_insn (note);
1661*38fd1498Szrj 
1662*38fd1498Szrj   reorder_blocks ();
1663*38fd1498Szrj }
1664*38fd1498Szrj 
1665*38fd1498Szrj static const char *some_local_dynamic_name;
1666*38fd1498Szrj 
1667*38fd1498Szrj /* Locate some local-dynamic symbol still in use by this function
1668*38fd1498Szrj    so that we can print its name in local-dynamic base patterns.
1669*38fd1498Szrj    Return null if there are no local-dynamic references.  */
1670*38fd1498Szrj 
1671*38fd1498Szrj const char *
1672*38fd1498Szrj get_some_local_dynamic_name ()
1673*38fd1498Szrj {
1674*38fd1498Szrj   subrtx_iterator::array_type array;
1675*38fd1498Szrj   rtx_insn *insn;
1676*38fd1498Szrj 
1677*38fd1498Szrj   if (some_local_dynamic_name)
1678*38fd1498Szrj     return some_local_dynamic_name;
1679*38fd1498Szrj 
1680*38fd1498Szrj   for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
1681*38fd1498Szrj     if (NONDEBUG_INSN_P (insn))
1682*38fd1498Szrj       FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
1683*38fd1498Szrj 	{
1684*38fd1498Szrj 	  const_rtx x = *iter;
1685*38fd1498Szrj 	  if (GET_CODE (x) == SYMBOL_REF)
1686*38fd1498Szrj 	    {
1687*38fd1498Szrj 	      if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
1688*38fd1498Szrj 		return some_local_dynamic_name = XSTR (x, 0);
1689*38fd1498Szrj 	      if (CONSTANT_POOL_ADDRESS_P (x))
1690*38fd1498Szrj 		iter.substitute (get_pool_constant (x));
1691*38fd1498Szrj 	    }
1692*38fd1498Szrj 	}
1693*38fd1498Szrj 
1694*38fd1498Szrj   return 0;
1695*38fd1498Szrj }
1696*38fd1498Szrj 
1697*38fd1498Szrj /* Arrange for us to emit a source location note before any further
1698*38fd1498Szrj    real insns or section changes, by setting the SEEN_NEXT_VIEW bit in
1699*38fd1498Szrj    *SEEN, as long as we are keeping track of location views.  The bit
1700*38fd1498Szrj    indicates we have referenced the next view at the current PC, so we
1701*38fd1498Szrj    have to emit it.  This should be called next to the var_location
1702*38fd1498Szrj    debug hook.  */
1703*38fd1498Szrj 
1704*38fd1498Szrj static inline void
1705*38fd1498Szrj set_next_view_needed (int *seen)
1706*38fd1498Szrj {
1707*38fd1498Szrj   if (debug_variable_location_views)
1708*38fd1498Szrj     *seen |= SEEN_NEXT_VIEW;
1709*38fd1498Szrj }
1710*38fd1498Szrj 
1711*38fd1498Szrj /* Clear the flag in *SEEN indicating we need to emit the next view.
1712*38fd1498Szrj    This should be called next to the source_line debug hook.  */
1713*38fd1498Szrj 
1714*38fd1498Szrj static inline void
1715*38fd1498Szrj clear_next_view_needed (int *seen)
1716*38fd1498Szrj {
1717*38fd1498Szrj   *seen &= ~SEEN_NEXT_VIEW;
1718*38fd1498Szrj }
1719*38fd1498Szrj 
1720*38fd1498Szrj /* Test whether we have a pending request to emit the next view in
1721*38fd1498Szrj    *SEEN, and emit it if needed, clearing the request bit.  */
1722*38fd1498Szrj 
1723*38fd1498Szrj static inline void
1724*38fd1498Szrj maybe_output_next_view (int *seen)
1725*38fd1498Szrj {
1726*38fd1498Szrj   if ((*seen & SEEN_NEXT_VIEW) != 0)
1727*38fd1498Szrj     {
1728*38fd1498Szrj       clear_next_view_needed (seen);
1729*38fd1498Szrj       (*debug_hooks->source_line) (last_linenum, last_columnnum,
1730*38fd1498Szrj 				   last_filename, last_discriminator,
1731*38fd1498Szrj 				   false);
1732*38fd1498Szrj     }
1733*38fd1498Szrj }
1734*38fd1498Szrj 
1735*38fd1498Szrj /* We want to emit param bindings (before the first begin_stmt) in the
1736*38fd1498Szrj    initial view, if we are emitting views.  To that end, we may
1737*38fd1498Szrj    consume initial notes in the function, processing them in
1738*38fd1498Szrj    final_start_function, before signaling the beginning of the
1739*38fd1498Szrj    prologue, rather than in final.
1740*38fd1498Szrj 
1741*38fd1498Szrj    We don't test whether the DECLs are PARM_DECLs: the assumption is
1742*38fd1498Szrj    that there will be a NOTE_INSN_BEGIN_STMT marker before any
1743*38fd1498Szrj    non-parameter NOTE_INSN_VAR_LOCATION.  It's ok if the marker is not
1744*38fd1498Szrj    there, we'll just have more variable locations bound in the initial
1745*38fd1498Szrj    view, which is consistent with their being bound without any code
1746*38fd1498Szrj    that would give them a value.  */
1747*38fd1498Szrj 
1748*38fd1498Szrj static inline bool
1749*38fd1498Szrj in_initial_view_p (rtx_insn *insn)
1750*38fd1498Szrj {
1751*38fd1498Szrj   return (!DECL_IGNORED_P (current_function_decl)
1752*38fd1498Szrj 	  && debug_variable_location_views
1753*38fd1498Szrj 	  && insn && GET_CODE (insn) == NOTE
1754*38fd1498Szrj 	  && (NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
1755*38fd1498Szrj 	      || NOTE_KIND (insn) == NOTE_INSN_DELETED));
1756*38fd1498Szrj }
1757*38fd1498Szrj 
1758*38fd1498Szrj /* Output assembler code for the start of a function,
1759*38fd1498Szrj    and initialize some of the variables in this file
1760*38fd1498Szrj    for the new function.  The label for the function and associated
1761*38fd1498Szrj    assembler pseudo-ops have already been output in `assemble_start_function'.
1762*38fd1498Szrj 
1763*38fd1498Szrj    FIRST is the first insn of the rtl for the function being compiled.
1764*38fd1498Szrj    FILE is the file to write assembler code to.
1765*38fd1498Szrj    SEEN should be initially set to zero, and it may be updated to
1766*38fd1498Szrj    indicate we have references to the next location view, that would
1767*38fd1498Szrj    require us to emit it at the current PC.
1768*38fd1498Szrj    OPTIMIZE_P is nonzero if we should eliminate redundant
1769*38fd1498Szrj      test and compare insns.  */
1770*38fd1498Szrj 
1771*38fd1498Szrj static void
1772*38fd1498Szrj final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
1773*38fd1498Szrj 			int optimize_p ATTRIBUTE_UNUSED)
1774*38fd1498Szrj {
1775*38fd1498Szrj   block_depth = 0;
1776*38fd1498Szrj 
1777*38fd1498Szrj   this_is_asm_operands = 0;
1778*38fd1498Szrj 
1779*38fd1498Szrj   need_profile_function = false;
1780*38fd1498Szrj 
1781*38fd1498Szrj   last_filename = LOCATION_FILE (prologue_location);
1782*38fd1498Szrj   last_linenum = LOCATION_LINE (prologue_location);
1783*38fd1498Szrj   last_columnnum = LOCATION_COLUMN (prologue_location);
1784*38fd1498Szrj   last_discriminator = discriminator = 0;
1785*38fd1498Szrj 
1786*38fd1498Szrj   high_block_linenum = high_function_linenum = last_linenum;
1787*38fd1498Szrj 
1788*38fd1498Szrj   if (flag_sanitize & SANITIZE_ADDRESS)
1789*38fd1498Szrj     asan_function_start ();
1790*38fd1498Szrj 
1791*38fd1498Szrj   rtx_insn *first = *firstp;
1792*38fd1498Szrj   if (in_initial_view_p (first))
1793*38fd1498Szrj     {
1794*38fd1498Szrj       do
1795*38fd1498Szrj 	{
1796*38fd1498Szrj 	  final_scan_insn (first, file, 0, 0, seen);
1797*38fd1498Szrj 	  first = NEXT_INSN (first);
1798*38fd1498Szrj 	}
1799*38fd1498Szrj       while (in_initial_view_p (first));
1800*38fd1498Szrj       *firstp = first;
1801*38fd1498Szrj     }
1802*38fd1498Szrj 
1803*38fd1498Szrj   if (!DECL_IGNORED_P (current_function_decl))
1804*38fd1498Szrj     debug_hooks->begin_prologue (last_linenum, last_columnnum,
1805*38fd1498Szrj 				 last_filename);
1806*38fd1498Szrj 
1807*38fd1498Szrj   if (!dwarf2_debug_info_emitted_p (current_function_decl))
1808*38fd1498Szrj     dwarf2out_begin_prologue (0, 0, NULL);
1809*38fd1498Szrj 
1810*38fd1498Szrj #ifdef LEAF_REG_REMAP
1811*38fd1498Szrj   if (crtl->uses_only_leaf_regs)
1812*38fd1498Szrj     leaf_renumber_regs (first);
1813*38fd1498Szrj #endif
1814*38fd1498Szrj 
1815*38fd1498Szrj   /* The Sun386i and perhaps other machines don't work right
1816*38fd1498Szrj      if the profiling code comes after the prologue.  */
1817*38fd1498Szrj   if (targetm.profile_before_prologue () && crtl->profile)
1818*38fd1498Szrj     {
1819*38fd1498Szrj       if (targetm.asm_out.function_prologue == default_function_pro_epilogue
1820*38fd1498Szrj 	  && targetm.have_prologue ())
1821*38fd1498Szrj 	{
1822*38fd1498Szrj 	  rtx_insn *insn;
1823*38fd1498Szrj 	  for (insn = first; insn; insn = NEXT_INSN (insn))
1824*38fd1498Szrj 	    if (!NOTE_P (insn))
1825*38fd1498Szrj 	      {
1826*38fd1498Szrj 		insn = NULL;
1827*38fd1498Szrj 		break;
1828*38fd1498Szrj 	      }
1829*38fd1498Szrj 	    else if (NOTE_KIND (insn) == NOTE_INSN_BASIC_BLOCK
1830*38fd1498Szrj 		     || NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
1831*38fd1498Szrj 	      break;
1832*38fd1498Szrj 	    else if (NOTE_KIND (insn) == NOTE_INSN_DELETED
1833*38fd1498Szrj 		     || NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
1834*38fd1498Szrj 	      continue;
1835*38fd1498Szrj 	    else
1836*38fd1498Szrj 	      {
1837*38fd1498Szrj 		insn = NULL;
1838*38fd1498Szrj 		break;
1839*38fd1498Szrj 	      }
1840*38fd1498Szrj 
1841*38fd1498Szrj 	  if (insn)
1842*38fd1498Szrj 	    need_profile_function = true;
1843*38fd1498Szrj 	  else
1844*38fd1498Szrj 	    profile_function (file);
1845*38fd1498Szrj 	}
1846*38fd1498Szrj       else
1847*38fd1498Szrj 	profile_function (file);
1848*38fd1498Szrj     }
1849*38fd1498Szrj 
1850*38fd1498Szrj   /* If debugging, assign block numbers to all of the blocks in this
1851*38fd1498Szrj      function.  */
1852*38fd1498Szrj   if (write_symbols)
1853*38fd1498Szrj     {
1854*38fd1498Szrj       reemit_insn_block_notes ();
1855*38fd1498Szrj       number_blocks (current_function_decl);
1856*38fd1498Szrj       /* We never actually put out begin/end notes for the top-level
1857*38fd1498Szrj 	 block in the function.  But, conceptually, that block is
1858*38fd1498Szrj 	 always needed.  */
1859*38fd1498Szrj       TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
1860*38fd1498Szrj     }
1861*38fd1498Szrj 
1862*38fd1498Szrj   HOST_WIDE_INT min_frame_size = constant_lower_bound (get_frame_size ());
1863*38fd1498Szrj   if (warn_frame_larger_than
1864*38fd1498Szrj       && min_frame_size > frame_larger_than_size)
1865*38fd1498Szrj     {
1866*38fd1498Szrj       /* Issue a warning */
1867*38fd1498Szrj       warning (OPT_Wframe_larger_than_,
1868*38fd1498Szrj 	       "the frame size of %wd bytes is larger than %wd bytes",
1869*38fd1498Szrj 	       min_frame_size, frame_larger_than_size);
1870*38fd1498Szrj     }
1871*38fd1498Szrj 
1872*38fd1498Szrj   /* First output the function prologue: code to set up the stack frame.  */
1873*38fd1498Szrj   targetm.asm_out.function_prologue (file);
1874*38fd1498Szrj 
1875*38fd1498Szrj   /* If the machine represents the prologue as RTL, the profiling code must
1876*38fd1498Szrj      be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
1877*38fd1498Szrj   if (! targetm.have_prologue ())
1878*38fd1498Szrj     profile_after_prologue (file);
1879*38fd1498Szrj }
1880*38fd1498Szrj 
1881*38fd1498Szrj /* This is an exported final_start_function_1, callable without SEEN.  */
1882*38fd1498Szrj 
1883*38fd1498Szrj void
1884*38fd1498Szrj final_start_function (rtx_insn *first, FILE *file,
1885*38fd1498Szrj 		      int optimize_p ATTRIBUTE_UNUSED)
1886*38fd1498Szrj {
1887*38fd1498Szrj   int seen = 0;
1888*38fd1498Szrj   final_start_function_1 (&first, file, &seen, optimize_p);
1889*38fd1498Szrj   gcc_assert (seen == 0);
1890*38fd1498Szrj }
1891*38fd1498Szrj 
1892*38fd1498Szrj static void
1893*38fd1498Szrj profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
1894*38fd1498Szrj {
1895*38fd1498Szrj   if (!targetm.profile_before_prologue () && crtl->profile)
1896*38fd1498Szrj     profile_function (file);
1897*38fd1498Szrj }
1898*38fd1498Szrj 
1899*38fd1498Szrj static void
1900*38fd1498Szrj profile_function (FILE *file ATTRIBUTE_UNUSED)
1901*38fd1498Szrj {
1902*38fd1498Szrj #ifndef NO_PROFILE_COUNTERS
1903*38fd1498Szrj # define NO_PROFILE_COUNTERS	0
1904*38fd1498Szrj #endif
1905*38fd1498Szrj #ifdef ASM_OUTPUT_REG_PUSH
1906*38fd1498Szrj   rtx sval = NULL, chain = NULL;
1907*38fd1498Szrj 
1908*38fd1498Szrj   if (cfun->returns_struct)
1909*38fd1498Szrj     sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl),
1910*38fd1498Szrj 					   true);
1911*38fd1498Szrj   if (cfun->static_chain_decl)
1912*38fd1498Szrj     chain = targetm.calls.static_chain (current_function_decl, true);
1913*38fd1498Szrj #endif /* ASM_OUTPUT_REG_PUSH */
1914*38fd1498Szrj 
1915*38fd1498Szrj   if (! NO_PROFILE_COUNTERS)
1916*38fd1498Szrj     {
1917*38fd1498Szrj       int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
1918*38fd1498Szrj       switch_to_section (data_section);
1919*38fd1498Szrj       ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
1920*38fd1498Szrj       targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
1921*38fd1498Szrj       assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
1922*38fd1498Szrj     }
1923*38fd1498Szrj 
1924*38fd1498Szrj   switch_to_section (current_function_section ());
1925*38fd1498Szrj 
1926*38fd1498Szrj #ifdef ASM_OUTPUT_REG_PUSH
1927*38fd1498Szrj   if (sval && REG_P (sval))
1928*38fd1498Szrj     ASM_OUTPUT_REG_PUSH (file, REGNO (sval));
1929*38fd1498Szrj   if (chain && REG_P (chain))
1930*38fd1498Szrj     ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
1931*38fd1498Szrj #endif
1932*38fd1498Szrj 
1933*38fd1498Szrj   FUNCTION_PROFILER (file, current_function_funcdef_no);
1934*38fd1498Szrj 
1935*38fd1498Szrj #ifdef ASM_OUTPUT_REG_PUSH
1936*38fd1498Szrj   if (chain && REG_P (chain))
1937*38fd1498Szrj     ASM_OUTPUT_REG_POP (file, REGNO (chain));
1938*38fd1498Szrj   if (sval && REG_P (sval))
1939*38fd1498Szrj     ASM_OUTPUT_REG_POP (file, REGNO (sval));
1940*38fd1498Szrj #endif
1941*38fd1498Szrj }
1942*38fd1498Szrj 
1943*38fd1498Szrj /* Output assembler code for the end of a function.
1944*38fd1498Szrj    For clarity, args are same as those of `final_start_function'
1945*38fd1498Szrj    even though not all of them are needed.  */
1946*38fd1498Szrj 
1947*38fd1498Szrj void
1948*38fd1498Szrj final_end_function (void)
1949*38fd1498Szrj {
1950*38fd1498Szrj   app_disable ();
1951*38fd1498Szrj 
1952*38fd1498Szrj   if (!DECL_IGNORED_P (current_function_decl))
1953*38fd1498Szrj     debug_hooks->end_function (high_function_linenum);
1954*38fd1498Szrj 
1955*38fd1498Szrj   /* Finally, output the function epilogue:
1956*38fd1498Szrj      code to restore the stack frame and return to the caller.  */
1957*38fd1498Szrj   targetm.asm_out.function_epilogue (asm_out_file);
1958*38fd1498Szrj 
1959*38fd1498Szrj   /* And debug output.  */
1960*38fd1498Szrj   if (!DECL_IGNORED_P (current_function_decl))
1961*38fd1498Szrj     debug_hooks->end_epilogue (last_linenum, last_filename);
1962*38fd1498Szrj 
1963*38fd1498Szrj   if (!dwarf2_debug_info_emitted_p (current_function_decl)
1964*38fd1498Szrj       && dwarf2out_do_frame ())
1965*38fd1498Szrj     dwarf2out_end_epilogue (last_linenum, last_filename);
1966*38fd1498Szrj 
1967*38fd1498Szrj   some_local_dynamic_name = 0;
1968*38fd1498Szrj }
1969*38fd1498Szrj 
1970*38fd1498Szrj 
1971*38fd1498Szrj /* Dumper helper for basic block information. FILE is the assembly
1972*38fd1498Szrj    output file, and INSN is the instruction being emitted.  */
1973*38fd1498Szrj 
1974*38fd1498Szrj static void
1975*38fd1498Szrj dump_basic_block_info (FILE *file, rtx_insn *insn, basic_block *start_to_bb,
1976*38fd1498Szrj                        basic_block *end_to_bb, int bb_map_size, int *bb_seqn)
1977*38fd1498Szrj {
1978*38fd1498Szrj   basic_block bb;
1979*38fd1498Szrj 
1980*38fd1498Szrj   if (!flag_debug_asm)
1981*38fd1498Szrj     return;
1982*38fd1498Szrj 
1983*38fd1498Szrj   if (INSN_UID (insn) < bb_map_size
1984*38fd1498Szrj       && (bb = start_to_bb[INSN_UID (insn)]) != NULL)
1985*38fd1498Szrj     {
1986*38fd1498Szrj       edge e;
1987*38fd1498Szrj       edge_iterator ei;
1988*38fd1498Szrj 
1989*38fd1498Szrj       fprintf (file, "%s BLOCK %d", ASM_COMMENT_START, bb->index);
1990*38fd1498Szrj       if (bb->count.initialized_p ())
1991*38fd1498Szrj 	{
1992*38fd1498Szrj           fprintf (file, ", count:");
1993*38fd1498Szrj 	  bb->count.dump (file);
1994*38fd1498Szrj 	}
1995*38fd1498Szrj       fprintf (file, " seq:%d", (*bb_seqn)++);
1996*38fd1498Szrj       fprintf (file, "\n%s PRED:", ASM_COMMENT_START);
1997*38fd1498Szrj       FOR_EACH_EDGE (e, ei, bb->preds)
1998*38fd1498Szrj         {
1999*38fd1498Szrj           dump_edge_info (file, e, TDF_DETAILS, 0);
2000*38fd1498Szrj         }
2001*38fd1498Szrj       fprintf (file, "\n");
2002*38fd1498Szrj     }
2003*38fd1498Szrj   if (INSN_UID (insn) < bb_map_size
2004*38fd1498Szrj       && (bb = end_to_bb[INSN_UID (insn)]) != NULL)
2005*38fd1498Szrj     {
2006*38fd1498Szrj       edge e;
2007*38fd1498Szrj       edge_iterator ei;
2008*38fd1498Szrj 
2009*38fd1498Szrj       fprintf (asm_out_file, "%s SUCC:", ASM_COMMENT_START);
2010*38fd1498Szrj       FOR_EACH_EDGE (e, ei, bb->succs)
2011*38fd1498Szrj        {
2012*38fd1498Szrj          dump_edge_info (asm_out_file, e, TDF_DETAILS, 1);
2013*38fd1498Szrj        }
2014*38fd1498Szrj       fprintf (file, "\n");
2015*38fd1498Szrj     }
2016*38fd1498Szrj }
2017*38fd1498Szrj 
2018*38fd1498Szrj /* Output assembler code for some insns: all or part of a function.
2019*38fd1498Szrj    For description of args, see `final_start_function', above.  */
2020*38fd1498Szrj 
2021*38fd1498Szrj static void
2022*38fd1498Szrj final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)
2023*38fd1498Szrj {
2024*38fd1498Szrj   rtx_insn *insn, *next;
2025*38fd1498Szrj 
2026*38fd1498Szrj   /* Used for -dA dump.  */
2027*38fd1498Szrj   basic_block *start_to_bb = NULL;
2028*38fd1498Szrj   basic_block *end_to_bb = NULL;
2029*38fd1498Szrj   int bb_map_size = 0;
2030*38fd1498Szrj   int bb_seqn = 0;
2031*38fd1498Szrj 
2032*38fd1498Szrj   last_ignored_compare = 0;
2033*38fd1498Szrj 
2034*38fd1498Szrj   if (HAVE_cc0)
2035*38fd1498Szrj     for (insn = first; insn; insn = NEXT_INSN (insn))
2036*38fd1498Szrj       {
2037*38fd1498Szrj 	/* If CC tracking across branches is enabled, record the insn which
2038*38fd1498Szrj 	   jumps to each branch only reached from one place.  */
2039*38fd1498Szrj 	if (optimize_p && JUMP_P (insn))
2040*38fd1498Szrj 	  {
2041*38fd1498Szrj 	    rtx lab = JUMP_LABEL (insn);
2042*38fd1498Szrj 	    if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
2043*38fd1498Szrj 	      {
2044*38fd1498Szrj 		LABEL_REFS (lab) = insn;
2045*38fd1498Szrj 	      }
2046*38fd1498Szrj 	  }
2047*38fd1498Szrj       }
2048*38fd1498Szrj 
2049*38fd1498Szrj   init_recog ();
2050*38fd1498Szrj 
2051*38fd1498Szrj   CC_STATUS_INIT;
2052*38fd1498Szrj 
2053*38fd1498Szrj   if (flag_debug_asm)
2054*38fd1498Szrj     {
2055*38fd1498Szrj       basic_block bb;
2056*38fd1498Szrj 
2057*38fd1498Szrj       bb_map_size = get_max_uid () + 1;
2058*38fd1498Szrj       start_to_bb = XCNEWVEC (basic_block, bb_map_size);
2059*38fd1498Szrj       end_to_bb = XCNEWVEC (basic_block, bb_map_size);
2060*38fd1498Szrj 
2061*38fd1498Szrj       /* There is no cfg for a thunk.  */
2062*38fd1498Szrj       if (!cfun->is_thunk)
2063*38fd1498Szrj 	FOR_EACH_BB_REVERSE_FN (bb, cfun)
2064*38fd1498Szrj 	  {
2065*38fd1498Szrj 	    start_to_bb[INSN_UID (BB_HEAD (bb))] = bb;
2066*38fd1498Szrj 	    end_to_bb[INSN_UID (BB_END (bb))] = bb;
2067*38fd1498Szrj 	  }
2068*38fd1498Szrj     }
2069*38fd1498Szrj 
2070*38fd1498Szrj   /* Output the insns.  */
2071*38fd1498Szrj   for (insn = first; insn;)
2072*38fd1498Szrj     {
2073*38fd1498Szrj       if (HAVE_ATTR_length)
2074*38fd1498Szrj 	{
2075*38fd1498Szrj 	  if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
2076*38fd1498Szrj 	    {
2077*38fd1498Szrj 	      /* This can be triggered by bugs elsewhere in the compiler if
2078*38fd1498Szrj 		 new insns are created after init_insn_lengths is called.  */
2079*38fd1498Szrj 	      gcc_assert (NOTE_P (insn));
2080*38fd1498Szrj 	      insn_current_address = -1;
2081*38fd1498Szrj 	    }
2082*38fd1498Szrj 	  else
2083*38fd1498Szrj 	    insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
2084*38fd1498Szrj 	  /* final can be seen as an iteration of shorten_branches that
2085*38fd1498Szrj 	     does nothing (since a fixed point has already been reached).  */
2086*38fd1498Szrj 	  insn_last_address = insn_current_address;
2087*38fd1498Szrj 	}
2088*38fd1498Szrj 
2089*38fd1498Szrj       dump_basic_block_info (file, insn, start_to_bb, end_to_bb,
2090*38fd1498Szrj                              bb_map_size, &bb_seqn);
2091*38fd1498Szrj       insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
2092*38fd1498Szrj     }
2093*38fd1498Szrj 
2094*38fd1498Szrj   maybe_output_next_view (&seen);
2095*38fd1498Szrj 
2096*38fd1498Szrj   if (flag_debug_asm)
2097*38fd1498Szrj     {
2098*38fd1498Szrj       free (start_to_bb);
2099*38fd1498Szrj       free (end_to_bb);
2100*38fd1498Szrj     }
2101*38fd1498Szrj 
2102*38fd1498Szrj   /* Remove CFI notes, to avoid compare-debug failures.  */
2103*38fd1498Szrj   for (insn = first; insn; insn = next)
2104*38fd1498Szrj     {
2105*38fd1498Szrj       next = NEXT_INSN (insn);
2106*38fd1498Szrj       if (NOTE_P (insn)
2107*38fd1498Szrj 	  && (NOTE_KIND (insn) == NOTE_INSN_CFI
2108*38fd1498Szrj 	      || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL))
2109*38fd1498Szrj 	delete_insn (insn);
2110*38fd1498Szrj     }
2111*38fd1498Szrj }
2112*38fd1498Szrj 
2113*38fd1498Szrj /* This is an exported final_1, callable without SEEN.  */
2114*38fd1498Szrj 
2115*38fd1498Szrj void
2116*38fd1498Szrj final (rtx_insn *first, FILE *file, int optimize_p)
2117*38fd1498Szrj {
2118*38fd1498Szrj   /* Those that use the internal final_start_function_1/final_1 API
2119*38fd1498Szrj      skip initial debug bind notes in final_start_function_1, and pass
2120*38fd1498Szrj      the modified FIRST to final_1.  But those that use the public
2121*38fd1498Szrj      final_start_function/final APIs, final_start_function can't move
2122*38fd1498Szrj      FIRST because it's not passed by reference, so if they were
2123*38fd1498Szrj      skipped there, skip them again here.  */
2124*38fd1498Szrj   while (in_initial_view_p (first))
2125*38fd1498Szrj     first = NEXT_INSN (first);
2126*38fd1498Szrj 
2127*38fd1498Szrj   final_1 (first, file, 0, optimize_p);
2128*38fd1498Szrj }
2129*38fd1498Szrj 
2130*38fd1498Szrj const char *
2131*38fd1498Szrj get_insn_template (int code, rtx insn)
2132*38fd1498Szrj {
2133*38fd1498Szrj   switch (insn_data[code].output_format)
2134*38fd1498Szrj     {
2135*38fd1498Szrj     case INSN_OUTPUT_FORMAT_SINGLE:
2136*38fd1498Szrj       return insn_data[code].output.single;
2137*38fd1498Szrj     case INSN_OUTPUT_FORMAT_MULTI:
2138*38fd1498Szrj       return insn_data[code].output.multi[which_alternative];
2139*38fd1498Szrj     case INSN_OUTPUT_FORMAT_FUNCTION:
2140*38fd1498Szrj       gcc_assert (insn);
2141*38fd1498Szrj       return (*insn_data[code].output.function) (recog_data.operand,
2142*38fd1498Szrj 						 as_a <rtx_insn *> (insn));
2143*38fd1498Szrj 
2144*38fd1498Szrj     default:
2145*38fd1498Szrj       gcc_unreachable ();
2146*38fd1498Szrj     }
2147*38fd1498Szrj }
2148*38fd1498Szrj 
2149*38fd1498Szrj /* Emit the appropriate declaration for an alternate-entry-point
2150*38fd1498Szrj    symbol represented by INSN, to FILE.  INSN is a CODE_LABEL with
2151*38fd1498Szrj    LABEL_KIND != LABEL_NORMAL.
2152*38fd1498Szrj 
2153*38fd1498Szrj    The case fall-through in this function is intentional.  */
2154*38fd1498Szrj static void
2155*38fd1498Szrj output_alternate_entry_point (FILE *file, rtx_insn *insn)
2156*38fd1498Szrj {
2157*38fd1498Szrj   const char *name = LABEL_NAME (insn);
2158*38fd1498Szrj 
2159*38fd1498Szrj   switch (LABEL_KIND (insn))
2160*38fd1498Szrj     {
2161*38fd1498Szrj     case LABEL_WEAK_ENTRY:
2162*38fd1498Szrj #ifdef ASM_WEAKEN_LABEL
2163*38fd1498Szrj       ASM_WEAKEN_LABEL (file, name);
2164*38fd1498Szrj       gcc_fallthrough ();
2165*38fd1498Szrj #endif
2166*38fd1498Szrj     case LABEL_GLOBAL_ENTRY:
2167*38fd1498Szrj       targetm.asm_out.globalize_label (file, name);
2168*38fd1498Szrj       gcc_fallthrough ();
2169*38fd1498Szrj     case LABEL_STATIC_ENTRY:
2170*38fd1498Szrj #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
2171*38fd1498Szrj       ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
2172*38fd1498Szrj #endif
2173*38fd1498Szrj       ASM_OUTPUT_LABEL (file, name);
2174*38fd1498Szrj       break;
2175*38fd1498Szrj 
2176*38fd1498Szrj     case LABEL_NORMAL:
2177*38fd1498Szrj     default:
2178*38fd1498Szrj       gcc_unreachable ();
2179*38fd1498Szrj     }
2180*38fd1498Szrj }
2181*38fd1498Szrj 
2182*38fd1498Szrj /* Given a CALL_INSN, find and return the nested CALL. */
2183*38fd1498Szrj static rtx
2184*38fd1498Szrj call_from_call_insn (rtx_call_insn *insn)
2185*38fd1498Szrj {
2186*38fd1498Szrj   rtx x;
2187*38fd1498Szrj   gcc_assert (CALL_P (insn));
2188*38fd1498Szrj   x = PATTERN (insn);
2189*38fd1498Szrj 
2190*38fd1498Szrj   while (GET_CODE (x) != CALL)
2191*38fd1498Szrj     {
2192*38fd1498Szrj       switch (GET_CODE (x))
2193*38fd1498Szrj 	{
2194*38fd1498Szrj 	default:
2195*38fd1498Szrj 	  gcc_unreachable ();
2196*38fd1498Szrj 	case COND_EXEC:
2197*38fd1498Szrj 	  x = COND_EXEC_CODE (x);
2198*38fd1498Szrj 	  break;
2199*38fd1498Szrj 	case PARALLEL:
2200*38fd1498Szrj 	  x = XVECEXP (x, 0, 0);
2201*38fd1498Szrj 	  break;
2202*38fd1498Szrj 	case SET:
2203*38fd1498Szrj 	  x = XEXP (x, 1);
2204*38fd1498Szrj 	  break;
2205*38fd1498Szrj 	}
2206*38fd1498Szrj     }
2207*38fd1498Szrj   return x;
2208*38fd1498Szrj }
2209*38fd1498Szrj 
2210*38fd1498Szrj /* Print a comment into the asm showing FILENAME, LINENUM, and the
2211*38fd1498Szrj    corresponding source line, if available.  */
2212*38fd1498Szrj 
2213*38fd1498Szrj static void
2214*38fd1498Szrj asm_show_source (const char *filename, int linenum)
2215*38fd1498Szrj {
2216*38fd1498Szrj   if (!filename)
2217*38fd1498Szrj     return;
2218*38fd1498Szrj 
2219*38fd1498Szrj   int line_size;
2220*38fd1498Szrj   const char *line = location_get_source_line (filename, linenum, &line_size);
2221*38fd1498Szrj   if (!line)
2222*38fd1498Szrj     return;
2223*38fd1498Szrj 
2224*38fd1498Szrj   fprintf (asm_out_file, "%s %s:%i: ", ASM_COMMENT_START, filename, linenum);
2225*38fd1498Szrj   /* "line" is not 0-terminated, so we must use line_size.  */
2226*38fd1498Szrj   fwrite (line, 1, line_size, asm_out_file);
2227*38fd1498Szrj   fputc ('\n', asm_out_file);
2228*38fd1498Szrj }
2229*38fd1498Szrj 
2230*38fd1498Szrj /* The final scan for one insn, INSN.
2231*38fd1498Szrj    Args are same as in `final', except that INSN
2232*38fd1498Szrj    is the insn being scanned.
2233*38fd1498Szrj    Value returned is the next insn to be scanned.
2234*38fd1498Szrj 
2235*38fd1498Szrj    NOPEEPHOLES is the flag to disallow peephole processing (currently
2236*38fd1498Szrj    used for within delayed branch sequence output).
2237*38fd1498Szrj 
2238*38fd1498Szrj    SEEN is used to track the end of the prologue, for emitting
2239*38fd1498Szrj    debug information.  We force the emission of a line note after
2240*38fd1498Szrj    both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG.  */
2241*38fd1498Szrj 
2242*38fd1498Szrj static rtx_insn *
2243*38fd1498Szrj final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
2244*38fd1498Szrj 		   int nopeepholes ATTRIBUTE_UNUSED, int *seen)
2245*38fd1498Szrj {
2246*38fd1498Szrj #if HAVE_cc0
2247*38fd1498Szrj   rtx set;
2248*38fd1498Szrj #endif
2249*38fd1498Szrj   rtx_insn *next;
2250*38fd1498Szrj   rtx_jump_table_data *table;
2251*38fd1498Szrj 
2252*38fd1498Szrj   insn_counter++;
2253*38fd1498Szrj 
2254*38fd1498Szrj   /* Ignore deleted insns.  These can occur when we split insns (due to a
2255*38fd1498Szrj      template of "#") while not optimizing.  */
2256*38fd1498Szrj   if (insn->deleted ())
2257*38fd1498Szrj     return NEXT_INSN (insn);
2258*38fd1498Szrj 
2259*38fd1498Szrj   switch (GET_CODE (insn))
2260*38fd1498Szrj     {
2261*38fd1498Szrj     case NOTE:
2262*38fd1498Szrj       switch (NOTE_KIND (insn))
2263*38fd1498Szrj 	{
2264*38fd1498Szrj 	case NOTE_INSN_DELETED:
2265*38fd1498Szrj 	case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
2266*38fd1498Szrj 	  break;
2267*38fd1498Szrj 
2268*38fd1498Szrj 	case NOTE_INSN_SWITCH_TEXT_SECTIONS:
2269*38fd1498Szrj 	  maybe_output_next_view (seen);
2270*38fd1498Szrj 
2271*38fd1498Szrj 	  output_function_exception_table (0);
2272*38fd1498Szrj 
2273*38fd1498Szrj 	  if (targetm.asm_out.unwind_emit)
2274*38fd1498Szrj 	    targetm.asm_out.unwind_emit (asm_out_file, insn);
2275*38fd1498Szrj 
2276*38fd1498Szrj 	  in_cold_section_p = !in_cold_section_p;
2277*38fd1498Szrj 
2278*38fd1498Szrj 	  if (in_cold_section_p)
2279*38fd1498Szrj 	    cold_function_name
2280*38fd1498Szrj 	      = clone_function_name (current_function_decl, "cold");
2281*38fd1498Szrj 
2282*38fd1498Szrj 	  if (dwarf2out_do_frame ())
2283*38fd1498Szrj 	    {
2284*38fd1498Szrj 	      dwarf2out_switch_text_section ();
2285*38fd1498Szrj 	      if (!dwarf2_debug_info_emitted_p (current_function_decl)
2286*38fd1498Szrj 		  && !DECL_IGNORED_P (current_function_decl))
2287*38fd1498Szrj 		debug_hooks->switch_text_section ();
2288*38fd1498Szrj 	    }
2289*38fd1498Szrj 	  else if (!DECL_IGNORED_P (current_function_decl))
2290*38fd1498Szrj 	    debug_hooks->switch_text_section ();
2291*38fd1498Szrj 
2292*38fd1498Szrj 	  switch_to_section (current_function_section ());
2293*38fd1498Szrj 	  targetm.asm_out.function_switched_text_sections (asm_out_file,
2294*38fd1498Szrj 							   current_function_decl,
2295*38fd1498Szrj 							   in_cold_section_p);
2296*38fd1498Szrj 	  /* Emit a label for the split cold section.  Form label name by
2297*38fd1498Szrj 	     suffixing "cold" to the original function's name.  */
2298*38fd1498Szrj 	  if (in_cold_section_p)
2299*38fd1498Szrj 	    {
2300*38fd1498Szrj #ifdef ASM_DECLARE_COLD_FUNCTION_NAME
2301*38fd1498Szrj 	      ASM_DECLARE_COLD_FUNCTION_NAME (asm_out_file,
2302*38fd1498Szrj 					      IDENTIFIER_POINTER
2303*38fd1498Szrj 					          (cold_function_name),
2304*38fd1498Szrj 					      current_function_decl);
2305*38fd1498Szrj #else
2306*38fd1498Szrj 	      ASM_OUTPUT_LABEL (asm_out_file,
2307*38fd1498Szrj 				IDENTIFIER_POINTER (cold_function_name));
2308*38fd1498Szrj #endif
2309*38fd1498Szrj 	    }
2310*38fd1498Szrj 	  break;
2311*38fd1498Szrj 
2312*38fd1498Szrj 	case NOTE_INSN_BASIC_BLOCK:
2313*38fd1498Szrj 	  if (need_profile_function)
2314*38fd1498Szrj 	    {
2315*38fd1498Szrj 	      profile_function (asm_out_file);
2316*38fd1498Szrj 	      need_profile_function = false;
2317*38fd1498Szrj 	    }
2318*38fd1498Szrj 
2319*38fd1498Szrj 	  if (targetm.asm_out.unwind_emit)
2320*38fd1498Szrj 	    targetm.asm_out.unwind_emit (asm_out_file, insn);
2321*38fd1498Szrj 
2322*38fd1498Szrj           discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
2323*38fd1498Szrj 
2324*38fd1498Szrj 	  break;
2325*38fd1498Szrj 
2326*38fd1498Szrj 	case NOTE_INSN_EH_REGION_BEG:
2327*38fd1498Szrj 	  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
2328*38fd1498Szrj 				  NOTE_EH_HANDLER (insn));
2329*38fd1498Szrj 	  break;
2330*38fd1498Szrj 
2331*38fd1498Szrj 	case NOTE_INSN_EH_REGION_END:
2332*38fd1498Szrj 	  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
2333*38fd1498Szrj 				  NOTE_EH_HANDLER (insn));
2334*38fd1498Szrj 	  break;
2335*38fd1498Szrj 
2336*38fd1498Szrj 	case NOTE_INSN_PROLOGUE_END:
2337*38fd1498Szrj 	  targetm.asm_out.function_end_prologue (file);
2338*38fd1498Szrj 	  profile_after_prologue (file);
2339*38fd1498Szrj 
2340*38fd1498Szrj 	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
2341*38fd1498Szrj 	    {
2342*38fd1498Szrj 	      *seen |= SEEN_EMITTED;
2343*38fd1498Szrj 	      force_source_line = true;
2344*38fd1498Szrj 	    }
2345*38fd1498Szrj 	  else
2346*38fd1498Szrj 	    *seen |= SEEN_NOTE;
2347*38fd1498Szrj 
2348*38fd1498Szrj 	  break;
2349*38fd1498Szrj 
2350*38fd1498Szrj 	case NOTE_INSN_EPILOGUE_BEG:
2351*38fd1498Szrj           if (!DECL_IGNORED_P (current_function_decl))
2352*38fd1498Szrj             (*debug_hooks->begin_epilogue) (last_linenum, last_filename);
2353*38fd1498Szrj 	  targetm.asm_out.function_begin_epilogue (file);
2354*38fd1498Szrj 	  break;
2355*38fd1498Szrj 
2356*38fd1498Szrj 	case NOTE_INSN_CFI:
2357*38fd1498Szrj 	  dwarf2out_emit_cfi (NOTE_CFI (insn));
2358*38fd1498Szrj 	  break;
2359*38fd1498Szrj 
2360*38fd1498Szrj 	case NOTE_INSN_CFI_LABEL:
2361*38fd1498Szrj 	  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI",
2362*38fd1498Szrj 				  NOTE_LABEL_NUMBER (insn));
2363*38fd1498Szrj 	  break;
2364*38fd1498Szrj 
2365*38fd1498Szrj 	case NOTE_INSN_FUNCTION_BEG:
2366*38fd1498Szrj 	  if (need_profile_function)
2367*38fd1498Szrj 	    {
2368*38fd1498Szrj 	      profile_function (asm_out_file);
2369*38fd1498Szrj 	      need_profile_function = false;
2370*38fd1498Szrj 	    }
2371*38fd1498Szrj 
2372*38fd1498Szrj 	  app_disable ();
2373*38fd1498Szrj 	  if (!DECL_IGNORED_P (current_function_decl))
2374*38fd1498Szrj 	    debug_hooks->end_prologue (last_linenum, last_filename);
2375*38fd1498Szrj 
2376*38fd1498Szrj 	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
2377*38fd1498Szrj 	    {
2378*38fd1498Szrj 	      *seen |= SEEN_EMITTED;
2379*38fd1498Szrj 	      force_source_line = true;
2380*38fd1498Szrj 	    }
2381*38fd1498Szrj 	  else
2382*38fd1498Szrj 	    *seen |= SEEN_NOTE;
2383*38fd1498Szrj 
2384*38fd1498Szrj 	  break;
2385*38fd1498Szrj 
2386*38fd1498Szrj 	case NOTE_INSN_BLOCK_BEG:
2387*38fd1498Szrj 	  if (debug_info_level == DINFO_LEVEL_NORMAL
2388*38fd1498Szrj 	      || debug_info_level == DINFO_LEVEL_VERBOSE
2389*38fd1498Szrj 	      || write_symbols == DWARF2_DEBUG
2390*38fd1498Szrj 	      || write_symbols == VMS_AND_DWARF2_DEBUG
2391*38fd1498Szrj 	      || write_symbols == VMS_DEBUG)
2392*38fd1498Szrj 	    {
2393*38fd1498Szrj 	      int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
2394*38fd1498Szrj 
2395*38fd1498Szrj 	      app_disable ();
2396*38fd1498Szrj 	      ++block_depth;
2397*38fd1498Szrj 	      high_block_linenum = last_linenum;
2398*38fd1498Szrj 
2399*38fd1498Szrj 	      /* Output debugging info about the symbol-block beginning.  */
2400*38fd1498Szrj 	      if (!DECL_IGNORED_P (current_function_decl))
2401*38fd1498Szrj 		debug_hooks->begin_block (last_linenum, n);
2402*38fd1498Szrj 
2403*38fd1498Szrj 	      /* Mark this block as output.  */
2404*38fd1498Szrj 	      TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
2405*38fd1498Szrj 	      BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
2406*38fd1498Szrj 	    }
2407*38fd1498Szrj 	  if (write_symbols == DBX_DEBUG)
2408*38fd1498Szrj 	    {
2409*38fd1498Szrj 	      location_t *locus_ptr
2410*38fd1498Szrj 		= block_nonartificial_location (NOTE_BLOCK (insn));
2411*38fd1498Szrj 
2412*38fd1498Szrj 	      if (locus_ptr != NULL)
2413*38fd1498Szrj 		{
2414*38fd1498Szrj 		  override_filename = LOCATION_FILE (*locus_ptr);
2415*38fd1498Szrj 		  override_linenum = LOCATION_LINE (*locus_ptr);
2416*38fd1498Szrj 		  override_columnnum = LOCATION_COLUMN (*locus_ptr);
2417*38fd1498Szrj 		}
2418*38fd1498Szrj 	    }
2419*38fd1498Szrj 	  break;
2420*38fd1498Szrj 
2421*38fd1498Szrj 	case NOTE_INSN_BLOCK_END:
2422*38fd1498Szrj 	  maybe_output_next_view (seen);
2423*38fd1498Szrj 
2424*38fd1498Szrj 	  if (debug_info_level == DINFO_LEVEL_NORMAL
2425*38fd1498Szrj 	      || debug_info_level == DINFO_LEVEL_VERBOSE
2426*38fd1498Szrj 	      || write_symbols == DWARF2_DEBUG
2427*38fd1498Szrj 	      || write_symbols == VMS_AND_DWARF2_DEBUG
2428*38fd1498Szrj 	      || write_symbols == VMS_DEBUG)
2429*38fd1498Szrj 	    {
2430*38fd1498Szrj 	      int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
2431*38fd1498Szrj 
2432*38fd1498Szrj 	      app_disable ();
2433*38fd1498Szrj 
2434*38fd1498Szrj 	      /* End of a symbol-block.  */
2435*38fd1498Szrj 	      --block_depth;
2436*38fd1498Szrj 	      gcc_assert (block_depth >= 0);
2437*38fd1498Szrj 
2438*38fd1498Szrj 	      if (!DECL_IGNORED_P (current_function_decl))
2439*38fd1498Szrj 		debug_hooks->end_block (high_block_linenum, n);
2440*38fd1498Szrj 	      gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
2441*38fd1498Szrj 			  == in_cold_section_p);
2442*38fd1498Szrj 	    }
2443*38fd1498Szrj 	  if (write_symbols == DBX_DEBUG)
2444*38fd1498Szrj 	    {
2445*38fd1498Szrj 	      tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn));
2446*38fd1498Szrj 	      location_t *locus_ptr
2447*38fd1498Szrj 		= block_nonartificial_location (outer_block);
2448*38fd1498Szrj 
2449*38fd1498Szrj 	      if (locus_ptr != NULL)
2450*38fd1498Szrj 		{
2451*38fd1498Szrj 		  override_filename = LOCATION_FILE (*locus_ptr);
2452*38fd1498Szrj 		  override_linenum = LOCATION_LINE (*locus_ptr);
2453*38fd1498Szrj 		  override_columnnum = LOCATION_COLUMN (*locus_ptr);
2454*38fd1498Szrj 		}
2455*38fd1498Szrj 	      else
2456*38fd1498Szrj 		{
2457*38fd1498Szrj 		  override_filename = NULL;
2458*38fd1498Szrj 		  override_linenum = 0;
2459*38fd1498Szrj 		  override_columnnum = 0;
2460*38fd1498Szrj 		}
2461*38fd1498Szrj 	    }
2462*38fd1498Szrj 	  break;
2463*38fd1498Szrj 
2464*38fd1498Szrj 	case NOTE_INSN_DELETED_LABEL:
2465*38fd1498Szrj 	  /* Emit the label.  We may have deleted the CODE_LABEL because
2466*38fd1498Szrj 	     the label could be proved to be unreachable, though still
2467*38fd1498Szrj 	     referenced (in the form of having its address taken.  */
2468*38fd1498Szrj 	  ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
2469*38fd1498Szrj 	  break;
2470*38fd1498Szrj 
2471*38fd1498Szrj 	case NOTE_INSN_DELETED_DEBUG_LABEL:
2472*38fd1498Szrj 	  /* Similarly, but need to use different namespace for it.  */
2473*38fd1498Szrj 	  if (CODE_LABEL_NUMBER (insn) != -1)
2474*38fd1498Szrj 	    ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn));
2475*38fd1498Szrj 	  break;
2476*38fd1498Szrj 
2477*38fd1498Szrj 	case NOTE_INSN_VAR_LOCATION:
2478*38fd1498Szrj 	  if (!DECL_IGNORED_P (current_function_decl))
2479*38fd1498Szrj 	    {
2480*38fd1498Szrj 	      debug_hooks->var_location (insn);
2481*38fd1498Szrj 	      set_next_view_needed (seen);
2482*38fd1498Szrj 	    }
2483*38fd1498Szrj 	  break;
2484*38fd1498Szrj 
2485*38fd1498Szrj 	case NOTE_INSN_BEGIN_STMT:
2486*38fd1498Szrj 	  gcc_checking_assert (cfun->debug_nonbind_markers);
2487*38fd1498Szrj 	  if (!DECL_IGNORED_P (current_function_decl)
2488*38fd1498Szrj 	      && notice_source_line (insn, NULL))
2489*38fd1498Szrj 	    {
2490*38fd1498Szrj 	    output_source_line:
2491*38fd1498Szrj 	      (*debug_hooks->source_line) (last_linenum, last_columnnum,
2492*38fd1498Szrj 					   last_filename, last_discriminator,
2493*38fd1498Szrj 					   true);
2494*38fd1498Szrj 	      clear_next_view_needed (seen);
2495*38fd1498Szrj 	    }
2496*38fd1498Szrj 	  break;
2497*38fd1498Szrj 
2498*38fd1498Szrj 	case NOTE_INSN_INLINE_ENTRY:
2499*38fd1498Szrj 	  gcc_checking_assert (cfun->debug_nonbind_markers);
2500*38fd1498Szrj 	  if (!DECL_IGNORED_P (current_function_decl))
2501*38fd1498Szrj 	    {
2502*38fd1498Szrj 	      if (!notice_source_line (insn, NULL))
2503*38fd1498Szrj 		break;
2504*38fd1498Szrj 	      (*debug_hooks->inline_entry) (LOCATION_BLOCK
2505*38fd1498Szrj 					    (NOTE_MARKER_LOCATION (insn)));
2506*38fd1498Szrj 	      goto output_source_line;
2507*38fd1498Szrj 	    }
2508*38fd1498Szrj 	  break;
2509*38fd1498Szrj 
2510*38fd1498Szrj 	default:
2511*38fd1498Szrj 	  gcc_unreachable ();
2512*38fd1498Szrj 	  break;
2513*38fd1498Szrj 	}
2514*38fd1498Szrj       break;
2515*38fd1498Szrj 
2516*38fd1498Szrj     case BARRIER:
2517*38fd1498Szrj       break;
2518*38fd1498Szrj 
2519*38fd1498Szrj     case CODE_LABEL:
2520*38fd1498Szrj       /* The target port might emit labels in the output function for
2521*38fd1498Szrj 	 some insn, e.g. sh.c output_branchy_insn.  */
2522*38fd1498Szrj       if (CODE_LABEL_NUMBER (insn) <= max_labelno)
2523*38fd1498Szrj 	{
2524*38fd1498Szrj 	  int align = LABEL_TO_ALIGNMENT (insn);
2525*38fd1498Szrj #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
2526*38fd1498Szrj 	  int max_skip = LABEL_TO_MAX_SKIP (insn);
2527*38fd1498Szrj #endif
2528*38fd1498Szrj 
2529*38fd1498Szrj 	  if (align && NEXT_INSN (insn))
2530*38fd1498Szrj 	    {
2531*38fd1498Szrj #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
2532*38fd1498Szrj 	      ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
2533*38fd1498Szrj #else
2534*38fd1498Szrj #ifdef ASM_OUTPUT_ALIGN_WITH_NOP
2535*38fd1498Szrj               ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
2536*38fd1498Szrj #else
2537*38fd1498Szrj 	      ASM_OUTPUT_ALIGN (file, align);
2538*38fd1498Szrj #endif
2539*38fd1498Szrj #endif
2540*38fd1498Szrj 	    }
2541*38fd1498Szrj 	}
2542*38fd1498Szrj       CC_STATUS_INIT;
2543*38fd1498Szrj 
2544*38fd1498Szrj       if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn))
2545*38fd1498Szrj 	debug_hooks->label (as_a <rtx_code_label *> (insn));
2546*38fd1498Szrj 
2547*38fd1498Szrj       app_disable ();
2548*38fd1498Szrj 
2549*38fd1498Szrj       /* If this label is followed by a jump-table, make sure we put
2550*38fd1498Szrj 	 the label in the read-only section.  Also possibly write the
2551*38fd1498Szrj 	 label and jump table together.  */
2552*38fd1498Szrj       table = jump_table_for_label (as_a <rtx_code_label *> (insn));
2553*38fd1498Szrj       if (table)
2554*38fd1498Szrj 	{
2555*38fd1498Szrj #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
2556*38fd1498Szrj 	  /* In this case, the case vector is being moved by the
2557*38fd1498Szrj 	     target, so don't output the label at all.  Leave that
2558*38fd1498Szrj 	     to the back end macros.  */
2559*38fd1498Szrj #else
2560*38fd1498Szrj 	  if (! JUMP_TABLES_IN_TEXT_SECTION)
2561*38fd1498Szrj 	    {
2562*38fd1498Szrj 	      int log_align;
2563*38fd1498Szrj 
2564*38fd1498Szrj 	      switch_to_section (targetm.asm_out.function_rodata_section
2565*38fd1498Szrj 				 (current_function_decl));
2566*38fd1498Szrj 
2567*38fd1498Szrj #ifdef ADDR_VEC_ALIGN
2568*38fd1498Szrj 	      log_align = ADDR_VEC_ALIGN (table);
2569*38fd1498Szrj #else
2570*38fd1498Szrj 	      log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
2571*38fd1498Szrj #endif
2572*38fd1498Szrj 	      ASM_OUTPUT_ALIGN (file, log_align);
2573*38fd1498Szrj 	    }
2574*38fd1498Szrj 	  else
2575*38fd1498Szrj 	    switch_to_section (current_function_section ());
2576*38fd1498Szrj 
2577*38fd1498Szrj #ifdef ASM_OUTPUT_CASE_LABEL
2578*38fd1498Szrj 	  ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
2579*38fd1498Szrj #else
2580*38fd1498Szrj 	  targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
2581*38fd1498Szrj #endif
2582*38fd1498Szrj #endif
2583*38fd1498Szrj 	  break;
2584*38fd1498Szrj 	}
2585*38fd1498Szrj       if (LABEL_ALT_ENTRY_P (insn))
2586*38fd1498Szrj 	output_alternate_entry_point (file, insn);
2587*38fd1498Szrj       else
2588*38fd1498Szrj 	targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
2589*38fd1498Szrj       break;
2590*38fd1498Szrj 
2591*38fd1498Szrj     default:
2592*38fd1498Szrj       {
2593*38fd1498Szrj 	rtx body = PATTERN (insn);
2594*38fd1498Szrj 	int insn_code_number;
2595*38fd1498Szrj 	const char *templ;
2596*38fd1498Szrj 	bool is_stmt, *is_stmt_p;
2597*38fd1498Szrj 
2598*38fd1498Szrj 	if (MAY_HAVE_DEBUG_MARKER_INSNS && cfun->debug_nonbind_markers)
2599*38fd1498Szrj 	  {
2600*38fd1498Szrj 	    is_stmt = false;
2601*38fd1498Szrj 	    is_stmt_p = NULL;
2602*38fd1498Szrj 	  }
2603*38fd1498Szrj 	else
2604*38fd1498Szrj 	  is_stmt_p = &is_stmt;
2605*38fd1498Szrj 
2606*38fd1498Szrj 	/* Reset this early so it is correct for ASM statements.  */
2607*38fd1498Szrj 	current_insn_predicate = NULL_RTX;
2608*38fd1498Szrj 
2609*38fd1498Szrj 	/* An INSN, JUMP_INSN or CALL_INSN.
2610*38fd1498Szrj 	   First check for special kinds that recog doesn't recognize.  */
2611*38fd1498Szrj 
2612*38fd1498Szrj 	if (GET_CODE (body) == USE /* These are just declarations.  */
2613*38fd1498Szrj 	    || GET_CODE (body) == CLOBBER)
2614*38fd1498Szrj 	  break;
2615*38fd1498Szrj 
2616*38fd1498Szrj #if HAVE_cc0
2617*38fd1498Szrj 	{
2618*38fd1498Szrj 	  /* If there is a REG_CC_SETTER note on this insn, it means that
2619*38fd1498Szrj 	     the setting of the condition code was done in the delay slot
2620*38fd1498Szrj 	     of the insn that branched here.  So recover the cc status
2621*38fd1498Szrj 	     from the insn that set it.  */
2622*38fd1498Szrj 
2623*38fd1498Szrj 	  rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
2624*38fd1498Szrj 	  if (note)
2625*38fd1498Szrj 	    {
2626*38fd1498Szrj 	      rtx_insn *other = as_a <rtx_insn *> (XEXP (note, 0));
2627*38fd1498Szrj 	      NOTICE_UPDATE_CC (PATTERN (other), other);
2628*38fd1498Szrj 	      cc_prev_status = cc_status;
2629*38fd1498Szrj 	    }
2630*38fd1498Szrj 	}
2631*38fd1498Szrj #endif
2632*38fd1498Szrj 
2633*38fd1498Szrj 	/* Detect insns that are really jump-tables
2634*38fd1498Szrj 	   and output them as such.  */
2635*38fd1498Szrj 
2636*38fd1498Szrj         if (JUMP_TABLE_DATA_P (insn))
2637*38fd1498Szrj 	  {
2638*38fd1498Szrj #if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
2639*38fd1498Szrj 	    int vlen, idx;
2640*38fd1498Szrj #endif
2641*38fd1498Szrj 
2642*38fd1498Szrj 	    if (! JUMP_TABLES_IN_TEXT_SECTION)
2643*38fd1498Szrj 	      switch_to_section (targetm.asm_out.function_rodata_section
2644*38fd1498Szrj 				 (current_function_decl));
2645*38fd1498Szrj 	    else
2646*38fd1498Szrj 	      switch_to_section (current_function_section ());
2647*38fd1498Szrj 
2648*38fd1498Szrj 	    app_disable ();
2649*38fd1498Szrj 
2650*38fd1498Szrj #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
2651*38fd1498Szrj 	    if (GET_CODE (body) == ADDR_VEC)
2652*38fd1498Szrj 	      {
2653*38fd1498Szrj #ifdef ASM_OUTPUT_ADDR_VEC
2654*38fd1498Szrj 		ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
2655*38fd1498Szrj #else
2656*38fd1498Szrj 		gcc_unreachable ();
2657*38fd1498Szrj #endif
2658*38fd1498Szrj 	      }
2659*38fd1498Szrj 	    else
2660*38fd1498Szrj 	      {
2661*38fd1498Szrj #ifdef ASM_OUTPUT_ADDR_DIFF_VEC
2662*38fd1498Szrj 		ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
2663*38fd1498Szrj #else
2664*38fd1498Szrj 		gcc_unreachable ();
2665*38fd1498Szrj #endif
2666*38fd1498Szrj 	      }
2667*38fd1498Szrj #else
2668*38fd1498Szrj 	    vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
2669*38fd1498Szrj 	    for (idx = 0; idx < vlen; idx++)
2670*38fd1498Szrj 	      {
2671*38fd1498Szrj 		if (GET_CODE (body) == ADDR_VEC)
2672*38fd1498Szrj 		  {
2673*38fd1498Szrj #ifdef ASM_OUTPUT_ADDR_VEC_ELT
2674*38fd1498Szrj 		    ASM_OUTPUT_ADDR_VEC_ELT
2675*38fd1498Szrj 		      (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
2676*38fd1498Szrj #else
2677*38fd1498Szrj 		    gcc_unreachable ();
2678*38fd1498Szrj #endif
2679*38fd1498Szrj 		  }
2680*38fd1498Szrj 		else
2681*38fd1498Szrj 		  {
2682*38fd1498Szrj #ifdef ASM_OUTPUT_ADDR_DIFF_ELT
2683*38fd1498Szrj 		    ASM_OUTPUT_ADDR_DIFF_ELT
2684*38fd1498Szrj 		      (file,
2685*38fd1498Szrj 		       body,
2686*38fd1498Szrj 		       CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
2687*38fd1498Szrj 		       CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
2688*38fd1498Szrj #else
2689*38fd1498Szrj 		    gcc_unreachable ();
2690*38fd1498Szrj #endif
2691*38fd1498Szrj 		  }
2692*38fd1498Szrj 	      }
2693*38fd1498Szrj #ifdef ASM_OUTPUT_CASE_END
2694*38fd1498Szrj 	    ASM_OUTPUT_CASE_END (file,
2695*38fd1498Szrj 				 CODE_LABEL_NUMBER (PREV_INSN (insn)),
2696*38fd1498Szrj 				 insn);
2697*38fd1498Szrj #endif
2698*38fd1498Szrj #endif
2699*38fd1498Szrj 
2700*38fd1498Szrj 	    switch_to_section (current_function_section ());
2701*38fd1498Szrj 
2702*38fd1498Szrj 	    if (debug_variable_location_views
2703*38fd1498Szrj 		&& !DECL_IGNORED_P (current_function_decl))
2704*38fd1498Szrj 	      debug_hooks->var_location (insn);
2705*38fd1498Szrj 
2706*38fd1498Szrj 	    break;
2707*38fd1498Szrj 	  }
2708*38fd1498Szrj 	/* Output this line note if it is the first or the last line
2709*38fd1498Szrj 	   note in a row.  */
2710*38fd1498Szrj 	if (!DECL_IGNORED_P (current_function_decl)
2711*38fd1498Szrj 	    && notice_source_line (insn, is_stmt_p))
2712*38fd1498Szrj 	  {
2713*38fd1498Szrj 	    if (flag_verbose_asm)
2714*38fd1498Szrj 	      asm_show_source (last_filename, last_linenum);
2715*38fd1498Szrj 	    (*debug_hooks->source_line) (last_linenum, last_columnnum,
2716*38fd1498Szrj 					 last_filename, last_discriminator,
2717*38fd1498Szrj 					 is_stmt);
2718*38fd1498Szrj 	    clear_next_view_needed (seen);
2719*38fd1498Szrj 	  }
2720*38fd1498Szrj 	else
2721*38fd1498Szrj 	  maybe_output_next_view (seen);
2722*38fd1498Szrj 
2723*38fd1498Szrj 	gcc_checking_assert (!DEBUG_INSN_P (insn));
2724*38fd1498Szrj 
2725*38fd1498Szrj 	if (GET_CODE (body) == PARALLEL
2726*38fd1498Szrj 	    && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
2727*38fd1498Szrj 	  body = XVECEXP (body, 0, 0);
2728*38fd1498Szrj 
2729*38fd1498Szrj 	if (GET_CODE (body) == ASM_INPUT)
2730*38fd1498Szrj 	  {
2731*38fd1498Szrj 	    const char *string = XSTR (body, 0);
2732*38fd1498Szrj 
2733*38fd1498Szrj 	    /* There's no telling what that did to the condition codes.  */
2734*38fd1498Szrj 	    CC_STATUS_INIT;
2735*38fd1498Szrj 
2736*38fd1498Szrj 	    if (string[0])
2737*38fd1498Szrj 	      {
2738*38fd1498Szrj 		expanded_location loc;
2739*38fd1498Szrj 
2740*38fd1498Szrj 		app_enable ();
2741*38fd1498Szrj 		loc = expand_location (ASM_INPUT_SOURCE_LOCATION (body));
2742*38fd1498Szrj 		if (*loc.file && loc.line)
2743*38fd1498Szrj 		  fprintf (asm_out_file, "%s %i \"%s\" 1\n",
2744*38fd1498Szrj 			   ASM_COMMENT_START, loc.line, loc.file);
2745*38fd1498Szrj 		fprintf (asm_out_file, "\t%s\n", string);
2746*38fd1498Szrj #if HAVE_AS_LINE_ZERO
2747*38fd1498Szrj 		if (*loc.file && loc.line)
2748*38fd1498Szrj 		  fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
2749*38fd1498Szrj #endif
2750*38fd1498Szrj 	      }
2751*38fd1498Szrj 	    break;
2752*38fd1498Szrj 	  }
2753*38fd1498Szrj 
2754*38fd1498Szrj 	/* Detect `asm' construct with operands.  */
2755*38fd1498Szrj 	if (asm_noperands (body) >= 0)
2756*38fd1498Szrj 	  {
2757*38fd1498Szrj 	    unsigned int noperands = asm_noperands (body);
2758*38fd1498Szrj 	    rtx *ops = XALLOCAVEC (rtx, noperands);
2759*38fd1498Szrj 	    const char *string;
2760*38fd1498Szrj 	    location_t loc;
2761*38fd1498Szrj 	    expanded_location expanded;
2762*38fd1498Szrj 
2763*38fd1498Szrj 	    /* There's no telling what that did to the condition codes.  */
2764*38fd1498Szrj 	    CC_STATUS_INIT;
2765*38fd1498Szrj 
2766*38fd1498Szrj 	    /* Get out the operand values.  */
2767*38fd1498Szrj 	    string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc);
2768*38fd1498Szrj 	    /* Inhibit dying on what would otherwise be compiler bugs.  */
2769*38fd1498Szrj 	    insn_noperands = noperands;
2770*38fd1498Szrj 	    this_is_asm_operands = insn;
2771*38fd1498Szrj 	    expanded = expand_location (loc);
2772*38fd1498Szrj 
2773*38fd1498Szrj #ifdef FINAL_PRESCAN_INSN
2774*38fd1498Szrj 	    FINAL_PRESCAN_INSN (insn, ops, insn_noperands);
2775*38fd1498Szrj #endif
2776*38fd1498Szrj 
2777*38fd1498Szrj 	    /* Output the insn using them.  */
2778*38fd1498Szrj 	    if (string[0])
2779*38fd1498Szrj 	      {
2780*38fd1498Szrj 		app_enable ();
2781*38fd1498Szrj 		if (expanded.file && expanded.line)
2782*38fd1498Szrj 		  fprintf (asm_out_file, "%s %i \"%s\" 1\n",
2783*38fd1498Szrj 			   ASM_COMMENT_START, expanded.line, expanded.file);
2784*38fd1498Szrj 	        output_asm_insn (string, ops);
2785*38fd1498Szrj #if HAVE_AS_LINE_ZERO
2786*38fd1498Szrj 		if (expanded.file && expanded.line)
2787*38fd1498Szrj 		  fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
2788*38fd1498Szrj #endif
2789*38fd1498Szrj 	      }
2790*38fd1498Szrj 
2791*38fd1498Szrj 	    if (targetm.asm_out.final_postscan_insn)
2792*38fd1498Szrj 	      targetm.asm_out.final_postscan_insn (file, insn, ops,
2793*38fd1498Szrj 						   insn_noperands);
2794*38fd1498Szrj 
2795*38fd1498Szrj 	    this_is_asm_operands = 0;
2796*38fd1498Szrj 	    break;
2797*38fd1498Szrj 	  }
2798*38fd1498Szrj 
2799*38fd1498Szrj 	app_disable ();
2800*38fd1498Szrj 
2801*38fd1498Szrj 	if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (body))
2802*38fd1498Szrj 	  {
2803*38fd1498Szrj 	    /* A delayed-branch sequence */
2804*38fd1498Szrj 	    int i;
2805*38fd1498Szrj 
2806*38fd1498Szrj 	    final_sequence = seq;
2807*38fd1498Szrj 
2808*38fd1498Szrj 	    /* The first insn in this SEQUENCE might be a JUMP_INSN that will
2809*38fd1498Szrj 	       force the restoration of a comparison that was previously
2810*38fd1498Szrj 	       thought unnecessary.  If that happens, cancel this sequence
2811*38fd1498Szrj 	       and cause that insn to be restored.  */
2812*38fd1498Szrj 
2813*38fd1498Szrj 	    next = final_scan_insn (seq->insn (0), file, 0, 1, seen);
2814*38fd1498Szrj 	    if (next != seq->insn (1))
2815*38fd1498Szrj 	      {
2816*38fd1498Szrj 		final_sequence = 0;
2817*38fd1498Szrj 		return next;
2818*38fd1498Szrj 	      }
2819*38fd1498Szrj 
2820*38fd1498Szrj 	    for (i = 1; i < seq->len (); i++)
2821*38fd1498Szrj 	      {
2822*38fd1498Szrj 		rtx_insn *insn = seq->insn (i);
2823*38fd1498Szrj 		rtx_insn *next = NEXT_INSN (insn);
2824*38fd1498Szrj 		/* We loop in case any instruction in a delay slot gets
2825*38fd1498Szrj 		   split.  */
2826*38fd1498Szrj 		do
2827*38fd1498Szrj 		  insn = final_scan_insn (insn, file, 0, 1, seen);
2828*38fd1498Szrj 		while (insn != next);
2829*38fd1498Szrj 	      }
2830*38fd1498Szrj #ifdef DBR_OUTPUT_SEQEND
2831*38fd1498Szrj 	    DBR_OUTPUT_SEQEND (file);
2832*38fd1498Szrj #endif
2833*38fd1498Szrj 	    final_sequence = 0;
2834*38fd1498Szrj 
2835*38fd1498Szrj 	    /* If the insn requiring the delay slot was a CALL_INSN, the
2836*38fd1498Szrj 	       insns in the delay slot are actually executed before the
2837*38fd1498Szrj 	       called function.  Hence we don't preserve any CC-setting
2838*38fd1498Szrj 	       actions in these insns and the CC must be marked as being
2839*38fd1498Szrj 	       clobbered by the function.  */
2840*38fd1498Szrj 	    if (CALL_P (seq->insn (0)))
2841*38fd1498Szrj 	      {
2842*38fd1498Szrj 		CC_STATUS_INIT;
2843*38fd1498Szrj 	      }
2844*38fd1498Szrj 	    break;
2845*38fd1498Szrj 	  }
2846*38fd1498Szrj 
2847*38fd1498Szrj 	/* We have a real machine instruction as rtl.  */
2848*38fd1498Szrj 
2849*38fd1498Szrj 	body = PATTERN (insn);
2850*38fd1498Szrj 
2851*38fd1498Szrj #if HAVE_cc0
2852*38fd1498Szrj 	set = single_set (insn);
2853*38fd1498Szrj 
2854*38fd1498Szrj 	/* Check for redundant test and compare instructions
2855*38fd1498Szrj 	   (when the condition codes are already set up as desired).
2856*38fd1498Szrj 	   This is done only when optimizing; if not optimizing,
2857*38fd1498Szrj 	   it should be possible for the user to alter a variable
2858*38fd1498Szrj 	   with the debugger in between statements
2859*38fd1498Szrj 	   and the next statement should reexamine the variable
2860*38fd1498Szrj 	   to compute the condition codes.  */
2861*38fd1498Szrj 
2862*38fd1498Szrj 	if (optimize_p)
2863*38fd1498Szrj 	  {
2864*38fd1498Szrj 	    if (set
2865*38fd1498Szrj 		&& GET_CODE (SET_DEST (set)) == CC0
2866*38fd1498Szrj 		&& insn != last_ignored_compare)
2867*38fd1498Szrj 	      {
2868*38fd1498Szrj 		rtx src1, src2;
2869*38fd1498Szrj 		if (GET_CODE (SET_SRC (set)) == SUBREG)
2870*38fd1498Szrj 		  SET_SRC (set) = alter_subreg (&SET_SRC (set), true);
2871*38fd1498Szrj 
2872*38fd1498Szrj 		src1 = SET_SRC (set);
2873*38fd1498Szrj 		src2 = NULL_RTX;
2874*38fd1498Szrj 		if (GET_CODE (SET_SRC (set)) == COMPARE)
2875*38fd1498Szrj 		  {
2876*38fd1498Szrj 		    if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
2877*38fd1498Szrj 		      XEXP (SET_SRC (set), 0)
2878*38fd1498Szrj 			= alter_subreg (&XEXP (SET_SRC (set), 0), true);
2879*38fd1498Szrj 		    if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
2880*38fd1498Szrj 		      XEXP (SET_SRC (set), 1)
2881*38fd1498Szrj 			= alter_subreg (&XEXP (SET_SRC (set), 1), true);
2882*38fd1498Szrj 		    if (XEXP (SET_SRC (set), 1)
2883*38fd1498Szrj 			== CONST0_RTX (GET_MODE (XEXP (SET_SRC (set), 0))))
2884*38fd1498Szrj 		      src2 = XEXP (SET_SRC (set), 0);
2885*38fd1498Szrj 		  }
2886*38fd1498Szrj 		if ((cc_status.value1 != 0
2887*38fd1498Szrj 		     && rtx_equal_p (src1, cc_status.value1))
2888*38fd1498Szrj 		    || (cc_status.value2 != 0
2889*38fd1498Szrj 			&& rtx_equal_p (src1, cc_status.value2))
2890*38fd1498Szrj 		    || (src2 != 0 && cc_status.value1 != 0
2891*38fd1498Szrj 		        && rtx_equal_p (src2, cc_status.value1))
2892*38fd1498Szrj 		    || (src2 != 0 && cc_status.value2 != 0
2893*38fd1498Szrj 			&& rtx_equal_p (src2, cc_status.value2)))
2894*38fd1498Szrj 		  {
2895*38fd1498Szrj 		    /* Don't delete insn if it has an addressing side-effect.  */
2896*38fd1498Szrj 		    if (! FIND_REG_INC_NOTE (insn, NULL_RTX)
2897*38fd1498Szrj 			/* or if anything in it is volatile.  */
2898*38fd1498Szrj 			&& ! volatile_refs_p (PATTERN (insn)))
2899*38fd1498Szrj 		      {
2900*38fd1498Szrj 			/* We don't really delete the insn; just ignore it.  */
2901*38fd1498Szrj 			last_ignored_compare = insn;
2902*38fd1498Szrj 			break;
2903*38fd1498Szrj 		      }
2904*38fd1498Szrj 		  }
2905*38fd1498Szrj 	      }
2906*38fd1498Szrj 	  }
2907*38fd1498Szrj 
2908*38fd1498Szrj 	/* If this is a conditional branch, maybe modify it
2909*38fd1498Szrj 	   if the cc's are in a nonstandard state
2910*38fd1498Szrj 	   so that it accomplishes the same thing that it would
2911*38fd1498Szrj 	   do straightforwardly if the cc's were set up normally.  */
2912*38fd1498Szrj 
2913*38fd1498Szrj 	if (cc_status.flags != 0
2914*38fd1498Szrj 	    && JUMP_P (insn)
2915*38fd1498Szrj 	    && GET_CODE (body) == SET
2916*38fd1498Szrj 	    && SET_DEST (body) == pc_rtx
2917*38fd1498Szrj 	    && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
2918*38fd1498Szrj 	    && COMPARISON_P (XEXP (SET_SRC (body), 0))
2919*38fd1498Szrj 	    && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
2920*38fd1498Szrj 	  {
2921*38fd1498Szrj 	    /* This function may alter the contents of its argument
2922*38fd1498Szrj 	       and clear some of the cc_status.flags bits.
2923*38fd1498Szrj 	       It may also return 1 meaning condition now always true
2924*38fd1498Szrj 	       or -1 meaning condition now always false
2925*38fd1498Szrj 	       or 2 meaning condition nontrivial but altered.  */
2926*38fd1498Szrj 	    int result = alter_cond (XEXP (SET_SRC (body), 0));
2927*38fd1498Szrj 	    /* If condition now has fixed value, replace the IF_THEN_ELSE
2928*38fd1498Szrj 	       with its then-operand or its else-operand.  */
2929*38fd1498Szrj 	    if (result == 1)
2930*38fd1498Szrj 	      SET_SRC (body) = XEXP (SET_SRC (body), 1);
2931*38fd1498Szrj 	    if (result == -1)
2932*38fd1498Szrj 	      SET_SRC (body) = XEXP (SET_SRC (body), 2);
2933*38fd1498Szrj 
2934*38fd1498Szrj 	    /* The jump is now either unconditional or a no-op.
2935*38fd1498Szrj 	       If it has become a no-op, don't try to output it.
2936*38fd1498Szrj 	       (It would not be recognized.)  */
2937*38fd1498Szrj 	    if (SET_SRC (body) == pc_rtx)
2938*38fd1498Szrj 	      {
2939*38fd1498Szrj 	        delete_insn (insn);
2940*38fd1498Szrj 		break;
2941*38fd1498Szrj 	      }
2942*38fd1498Szrj 	    else if (ANY_RETURN_P (SET_SRC (body)))
2943*38fd1498Szrj 	      /* Replace (set (pc) (return)) with (return).  */
2944*38fd1498Szrj 	      PATTERN (insn) = body = SET_SRC (body);
2945*38fd1498Szrj 
2946*38fd1498Szrj 	    /* Rerecognize the instruction if it has changed.  */
2947*38fd1498Szrj 	    if (result != 0)
2948*38fd1498Szrj 	      INSN_CODE (insn) = -1;
2949*38fd1498Szrj 	  }
2950*38fd1498Szrj 
2951*38fd1498Szrj 	/* If this is a conditional trap, maybe modify it if the cc's
2952*38fd1498Szrj 	   are in a nonstandard state so that it accomplishes the same
2953*38fd1498Szrj 	   thing that it would do straightforwardly if the cc's were
2954*38fd1498Szrj 	   set up normally.  */
2955*38fd1498Szrj 	if (cc_status.flags != 0
2956*38fd1498Szrj 	    && NONJUMP_INSN_P (insn)
2957*38fd1498Szrj 	    && GET_CODE (body) == TRAP_IF
2958*38fd1498Szrj 	    && COMPARISON_P (TRAP_CONDITION (body))
2959*38fd1498Szrj 	    && XEXP (TRAP_CONDITION (body), 0) == cc0_rtx)
2960*38fd1498Szrj 	  {
2961*38fd1498Szrj 	    /* This function may alter the contents of its argument
2962*38fd1498Szrj 	       and clear some of the cc_status.flags bits.
2963*38fd1498Szrj 	       It may also return 1 meaning condition now always true
2964*38fd1498Szrj 	       or -1 meaning condition now always false
2965*38fd1498Szrj 	       or 2 meaning condition nontrivial but altered.  */
2966*38fd1498Szrj 	    int result = alter_cond (TRAP_CONDITION (body));
2967*38fd1498Szrj 
2968*38fd1498Szrj 	    /* If TRAP_CONDITION has become always false, delete the
2969*38fd1498Szrj 	       instruction.  */
2970*38fd1498Szrj 	    if (result == -1)
2971*38fd1498Szrj 	      {
2972*38fd1498Szrj 		delete_insn (insn);
2973*38fd1498Szrj 		break;
2974*38fd1498Szrj 	      }
2975*38fd1498Szrj 
2976*38fd1498Szrj 	    /* If TRAP_CONDITION has become always true, replace
2977*38fd1498Szrj 	       TRAP_CONDITION with const_true_rtx.  */
2978*38fd1498Szrj 	    if (result == 1)
2979*38fd1498Szrj 	      TRAP_CONDITION (body) = const_true_rtx;
2980*38fd1498Szrj 
2981*38fd1498Szrj 	    /* Rerecognize the instruction if it has changed.  */
2982*38fd1498Szrj 	    if (result != 0)
2983*38fd1498Szrj 	      INSN_CODE (insn) = -1;
2984*38fd1498Szrj 	  }
2985*38fd1498Szrj 
2986*38fd1498Szrj 	/* Make same adjustments to instructions that examine the
2987*38fd1498Szrj 	   condition codes without jumping and instructions that
2988*38fd1498Szrj 	   handle conditional moves (if this machine has either one).  */
2989*38fd1498Szrj 
2990*38fd1498Szrj 	if (cc_status.flags != 0
2991*38fd1498Szrj 	    && set != 0)
2992*38fd1498Szrj 	  {
2993*38fd1498Szrj 	    rtx cond_rtx, then_rtx, else_rtx;
2994*38fd1498Szrj 
2995*38fd1498Szrj 	    if (!JUMP_P (insn)
2996*38fd1498Szrj 		&& GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
2997*38fd1498Szrj 	      {
2998*38fd1498Szrj 		cond_rtx = XEXP (SET_SRC (set), 0);
2999*38fd1498Szrj 		then_rtx = XEXP (SET_SRC (set), 1);
3000*38fd1498Szrj 		else_rtx = XEXP (SET_SRC (set), 2);
3001*38fd1498Szrj 	      }
3002*38fd1498Szrj 	    else
3003*38fd1498Szrj 	      {
3004*38fd1498Szrj 		cond_rtx = SET_SRC (set);
3005*38fd1498Szrj 		then_rtx = const_true_rtx;
3006*38fd1498Szrj 		else_rtx = const0_rtx;
3007*38fd1498Szrj 	      }
3008*38fd1498Szrj 
3009*38fd1498Szrj 	    if (COMPARISON_P (cond_rtx)
3010*38fd1498Szrj 		&& XEXP (cond_rtx, 0) == cc0_rtx)
3011*38fd1498Szrj 	      {
3012*38fd1498Szrj 		int result;
3013*38fd1498Szrj 		result = alter_cond (cond_rtx);
3014*38fd1498Szrj 		if (result == 1)
3015*38fd1498Szrj 		  validate_change (insn, &SET_SRC (set), then_rtx, 0);
3016*38fd1498Szrj 		else if (result == -1)
3017*38fd1498Szrj 		  validate_change (insn, &SET_SRC (set), else_rtx, 0);
3018*38fd1498Szrj 		else if (result == 2)
3019*38fd1498Szrj 		  INSN_CODE (insn) = -1;
3020*38fd1498Szrj 		if (SET_DEST (set) == SET_SRC (set))
3021*38fd1498Szrj 		  delete_insn (insn);
3022*38fd1498Szrj 	      }
3023*38fd1498Szrj 	  }
3024*38fd1498Szrj 
3025*38fd1498Szrj #endif
3026*38fd1498Szrj 
3027*38fd1498Szrj 	/* Do machine-specific peephole optimizations if desired.  */
3028*38fd1498Szrj 
3029*38fd1498Szrj 	if (HAVE_peephole && optimize_p && !flag_no_peephole && !nopeepholes)
3030*38fd1498Szrj 	  {
3031*38fd1498Szrj 	    rtx_insn *next = peephole (insn);
3032*38fd1498Szrj 	    /* When peepholing, if there were notes within the peephole,
3033*38fd1498Szrj 	       emit them before the peephole.  */
3034*38fd1498Szrj 	    if (next != 0 && next != NEXT_INSN (insn))
3035*38fd1498Szrj 	      {
3036*38fd1498Szrj 		rtx_insn *note, *prev = PREV_INSN (insn);
3037*38fd1498Szrj 
3038*38fd1498Szrj 		for (note = NEXT_INSN (insn); note != next;
3039*38fd1498Szrj 		     note = NEXT_INSN (note))
3040*38fd1498Szrj 		  final_scan_insn (note, file, optimize_p, nopeepholes, seen);
3041*38fd1498Szrj 
3042*38fd1498Szrj 		/* Put the notes in the proper position for a later
3043*38fd1498Szrj 		   rescan.  For example, the SH target can do this
3044*38fd1498Szrj 		   when generating a far jump in a delayed branch
3045*38fd1498Szrj 		   sequence.  */
3046*38fd1498Szrj 		note = NEXT_INSN (insn);
3047*38fd1498Szrj 		SET_PREV_INSN (note) = prev;
3048*38fd1498Szrj 		SET_NEXT_INSN (prev) = note;
3049*38fd1498Szrj 		SET_NEXT_INSN (PREV_INSN (next)) = insn;
3050*38fd1498Szrj 		SET_PREV_INSN (insn) = PREV_INSN (next);
3051*38fd1498Szrj 		SET_NEXT_INSN (insn) = next;
3052*38fd1498Szrj 		SET_PREV_INSN (next) = insn;
3053*38fd1498Szrj 	      }
3054*38fd1498Szrj 
3055*38fd1498Szrj 	    /* PEEPHOLE might have changed this.  */
3056*38fd1498Szrj 	    body = PATTERN (insn);
3057*38fd1498Szrj 	  }
3058*38fd1498Szrj 
3059*38fd1498Szrj 	/* Try to recognize the instruction.
3060*38fd1498Szrj 	   If successful, verify that the operands satisfy the
3061*38fd1498Szrj 	   constraints for the instruction.  Crash if they don't,
3062*38fd1498Szrj 	   since `reload' should have changed them so that they do.  */
3063*38fd1498Szrj 
3064*38fd1498Szrj 	insn_code_number = recog_memoized (insn);
3065*38fd1498Szrj 	cleanup_subreg_operands (insn);
3066*38fd1498Szrj 
3067*38fd1498Szrj 	/* Dump the insn in the assembly for debugging (-dAP).
3068*38fd1498Szrj 	   If the final dump is requested as slim RTL, dump slim
3069*38fd1498Szrj 	   RTL to the assembly file also.  */
3070*38fd1498Szrj 	if (flag_dump_rtl_in_asm)
3071*38fd1498Szrj 	  {
3072*38fd1498Szrj 	    print_rtx_head = ASM_COMMENT_START;
3073*38fd1498Szrj 	    if (! (dump_flags & TDF_SLIM))
3074*38fd1498Szrj 	      print_rtl_single (asm_out_file, insn);
3075*38fd1498Szrj 	    else
3076*38fd1498Szrj 	      dump_insn_slim (asm_out_file, insn);
3077*38fd1498Szrj 	    print_rtx_head = "";
3078*38fd1498Szrj 	  }
3079*38fd1498Szrj 
3080*38fd1498Szrj 	if (! constrain_operands_cached (insn, 1))
3081*38fd1498Szrj 	  fatal_insn_not_found (insn);
3082*38fd1498Szrj 
3083*38fd1498Szrj 	/* Some target machines need to prescan each insn before
3084*38fd1498Szrj 	   it is output.  */
3085*38fd1498Szrj 
3086*38fd1498Szrj #ifdef FINAL_PRESCAN_INSN
3087*38fd1498Szrj 	FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
3088*38fd1498Szrj #endif
3089*38fd1498Szrj 
3090*38fd1498Szrj 	if (targetm.have_conditional_execution ()
3091*38fd1498Szrj 	    && GET_CODE (PATTERN (insn)) == COND_EXEC)
3092*38fd1498Szrj 	  current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
3093*38fd1498Szrj 
3094*38fd1498Szrj #if HAVE_cc0
3095*38fd1498Szrj 	cc_prev_status = cc_status;
3096*38fd1498Szrj 
3097*38fd1498Szrj 	/* Update `cc_status' for this instruction.
3098*38fd1498Szrj 	   The instruction's output routine may change it further.
3099*38fd1498Szrj 	   If the output routine for a jump insn needs to depend
3100*38fd1498Szrj 	   on the cc status, it should look at cc_prev_status.  */
3101*38fd1498Szrj 
3102*38fd1498Szrj 	NOTICE_UPDATE_CC (body, insn);
3103*38fd1498Szrj #endif
3104*38fd1498Szrj 
3105*38fd1498Szrj 	current_output_insn = debug_insn = insn;
3106*38fd1498Szrj 
3107*38fd1498Szrj 	/* Find the proper template for this insn.  */
3108*38fd1498Szrj 	templ = get_insn_template (insn_code_number, insn);
3109*38fd1498Szrj 
3110*38fd1498Szrj 	/* If the C code returns 0, it means that it is a jump insn
3111*38fd1498Szrj 	   which follows a deleted test insn, and that test insn
3112*38fd1498Szrj 	   needs to be reinserted.  */
3113*38fd1498Szrj 	if (templ == 0)
3114*38fd1498Szrj 	  {
3115*38fd1498Szrj 	    rtx_insn *prev;
3116*38fd1498Szrj 
3117*38fd1498Szrj 	    gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);
3118*38fd1498Szrj 
3119*38fd1498Szrj 	    /* We have already processed the notes between the setter and
3120*38fd1498Szrj 	       the user.  Make sure we don't process them again, this is
3121*38fd1498Szrj 	       particularly important if one of the notes is a block
3122*38fd1498Szrj 	       scope note or an EH note.  */
3123*38fd1498Szrj 	    for (prev = insn;
3124*38fd1498Szrj 		 prev != last_ignored_compare;
3125*38fd1498Szrj 		 prev = PREV_INSN (prev))
3126*38fd1498Szrj 	      {
3127*38fd1498Szrj 		if (NOTE_P (prev))
3128*38fd1498Szrj 		  delete_insn (prev);	/* Use delete_note.  */
3129*38fd1498Szrj 	      }
3130*38fd1498Szrj 
3131*38fd1498Szrj 	    return prev;
3132*38fd1498Szrj 	  }
3133*38fd1498Szrj 
3134*38fd1498Szrj 	/* If the template is the string "#", it means that this insn must
3135*38fd1498Szrj 	   be split.  */
3136*38fd1498Szrj 	if (templ[0] == '#' && templ[1] == '\0')
3137*38fd1498Szrj 	  {
3138*38fd1498Szrj 	    rtx_insn *new_rtx = try_split (body, insn, 0);
3139*38fd1498Szrj 
3140*38fd1498Szrj 	    /* If we didn't split the insn, go away.  */
3141*38fd1498Szrj 	    if (new_rtx == insn && PATTERN (new_rtx) == body)
3142*38fd1498Szrj 	      fatal_insn ("could not split insn", insn);
3143*38fd1498Szrj 
3144*38fd1498Szrj 	    /* If we have a length attribute, this instruction should have
3145*38fd1498Szrj 	       been split in shorten_branches, to ensure that we would have
3146*38fd1498Szrj 	       valid length info for the splitees.  */
3147*38fd1498Szrj 	    gcc_assert (!HAVE_ATTR_length);
3148*38fd1498Szrj 
3149*38fd1498Szrj 	    return new_rtx;
3150*38fd1498Szrj 	  }
3151*38fd1498Szrj 
3152*38fd1498Szrj 	/* ??? This will put the directives in the wrong place if
3153*38fd1498Szrj 	   get_insn_template outputs assembly directly.  However calling it
3154*38fd1498Szrj 	   before get_insn_template breaks if the insns is split.  */
3155*38fd1498Szrj 	if (targetm.asm_out.unwind_emit_before_insn
3156*38fd1498Szrj 	    && targetm.asm_out.unwind_emit)
3157*38fd1498Szrj 	  targetm.asm_out.unwind_emit (asm_out_file, insn);
3158*38fd1498Szrj 
3159*38fd1498Szrj 	rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn);
3160*38fd1498Szrj 	if (call_insn != NULL)
3161*38fd1498Szrj 	  {
3162*38fd1498Szrj 	    rtx x = call_from_call_insn (call_insn);
3163*38fd1498Szrj 	    x = XEXP (x, 0);
3164*38fd1498Szrj 	    if (x && MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
3165*38fd1498Szrj 	      {
3166*38fd1498Szrj 		tree t;
3167*38fd1498Szrj 		x = XEXP (x, 0);
3168*38fd1498Szrj 		t = SYMBOL_REF_DECL (x);
3169*38fd1498Szrj 		if (t)
3170*38fd1498Szrj 		  assemble_external (t);
3171*38fd1498Szrj 	      }
3172*38fd1498Szrj 	  }
3173*38fd1498Szrj 
3174*38fd1498Szrj 	/* Output assembler code from the template.  */
3175*38fd1498Szrj 	output_asm_insn (templ, recog_data.operand);
3176*38fd1498Szrj 
3177*38fd1498Szrj 	/* Some target machines need to postscan each insn after
3178*38fd1498Szrj 	   it is output.  */
3179*38fd1498Szrj 	if (targetm.asm_out.final_postscan_insn)
3180*38fd1498Szrj 	  targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand,
3181*38fd1498Szrj 					       recog_data.n_operands);
3182*38fd1498Szrj 
3183*38fd1498Szrj 	if (!targetm.asm_out.unwind_emit_before_insn
3184*38fd1498Szrj 	    && targetm.asm_out.unwind_emit)
3185*38fd1498Szrj 	  targetm.asm_out.unwind_emit (asm_out_file, insn);
3186*38fd1498Szrj 
3187*38fd1498Szrj 	/* Let the debug info back-end know about this call.  We do this only
3188*38fd1498Szrj 	   after the instruction has been emitted because labels that may be
3189*38fd1498Szrj 	   created to reference the call instruction must appear after it.  */
3190*38fd1498Szrj 	if ((debug_variable_location_views || call_insn != NULL)
3191*38fd1498Szrj 	    && !DECL_IGNORED_P (current_function_decl))
3192*38fd1498Szrj 	  debug_hooks->var_location (insn);
3193*38fd1498Szrj 
3194*38fd1498Szrj 	current_output_insn = debug_insn = 0;
3195*38fd1498Szrj       }
3196*38fd1498Szrj     }
3197*38fd1498Szrj   return NEXT_INSN (insn);
3198*38fd1498Szrj }
3199*38fd1498Szrj 
3200*38fd1498Szrj /* This is a wrapper around final_scan_insn_1 that allows ports to
3201*38fd1498Szrj    call it recursively without a known value for SEEN.  The value is
3202*38fd1498Szrj    saved at the outermost call, and recovered for recursive calls.
3203*38fd1498Szrj    Recursive calls MUST pass NULL, or the same pointer if they can
3204*38fd1498Szrj    otherwise get to it.  */
3205*38fd1498Szrj 
3206*38fd1498Szrj rtx_insn *
3207*38fd1498Szrj final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
3208*38fd1498Szrj 		 int nopeepholes, int *seen)
3209*38fd1498Szrj {
3210*38fd1498Szrj   static int *enclosing_seen;
3211*38fd1498Szrj   static int recursion_counter;
3212*38fd1498Szrj 
3213*38fd1498Szrj   gcc_assert (seen || recursion_counter);
3214*38fd1498Szrj   gcc_assert (!recursion_counter || !seen || seen == enclosing_seen);
3215*38fd1498Szrj 
3216*38fd1498Szrj   if (!recursion_counter++)
3217*38fd1498Szrj     enclosing_seen = seen;
3218*38fd1498Szrj   else if (!seen)
3219*38fd1498Szrj     seen = enclosing_seen;
3220*38fd1498Szrj 
3221*38fd1498Szrj   rtx_insn *ret = final_scan_insn_1 (insn, file, optimize_p, nopeepholes, seen);
3222*38fd1498Szrj 
3223*38fd1498Szrj   if (!--recursion_counter)
3224*38fd1498Szrj     enclosing_seen = NULL;
3225*38fd1498Szrj 
3226*38fd1498Szrj   return ret;
3227*38fd1498Szrj }
3228*38fd1498Szrj 
3229*38fd1498Szrj 
3230*38fd1498Szrj /* Return whether a source line note needs to be emitted before INSN.
3231*38fd1498Szrj    Sets IS_STMT to TRUE if the line should be marked as a possible
3232*38fd1498Szrj    breakpoint location.  */
3233*38fd1498Szrj 
3234*38fd1498Szrj static bool
3235*38fd1498Szrj notice_source_line (rtx_insn *insn, bool *is_stmt)
3236*38fd1498Szrj {
3237*38fd1498Szrj   const char *filename;
3238*38fd1498Szrj   int linenum, columnnum;
3239*38fd1498Szrj 
3240*38fd1498Szrj   if (NOTE_MARKER_P (insn))
3241*38fd1498Szrj     {
3242*38fd1498Szrj       location_t loc = NOTE_MARKER_LOCATION (insn);
3243*38fd1498Szrj       /* The inline entry markers (gimple, insn, note) carry the
3244*38fd1498Szrj 	 location of the call, because that's what we want to carry
3245*38fd1498Szrj 	 during compilation, but the location we want to output in
3246*38fd1498Szrj 	 debug information for the inline entry point is the location
3247*38fd1498Szrj 	 of the function itself.  */
3248*38fd1498Szrj       if (NOTE_KIND (insn) == NOTE_INSN_INLINE_ENTRY)
3249*38fd1498Szrj 	{
3250*38fd1498Szrj 	  tree block = LOCATION_BLOCK (loc);
3251*38fd1498Szrj 	  tree fn = block_ultimate_origin (block);
3252*38fd1498Szrj 	  loc = DECL_SOURCE_LOCATION (fn);
3253*38fd1498Szrj 	}
3254*38fd1498Szrj       expanded_location xloc = expand_location (loc);
3255*38fd1498Szrj       if (xloc.line == 0)
3256*38fd1498Szrj 	{
3257*38fd1498Szrj 	  gcc_checking_assert (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION
3258*38fd1498Szrj 			       || LOCATION_LOCUS (loc) == BUILTINS_LOCATION);
3259*38fd1498Szrj 	  return false;
3260*38fd1498Szrj 	}
3261*38fd1498Szrj       filename = xloc.file;
3262*38fd1498Szrj       linenum = xloc.line;
3263*38fd1498Szrj       columnnum = xloc.column;
3264*38fd1498Szrj       force_source_line = true;
3265*38fd1498Szrj     }
3266*38fd1498Szrj   else if (override_filename)
3267*38fd1498Szrj     {
3268*38fd1498Szrj       filename = override_filename;
3269*38fd1498Szrj       linenum = override_linenum;
3270*38fd1498Szrj       columnnum = override_columnnum;
3271*38fd1498Szrj     }
3272*38fd1498Szrj   else if (INSN_HAS_LOCATION (insn))
3273*38fd1498Szrj     {
3274*38fd1498Szrj       expanded_location xloc = insn_location (insn);
3275*38fd1498Szrj       filename = xloc.file;
3276*38fd1498Szrj       linenum = xloc.line;
3277*38fd1498Szrj       columnnum = xloc.column;
3278*38fd1498Szrj     }
3279*38fd1498Szrj   else
3280*38fd1498Szrj     {
3281*38fd1498Szrj       filename = NULL;
3282*38fd1498Szrj       linenum = 0;
3283*38fd1498Szrj       columnnum = 0;
3284*38fd1498Szrj     }
3285*38fd1498Szrj 
3286*38fd1498Szrj   if (filename == NULL)
3287*38fd1498Szrj     return false;
3288*38fd1498Szrj 
3289*38fd1498Szrj   if (force_source_line
3290*38fd1498Szrj       || filename != last_filename
3291*38fd1498Szrj       || last_linenum != linenum
3292*38fd1498Szrj       || (debug_column_info && last_columnnum != columnnum))
3293*38fd1498Szrj     {
3294*38fd1498Szrj       force_source_line = false;
3295*38fd1498Szrj       last_filename = filename;
3296*38fd1498Szrj       last_linenum = linenum;
3297*38fd1498Szrj       last_columnnum = columnnum;
3298*38fd1498Szrj       last_discriminator = discriminator;
3299*38fd1498Szrj       if (is_stmt)
3300*38fd1498Szrj 	*is_stmt = true;
3301*38fd1498Szrj       high_block_linenum = MAX (last_linenum, high_block_linenum);
3302*38fd1498Szrj       high_function_linenum = MAX (last_linenum, high_function_linenum);
3303*38fd1498Szrj       return true;
3304*38fd1498Szrj     }
3305*38fd1498Szrj 
3306*38fd1498Szrj   if (SUPPORTS_DISCRIMINATOR && last_discriminator != discriminator)
3307*38fd1498Szrj     {
3308*38fd1498Szrj       /* If the discriminator changed, but the line number did not,
3309*38fd1498Szrj          output the line table entry with is_stmt false so the
3310*38fd1498Szrj          debugger does not treat this as a breakpoint location.  */
3311*38fd1498Szrj       last_discriminator = discriminator;
3312*38fd1498Szrj       if (is_stmt)
3313*38fd1498Szrj 	*is_stmt = false;
3314*38fd1498Szrj       return true;
3315*38fd1498Szrj     }
3316*38fd1498Szrj 
3317*38fd1498Szrj   return false;
3318*38fd1498Szrj }
3319*38fd1498Szrj 
3320*38fd1498Szrj /* For each operand in INSN, simplify (subreg (reg)) so that it refers
3321*38fd1498Szrj    directly to the desired hard register.  */
3322*38fd1498Szrj 
3323*38fd1498Szrj void
3324*38fd1498Szrj cleanup_subreg_operands (rtx_insn *insn)
3325*38fd1498Szrj {
3326*38fd1498Szrj   int i;
3327*38fd1498Szrj   bool changed = false;
3328*38fd1498Szrj   extract_insn_cached (insn);
3329*38fd1498Szrj   for (i = 0; i < recog_data.n_operands; i++)
3330*38fd1498Szrj     {
3331*38fd1498Szrj       /* The following test cannot use recog_data.operand when testing
3332*38fd1498Szrj 	 for a SUBREG: the underlying object might have been changed
3333*38fd1498Szrj 	 already if we are inside a match_operator expression that
3334*38fd1498Szrj 	 matches the else clause.  Instead we test the underlying
3335*38fd1498Szrj 	 expression directly.  */
3336*38fd1498Szrj       if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
3337*38fd1498Szrj 	{
3338*38fd1498Szrj 	  recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i], true);
3339*38fd1498Szrj 	  changed = true;
3340*38fd1498Szrj 	}
3341*38fd1498Szrj       else if (GET_CODE (recog_data.operand[i]) == PLUS
3342*38fd1498Szrj 	       || GET_CODE (recog_data.operand[i]) == MULT
3343*38fd1498Szrj 	       || MEM_P (recog_data.operand[i]))
3344*38fd1498Szrj 	recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i], &changed);
3345*38fd1498Szrj     }
3346*38fd1498Szrj 
3347*38fd1498Szrj   for (i = 0; i < recog_data.n_dups; i++)
3348*38fd1498Szrj     {
3349*38fd1498Szrj       if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
3350*38fd1498Szrj 	{
3351*38fd1498Szrj 	  *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i], true);
3352*38fd1498Szrj 	  changed = true;
3353*38fd1498Szrj 	}
3354*38fd1498Szrj       else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
3355*38fd1498Szrj 	       || GET_CODE (*recog_data.dup_loc[i]) == MULT
3356*38fd1498Szrj 	       || MEM_P (*recog_data.dup_loc[i]))
3357*38fd1498Szrj 	*recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed);
3358*38fd1498Szrj     }
3359*38fd1498Szrj   if (changed)
3360*38fd1498Szrj     df_insn_rescan (insn);
3361*38fd1498Szrj }
3362*38fd1498Szrj 
3363*38fd1498Szrj /* If X is a SUBREG, try to replace it with a REG or a MEM, based on
3364*38fd1498Szrj    the thing it is a subreg of.  Do it anyway if FINAL_P.  */
3365*38fd1498Szrj 
3366*38fd1498Szrj rtx
3367*38fd1498Szrj alter_subreg (rtx *xp, bool final_p)
3368*38fd1498Szrj {
3369*38fd1498Szrj   rtx x = *xp;
3370*38fd1498Szrj   rtx y = SUBREG_REG (x);
3371*38fd1498Szrj 
3372*38fd1498Szrj   /* simplify_subreg does not remove subreg from volatile references.
3373*38fd1498Szrj      We are required to.  */
3374*38fd1498Szrj   if (MEM_P (y))
3375*38fd1498Szrj     {
3376*38fd1498Szrj       poly_int64 offset = SUBREG_BYTE (x);
3377*38fd1498Szrj 
3378*38fd1498Szrj       /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
3379*38fd1498Szrj 	 contains 0 instead of the proper offset.  See simplify_subreg.  */
3380*38fd1498Szrj       if (paradoxical_subreg_p (x))
3381*38fd1498Szrj 	offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y));
3382*38fd1498Szrj 
3383*38fd1498Szrj       if (final_p)
3384*38fd1498Szrj 	*xp = adjust_address (y, GET_MODE (x), offset);
3385*38fd1498Szrj       else
3386*38fd1498Szrj 	*xp = adjust_address_nv (y, GET_MODE (x), offset);
3387*38fd1498Szrj     }
3388*38fd1498Szrj   else if (REG_P (y) && HARD_REGISTER_P (y))
3389*38fd1498Szrj     {
3390*38fd1498Szrj       rtx new_rtx = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
3391*38fd1498Szrj 				     SUBREG_BYTE (x));
3392*38fd1498Szrj 
3393*38fd1498Szrj       if (new_rtx != 0)
3394*38fd1498Szrj 	*xp = new_rtx;
3395*38fd1498Szrj       else if (final_p && REG_P (y))
3396*38fd1498Szrj 	{
3397*38fd1498Szrj 	  /* Simplify_subreg can't handle some REG cases, but we have to.  */
3398*38fd1498Szrj 	  unsigned int regno;
3399*38fd1498Szrj 	  poly_int64 offset;
3400*38fd1498Szrj 
3401*38fd1498Szrj 	  regno = subreg_regno (x);
3402*38fd1498Szrj 	  if (subreg_lowpart_p (x))
3403*38fd1498Szrj 	    offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y));
3404*38fd1498Szrj 	  else
3405*38fd1498Szrj 	    offset = SUBREG_BYTE (x);
3406*38fd1498Szrj 	  *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, offset);
3407*38fd1498Szrj 	}
3408*38fd1498Szrj     }
3409*38fd1498Szrj 
3410*38fd1498Szrj   return *xp;
3411*38fd1498Szrj }
3412*38fd1498Szrj 
3413*38fd1498Szrj /* Do alter_subreg on all the SUBREGs contained in X.  */
3414*38fd1498Szrj 
3415*38fd1498Szrj static rtx
3416*38fd1498Szrj walk_alter_subreg (rtx *xp, bool *changed)
3417*38fd1498Szrj {
3418*38fd1498Szrj   rtx x = *xp;
3419*38fd1498Szrj   switch (GET_CODE (x))
3420*38fd1498Szrj     {
3421*38fd1498Szrj     case PLUS:
3422*38fd1498Szrj     case MULT:
3423*38fd1498Szrj     case AND:
3424*38fd1498Szrj       XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed);
3425*38fd1498Szrj       XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1), changed);
3426*38fd1498Szrj       break;
3427*38fd1498Szrj 
3428*38fd1498Szrj     case MEM:
3429*38fd1498Szrj     case ZERO_EXTEND:
3430*38fd1498Szrj       XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed);
3431*38fd1498Szrj       break;
3432*38fd1498Szrj 
3433*38fd1498Szrj     case SUBREG:
3434*38fd1498Szrj       *changed = true;
3435*38fd1498Szrj       return alter_subreg (xp, true);
3436*38fd1498Szrj 
3437*38fd1498Szrj     default:
3438*38fd1498Szrj       break;
3439*38fd1498Szrj     }
3440*38fd1498Szrj 
3441*38fd1498Szrj   return *xp;
3442*38fd1498Szrj }
3443*38fd1498Szrj 
3444*38fd1498Szrj #if HAVE_cc0
3445*38fd1498Szrj 
3446*38fd1498Szrj /* Given BODY, the body of a jump instruction, alter the jump condition
3447*38fd1498Szrj    as required by the bits that are set in cc_status.flags.
3448*38fd1498Szrj    Not all of the bits there can be handled at this level in all cases.
3449*38fd1498Szrj 
3450*38fd1498Szrj    The value is normally 0.
3451*38fd1498Szrj    1 means that the condition has become always true.
3452*38fd1498Szrj    -1 means that the condition has become always false.
3453*38fd1498Szrj    2 means that COND has been altered.  */
3454*38fd1498Szrj 
3455*38fd1498Szrj static int
3456*38fd1498Szrj alter_cond (rtx cond)
3457*38fd1498Szrj {
3458*38fd1498Szrj   int value = 0;
3459*38fd1498Szrj 
3460*38fd1498Szrj   if (cc_status.flags & CC_REVERSED)
3461*38fd1498Szrj     {
3462*38fd1498Szrj       value = 2;
3463*38fd1498Szrj       PUT_CODE (cond, swap_condition (GET_CODE (cond)));
3464*38fd1498Szrj     }
3465*38fd1498Szrj 
3466*38fd1498Szrj   if (cc_status.flags & CC_INVERTED)
3467*38fd1498Szrj     {
3468*38fd1498Szrj       value = 2;
3469*38fd1498Szrj       PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
3470*38fd1498Szrj     }
3471*38fd1498Szrj 
3472*38fd1498Szrj   if (cc_status.flags & CC_NOT_POSITIVE)
3473*38fd1498Szrj     switch (GET_CODE (cond))
3474*38fd1498Szrj       {
3475*38fd1498Szrj       case LE:
3476*38fd1498Szrj       case LEU:
3477*38fd1498Szrj       case GEU:
3478*38fd1498Szrj 	/* Jump becomes unconditional.  */
3479*38fd1498Szrj 	return 1;
3480*38fd1498Szrj 
3481*38fd1498Szrj       case GT:
3482*38fd1498Szrj       case GTU:
3483*38fd1498Szrj       case LTU:
3484*38fd1498Szrj 	/* Jump becomes no-op.  */
3485*38fd1498Szrj 	return -1;
3486*38fd1498Szrj 
3487*38fd1498Szrj       case GE:
3488*38fd1498Szrj 	PUT_CODE (cond, EQ);
3489*38fd1498Szrj 	value = 2;
3490*38fd1498Szrj 	break;
3491*38fd1498Szrj 
3492*38fd1498Szrj       case LT:
3493*38fd1498Szrj 	PUT_CODE (cond, NE);
3494*38fd1498Szrj 	value = 2;
3495*38fd1498Szrj 	break;
3496*38fd1498Szrj 
3497*38fd1498Szrj       default:
3498*38fd1498Szrj 	break;
3499*38fd1498Szrj       }
3500*38fd1498Szrj 
3501*38fd1498Szrj   if (cc_status.flags & CC_NOT_NEGATIVE)
3502*38fd1498Szrj     switch (GET_CODE (cond))
3503*38fd1498Szrj       {
3504*38fd1498Szrj       case GE:
3505*38fd1498Szrj       case GEU:
3506*38fd1498Szrj 	/* Jump becomes unconditional.  */
3507*38fd1498Szrj 	return 1;
3508*38fd1498Szrj 
3509*38fd1498Szrj       case LT:
3510*38fd1498Szrj       case LTU:
3511*38fd1498Szrj 	/* Jump becomes no-op.  */
3512*38fd1498Szrj 	return -1;
3513*38fd1498Szrj 
3514*38fd1498Szrj       case LE:
3515*38fd1498Szrj       case LEU:
3516*38fd1498Szrj 	PUT_CODE (cond, EQ);
3517*38fd1498Szrj 	value = 2;
3518*38fd1498Szrj 	break;
3519*38fd1498Szrj 
3520*38fd1498Szrj       case GT:
3521*38fd1498Szrj       case GTU:
3522*38fd1498Szrj 	PUT_CODE (cond, NE);
3523*38fd1498Szrj 	value = 2;
3524*38fd1498Szrj 	break;
3525*38fd1498Szrj 
3526*38fd1498Szrj       default:
3527*38fd1498Szrj 	break;
3528*38fd1498Szrj       }
3529*38fd1498Szrj 
3530*38fd1498Szrj   if (cc_status.flags & CC_NO_OVERFLOW)
3531*38fd1498Szrj     switch (GET_CODE (cond))
3532*38fd1498Szrj       {
3533*38fd1498Szrj       case GEU:
3534*38fd1498Szrj 	/* Jump becomes unconditional.  */
3535*38fd1498Szrj 	return 1;
3536*38fd1498Szrj 
3537*38fd1498Szrj       case LEU:
3538*38fd1498Szrj 	PUT_CODE (cond, EQ);
3539*38fd1498Szrj 	value = 2;
3540*38fd1498Szrj 	break;
3541*38fd1498Szrj 
3542*38fd1498Szrj       case GTU:
3543*38fd1498Szrj 	PUT_CODE (cond, NE);
3544*38fd1498Szrj 	value = 2;
3545*38fd1498Szrj 	break;
3546*38fd1498Szrj 
3547*38fd1498Szrj       case LTU:
3548*38fd1498Szrj 	/* Jump becomes no-op.  */
3549*38fd1498Szrj 	return -1;
3550*38fd1498Szrj 
3551*38fd1498Szrj       default:
3552*38fd1498Szrj 	break;
3553*38fd1498Szrj       }
3554*38fd1498Szrj 
3555*38fd1498Szrj   if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
3556*38fd1498Szrj     switch (GET_CODE (cond))
3557*38fd1498Szrj       {
3558*38fd1498Szrj       default:
3559*38fd1498Szrj 	gcc_unreachable ();
3560*38fd1498Szrj 
3561*38fd1498Szrj       case NE:
3562*38fd1498Szrj 	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
3563*38fd1498Szrj 	value = 2;
3564*38fd1498Szrj 	break;
3565*38fd1498Szrj 
3566*38fd1498Szrj       case EQ:
3567*38fd1498Szrj 	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
3568*38fd1498Szrj 	value = 2;
3569*38fd1498Szrj 	break;
3570*38fd1498Szrj       }
3571*38fd1498Szrj 
3572*38fd1498Szrj   if (cc_status.flags & CC_NOT_SIGNED)
3573*38fd1498Szrj     /* The flags are valid if signed condition operators are converted
3574*38fd1498Szrj        to unsigned.  */
3575*38fd1498Szrj     switch (GET_CODE (cond))
3576*38fd1498Szrj       {
3577*38fd1498Szrj       case LE:
3578*38fd1498Szrj 	PUT_CODE (cond, LEU);
3579*38fd1498Szrj 	value = 2;
3580*38fd1498Szrj 	break;
3581*38fd1498Szrj 
3582*38fd1498Szrj       case LT:
3583*38fd1498Szrj 	PUT_CODE (cond, LTU);
3584*38fd1498Szrj 	value = 2;
3585*38fd1498Szrj 	break;
3586*38fd1498Szrj 
3587*38fd1498Szrj       case GT:
3588*38fd1498Szrj 	PUT_CODE (cond, GTU);
3589*38fd1498Szrj 	value = 2;
3590*38fd1498Szrj 	break;
3591*38fd1498Szrj 
3592*38fd1498Szrj       case GE:
3593*38fd1498Szrj 	PUT_CODE (cond, GEU);
3594*38fd1498Szrj 	value = 2;
3595*38fd1498Szrj 	break;
3596*38fd1498Szrj 
3597*38fd1498Szrj       default:
3598*38fd1498Szrj 	break;
3599*38fd1498Szrj       }
3600*38fd1498Szrj 
3601*38fd1498Szrj   return value;
3602*38fd1498Szrj }
3603*38fd1498Szrj #endif
3604*38fd1498Szrj 
3605*38fd1498Szrj /* Report inconsistency between the assembler template and the operands.
3606*38fd1498Szrj    In an `asm', it's the user's fault; otherwise, the compiler's fault.  */
3607*38fd1498Szrj 
3608*38fd1498Szrj void
3609*38fd1498Szrj output_operand_lossage (const char *cmsgid, ...)
3610*38fd1498Szrj {
3611*38fd1498Szrj   char *fmt_string;
3612*38fd1498Szrj   char *new_message;
3613*38fd1498Szrj   const char *pfx_str;
3614*38fd1498Szrj   va_list ap;
3615*38fd1498Szrj 
3616*38fd1498Szrj   va_start (ap, cmsgid);
3617*38fd1498Szrj 
3618*38fd1498Szrj   pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
3619*38fd1498Szrj   fmt_string = xasprintf ("%s%s", pfx_str, _(cmsgid));
3620*38fd1498Szrj   new_message = xvasprintf (fmt_string, ap);
3621*38fd1498Szrj 
3622*38fd1498Szrj   if (this_is_asm_operands)
3623*38fd1498Szrj     error_for_asm (this_is_asm_operands, "%s", new_message);
3624*38fd1498Szrj   else
3625*38fd1498Szrj     internal_error ("%s", new_message);
3626*38fd1498Szrj 
3627*38fd1498Szrj   free (fmt_string);
3628*38fd1498Szrj   free (new_message);
3629*38fd1498Szrj   va_end (ap);
3630*38fd1498Szrj }
3631*38fd1498Szrj 
3632*38fd1498Szrj /* Output of assembler code from a template, and its subroutines.  */
3633*38fd1498Szrj 
3634*38fd1498Szrj /* Annotate the assembly with a comment describing the pattern and
3635*38fd1498Szrj    alternative used.  */
3636*38fd1498Szrj 
3637*38fd1498Szrj static void
3638*38fd1498Szrj output_asm_name (void)
3639*38fd1498Szrj {
3640*38fd1498Szrj   if (debug_insn)
3641*38fd1498Szrj     {
3642*38fd1498Szrj       fprintf (asm_out_file, "\t%s %d\t",
3643*38fd1498Szrj 	       ASM_COMMENT_START, INSN_UID (debug_insn));
3644*38fd1498Szrj 
3645*38fd1498Szrj       fprintf (asm_out_file, "[c=%d",
3646*38fd1498Szrj 	       insn_cost (debug_insn, optimize_insn_for_speed_p ()));
3647*38fd1498Szrj       if (HAVE_ATTR_length)
3648*38fd1498Szrj 	fprintf (asm_out_file, " l=%d",
3649*38fd1498Szrj 		 get_attr_length (debug_insn));
3650*38fd1498Szrj       fprintf (asm_out_file, "]  ");
3651*38fd1498Szrj 
3652*38fd1498Szrj       int num = INSN_CODE (debug_insn);
3653*38fd1498Szrj       fprintf (asm_out_file, "%s", insn_data[num].name);
3654*38fd1498Szrj       if (insn_data[num].n_alternatives > 1)
3655*38fd1498Szrj 	fprintf (asm_out_file, "/%d", which_alternative);
3656*38fd1498Szrj 
3657*38fd1498Szrj       /* Clear this so only the first assembler insn
3658*38fd1498Szrj 	 of any rtl insn will get the special comment for -dp.  */
3659*38fd1498Szrj       debug_insn = 0;
3660*38fd1498Szrj     }
3661*38fd1498Szrj }
3662*38fd1498Szrj 
3663*38fd1498Szrj /* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it
3664*38fd1498Szrj    or its address, return that expr .  Set *PADDRESSP to 1 if the expr
3665*38fd1498Szrj    corresponds to the address of the object and 0 if to the object.  */
3666*38fd1498Szrj 
3667*38fd1498Szrj static tree
3668*38fd1498Szrj get_mem_expr_from_op (rtx op, int *paddressp)
3669*38fd1498Szrj {
3670*38fd1498Szrj   tree expr;
3671*38fd1498Szrj   int inner_addressp;
3672*38fd1498Szrj 
3673*38fd1498Szrj   *paddressp = 0;
3674*38fd1498Szrj 
3675*38fd1498Szrj   if (REG_P (op))
3676*38fd1498Szrj     return REG_EXPR (op);
3677*38fd1498Szrj   else if (!MEM_P (op))
3678*38fd1498Szrj     return 0;
3679*38fd1498Szrj 
3680*38fd1498Szrj   if (MEM_EXPR (op) != 0)
3681*38fd1498Szrj     return MEM_EXPR (op);
3682*38fd1498Szrj 
3683*38fd1498Szrj   /* Otherwise we have an address, so indicate it and look at the address.  */
3684*38fd1498Szrj   *paddressp = 1;
3685*38fd1498Szrj   op = XEXP (op, 0);
3686*38fd1498Szrj 
3687*38fd1498Szrj   /* First check if we have a decl for the address, then look at the right side
3688*38fd1498Szrj      if it is a PLUS.  Otherwise, strip off arithmetic and keep looking.
3689*38fd1498Szrj      But don't allow the address to itself be indirect.  */
3690*38fd1498Szrj   if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
3691*38fd1498Szrj     return expr;
3692*38fd1498Szrj   else if (GET_CODE (op) == PLUS
3693*38fd1498Szrj 	   && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
3694*38fd1498Szrj     return expr;
3695*38fd1498Szrj 
3696*38fd1498Szrj   while (UNARY_P (op)
3697*38fd1498Szrj 	 || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH)
3698*38fd1498Szrj     op = XEXP (op, 0);
3699*38fd1498Szrj 
3700*38fd1498Szrj   expr = get_mem_expr_from_op (op, &inner_addressp);
3701*38fd1498Szrj   return inner_addressp ? 0 : expr;
3702*38fd1498Szrj }
3703*38fd1498Szrj 
3704*38fd1498Szrj /* Output operand names for assembler instructions.  OPERANDS is the
3705*38fd1498Szrj    operand vector, OPORDER is the order to write the operands, and NOPS
3706*38fd1498Szrj    is the number of operands to write.  */
3707*38fd1498Szrj 
3708*38fd1498Szrj static void
3709*38fd1498Szrj output_asm_operand_names (rtx *operands, int *oporder, int nops)
3710*38fd1498Szrj {
3711*38fd1498Szrj   int wrote = 0;
3712*38fd1498Szrj   int i;
3713*38fd1498Szrj 
3714*38fd1498Szrj   for (i = 0; i < nops; i++)
3715*38fd1498Szrj     {
3716*38fd1498Szrj       int addressp;
3717*38fd1498Szrj       rtx op = operands[oporder[i]];
3718*38fd1498Szrj       tree expr = get_mem_expr_from_op (op, &addressp);
3719*38fd1498Szrj 
3720*38fd1498Szrj       fprintf (asm_out_file, "%c%s",
3721*38fd1498Szrj 	       wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START);
3722*38fd1498Szrj       wrote = 1;
3723*38fd1498Szrj       if (expr)
3724*38fd1498Szrj 	{
3725*38fd1498Szrj 	  fprintf (asm_out_file, "%s",
3726*38fd1498Szrj 		   addressp ? "*" : "");
3727*38fd1498Szrj 	  print_mem_expr (asm_out_file, expr);
3728*38fd1498Szrj 	  wrote = 1;
3729*38fd1498Szrj 	}
3730*38fd1498Szrj       else if (REG_P (op) && ORIGINAL_REGNO (op)
3731*38fd1498Szrj 	       && ORIGINAL_REGNO (op) != REGNO (op))
3732*38fd1498Szrj 	fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op));
3733*38fd1498Szrj     }
3734*38fd1498Szrj }
3735*38fd1498Szrj 
3736*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
3737*38fd1498Szrj /* Helper function to parse assembler dialects in the asm string.
3738*38fd1498Szrj    This is called from output_asm_insn and asm_fprintf.  */
3739*38fd1498Szrj static const char *
3740*38fd1498Szrj do_assembler_dialects (const char *p, int *dialect)
3741*38fd1498Szrj {
3742*38fd1498Szrj   char c = *(p - 1);
3743*38fd1498Szrj 
3744*38fd1498Szrj   switch (c)
3745*38fd1498Szrj     {
3746*38fd1498Szrj     case '{':
3747*38fd1498Szrj       {
3748*38fd1498Szrj         int i;
3749*38fd1498Szrj 
3750*38fd1498Szrj         if (*dialect)
3751*38fd1498Szrj           output_operand_lossage ("nested assembly dialect alternatives");
3752*38fd1498Szrj         else
3753*38fd1498Szrj           *dialect = 1;
3754*38fd1498Szrj 
3755*38fd1498Szrj         /* If we want the first dialect, do nothing.  Otherwise, skip
3756*38fd1498Szrj            DIALECT_NUMBER of strings ending with '|'.  */
3757*38fd1498Szrj         for (i = 0; i < dialect_number; i++)
3758*38fd1498Szrj           {
3759*38fd1498Szrj             while (*p && *p != '}')
3760*38fd1498Szrj 	      {
3761*38fd1498Szrj 		if (*p == '|')
3762*38fd1498Szrj 		  {
3763*38fd1498Szrj 		    p++;
3764*38fd1498Szrj 		    break;
3765*38fd1498Szrj 		  }
3766*38fd1498Szrj 
3767*38fd1498Szrj 		/* Skip over any character after a percent sign.  */
3768*38fd1498Szrj 		if (*p == '%')
3769*38fd1498Szrj 		  p++;
3770*38fd1498Szrj 		if (*p)
3771*38fd1498Szrj 		  p++;
3772*38fd1498Szrj 	      }
3773*38fd1498Szrj 
3774*38fd1498Szrj             if (*p == '}')
3775*38fd1498Szrj 	      break;
3776*38fd1498Szrj           }
3777*38fd1498Szrj 
3778*38fd1498Szrj         if (*p == '\0')
3779*38fd1498Szrj           output_operand_lossage ("unterminated assembly dialect alternative");
3780*38fd1498Szrj       }
3781*38fd1498Szrj       break;
3782*38fd1498Szrj 
3783*38fd1498Szrj     case '|':
3784*38fd1498Szrj       if (*dialect)
3785*38fd1498Szrj         {
3786*38fd1498Szrj           /* Skip to close brace.  */
3787*38fd1498Szrj           do
3788*38fd1498Szrj             {
3789*38fd1498Szrj 	      if (*p == '\0')
3790*38fd1498Szrj 		{
3791*38fd1498Szrj 		  output_operand_lossage ("unterminated assembly dialect alternative");
3792*38fd1498Szrj 		  break;
3793*38fd1498Szrj 		}
3794*38fd1498Szrj 
3795*38fd1498Szrj 	      /* Skip over any character after a percent sign.  */
3796*38fd1498Szrj 	      if (*p == '%' && p[1])
3797*38fd1498Szrj 		{
3798*38fd1498Szrj 		  p += 2;
3799*38fd1498Szrj 		  continue;
3800*38fd1498Szrj 		}
3801*38fd1498Szrj 
3802*38fd1498Szrj 	      if (*p++ == '}')
3803*38fd1498Szrj 		break;
3804*38fd1498Szrj             }
3805*38fd1498Szrj           while (1);
3806*38fd1498Szrj 
3807*38fd1498Szrj           *dialect = 0;
3808*38fd1498Szrj         }
3809*38fd1498Szrj       else
3810*38fd1498Szrj         putc (c, asm_out_file);
3811*38fd1498Szrj       break;
3812*38fd1498Szrj 
3813*38fd1498Szrj     case '}':
3814*38fd1498Szrj       if (! *dialect)
3815*38fd1498Szrj         putc (c, asm_out_file);
3816*38fd1498Szrj       *dialect = 0;
3817*38fd1498Szrj       break;
3818*38fd1498Szrj     default:
3819*38fd1498Szrj       gcc_unreachable ();
3820*38fd1498Szrj     }
3821*38fd1498Szrj 
3822*38fd1498Szrj   return p;
3823*38fd1498Szrj }
3824*38fd1498Szrj #endif
3825*38fd1498Szrj 
3826*38fd1498Szrj /* Output text from TEMPLATE to the assembler output file,
3827*38fd1498Szrj    obeying %-directions to substitute operands taken from
3828*38fd1498Szrj    the vector OPERANDS.
3829*38fd1498Szrj 
3830*38fd1498Szrj    %N (for N a digit) means print operand N in usual manner.
3831*38fd1498Szrj    %lN means require operand N to be a CODE_LABEL or LABEL_REF
3832*38fd1498Szrj       and print the label name with no punctuation.
3833*38fd1498Szrj    %cN means require operand N to be a constant
3834*38fd1498Szrj       and print the constant expression with no punctuation.
3835*38fd1498Szrj    %aN means expect operand N to be a memory address
3836*38fd1498Szrj       (not a memory reference!) and print a reference
3837*38fd1498Szrj       to that address.
3838*38fd1498Szrj    %nN means expect operand N to be a constant
3839*38fd1498Szrj       and print a constant expression for minus the value
3840*38fd1498Szrj       of the operand, with no other punctuation.  */
3841*38fd1498Szrj 
3842*38fd1498Szrj void
3843*38fd1498Szrj output_asm_insn (const char *templ, rtx *operands)
3844*38fd1498Szrj {
3845*38fd1498Szrj   const char *p;
3846*38fd1498Szrj   int c;
3847*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
3848*38fd1498Szrj   int dialect = 0;
3849*38fd1498Szrj #endif
3850*38fd1498Szrj   int oporder[MAX_RECOG_OPERANDS];
3851*38fd1498Szrj   char opoutput[MAX_RECOG_OPERANDS];
3852*38fd1498Szrj   int ops = 0;
3853*38fd1498Szrj 
3854*38fd1498Szrj   /* An insn may return a null string template
3855*38fd1498Szrj      in a case where no assembler code is needed.  */
3856*38fd1498Szrj   if (*templ == 0)
3857*38fd1498Szrj     return;
3858*38fd1498Szrj 
3859*38fd1498Szrj   memset (opoutput, 0, sizeof opoutput);
3860*38fd1498Szrj   p = templ;
3861*38fd1498Szrj   putc ('\t', asm_out_file);
3862*38fd1498Szrj 
3863*38fd1498Szrj #ifdef ASM_OUTPUT_OPCODE
3864*38fd1498Szrj   ASM_OUTPUT_OPCODE (asm_out_file, p);
3865*38fd1498Szrj #endif
3866*38fd1498Szrj 
3867*38fd1498Szrj   while ((c = *p++))
3868*38fd1498Szrj     switch (c)
3869*38fd1498Szrj       {
3870*38fd1498Szrj       case '\n':
3871*38fd1498Szrj 	if (flag_verbose_asm)
3872*38fd1498Szrj 	  output_asm_operand_names (operands, oporder, ops);
3873*38fd1498Szrj 	if (flag_print_asm_name)
3874*38fd1498Szrj 	  output_asm_name ();
3875*38fd1498Szrj 
3876*38fd1498Szrj 	ops = 0;
3877*38fd1498Szrj 	memset (opoutput, 0, sizeof opoutput);
3878*38fd1498Szrj 
3879*38fd1498Szrj 	putc (c, asm_out_file);
3880*38fd1498Szrj #ifdef ASM_OUTPUT_OPCODE
3881*38fd1498Szrj 	while ((c = *p) == '\t')
3882*38fd1498Szrj 	  {
3883*38fd1498Szrj 	    putc (c, asm_out_file);
3884*38fd1498Szrj 	    p++;
3885*38fd1498Szrj 	  }
3886*38fd1498Szrj 	ASM_OUTPUT_OPCODE (asm_out_file, p);
3887*38fd1498Szrj #endif
3888*38fd1498Szrj 	break;
3889*38fd1498Szrj 
3890*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
3891*38fd1498Szrj       case '{':
3892*38fd1498Szrj       case '}':
3893*38fd1498Szrj       case '|':
3894*38fd1498Szrj 	p = do_assembler_dialects (p, &dialect);
3895*38fd1498Szrj 	break;
3896*38fd1498Szrj #endif
3897*38fd1498Szrj 
3898*38fd1498Szrj       case '%':
3899*38fd1498Szrj 	/* %% outputs a single %.  %{, %} and %| print {, } and | respectively
3900*38fd1498Szrj 	   if ASSEMBLER_DIALECT defined and these characters have a special
3901*38fd1498Szrj 	   meaning as dialect delimiters.*/
3902*38fd1498Szrj 	if (*p == '%'
3903*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
3904*38fd1498Szrj 	    || *p == '{' || *p == '}' || *p == '|'
3905*38fd1498Szrj #endif
3906*38fd1498Szrj 	    )
3907*38fd1498Szrj 	  {
3908*38fd1498Szrj 	    putc (*p, asm_out_file);
3909*38fd1498Szrj 	    p++;
3910*38fd1498Szrj 	  }
3911*38fd1498Szrj 	/* %= outputs a number which is unique to each insn in the entire
3912*38fd1498Szrj 	   compilation.  This is useful for making local labels that are
3913*38fd1498Szrj 	   referred to more than once in a given insn.  */
3914*38fd1498Szrj 	else if (*p == '=')
3915*38fd1498Szrj 	  {
3916*38fd1498Szrj 	    p++;
3917*38fd1498Szrj 	    fprintf (asm_out_file, "%d", insn_counter);
3918*38fd1498Szrj 	  }
3919*38fd1498Szrj 	/* % followed by a letter and some digits
3920*38fd1498Szrj 	   outputs an operand in a special way depending on the letter.
3921*38fd1498Szrj 	   Letters `acln' are implemented directly.
3922*38fd1498Szrj 	   Other letters are passed to `output_operand' so that
3923*38fd1498Szrj 	   the TARGET_PRINT_OPERAND hook can define them.  */
3924*38fd1498Szrj 	else if (ISALPHA (*p))
3925*38fd1498Szrj 	  {
3926*38fd1498Szrj 	    int letter = *p++;
3927*38fd1498Szrj 	    unsigned long opnum;
3928*38fd1498Szrj 	    char *endptr;
3929*38fd1498Szrj 
3930*38fd1498Szrj 	    opnum = strtoul (p, &endptr, 10);
3931*38fd1498Szrj 
3932*38fd1498Szrj 	    if (endptr == p)
3933*38fd1498Szrj 	      output_operand_lossage ("operand number missing "
3934*38fd1498Szrj 				      "after %%-letter");
3935*38fd1498Szrj 	    else if (this_is_asm_operands && opnum >= insn_noperands)
3936*38fd1498Szrj 	      output_operand_lossage ("operand number out of range");
3937*38fd1498Szrj 	    else if (letter == 'l')
3938*38fd1498Szrj 	      output_asm_label (operands[opnum]);
3939*38fd1498Szrj 	    else if (letter == 'a')
3940*38fd1498Szrj 	      output_address (VOIDmode, operands[opnum]);
3941*38fd1498Szrj 	    else if (letter == 'c')
3942*38fd1498Szrj 	      {
3943*38fd1498Szrj 		if (CONSTANT_ADDRESS_P (operands[opnum]))
3944*38fd1498Szrj 		  output_addr_const (asm_out_file, operands[opnum]);
3945*38fd1498Szrj 		else
3946*38fd1498Szrj 		  output_operand (operands[opnum], 'c');
3947*38fd1498Szrj 	      }
3948*38fd1498Szrj 	    else if (letter == 'n')
3949*38fd1498Szrj 	      {
3950*38fd1498Szrj 		if (CONST_INT_P (operands[opnum]))
3951*38fd1498Szrj 		  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
3952*38fd1498Szrj 			   - INTVAL (operands[opnum]));
3953*38fd1498Szrj 		else
3954*38fd1498Szrj 		  {
3955*38fd1498Szrj 		    putc ('-', asm_out_file);
3956*38fd1498Szrj 		    output_addr_const (asm_out_file, operands[opnum]);
3957*38fd1498Szrj 		  }
3958*38fd1498Szrj 	      }
3959*38fd1498Szrj 	    else
3960*38fd1498Szrj 	      output_operand (operands[opnum], letter);
3961*38fd1498Szrj 
3962*38fd1498Szrj 	    if (!opoutput[opnum])
3963*38fd1498Szrj 	      oporder[ops++] = opnum;
3964*38fd1498Szrj 	    opoutput[opnum] = 1;
3965*38fd1498Szrj 
3966*38fd1498Szrj 	    p = endptr;
3967*38fd1498Szrj 	    c = *p;
3968*38fd1498Szrj 	  }
3969*38fd1498Szrj 	/* % followed by a digit outputs an operand the default way.  */
3970*38fd1498Szrj 	else if (ISDIGIT (*p))
3971*38fd1498Szrj 	  {
3972*38fd1498Szrj 	    unsigned long opnum;
3973*38fd1498Szrj 	    char *endptr;
3974*38fd1498Szrj 
3975*38fd1498Szrj 	    opnum = strtoul (p, &endptr, 10);
3976*38fd1498Szrj 	    if (this_is_asm_operands && opnum >= insn_noperands)
3977*38fd1498Szrj 	      output_operand_lossage ("operand number out of range");
3978*38fd1498Szrj 	    else
3979*38fd1498Szrj 	      output_operand (operands[opnum], 0);
3980*38fd1498Szrj 
3981*38fd1498Szrj 	    if (!opoutput[opnum])
3982*38fd1498Szrj 	      oporder[ops++] = opnum;
3983*38fd1498Szrj 	    opoutput[opnum] = 1;
3984*38fd1498Szrj 
3985*38fd1498Szrj 	    p = endptr;
3986*38fd1498Szrj 	    c = *p;
3987*38fd1498Szrj 	  }
3988*38fd1498Szrj 	/* % followed by punctuation: output something for that
3989*38fd1498Szrj 	   punctuation character alone, with no operand.  The
3990*38fd1498Szrj 	   TARGET_PRINT_OPERAND hook decides what is actually done.  */
3991*38fd1498Szrj 	else if (targetm.asm_out.print_operand_punct_valid_p ((unsigned char) *p))
3992*38fd1498Szrj 	  output_operand (NULL_RTX, *p++);
3993*38fd1498Szrj 	else
3994*38fd1498Szrj 	  output_operand_lossage ("invalid %%-code");
3995*38fd1498Szrj 	break;
3996*38fd1498Szrj 
3997*38fd1498Szrj       default:
3998*38fd1498Szrj 	putc (c, asm_out_file);
3999*38fd1498Szrj       }
4000*38fd1498Szrj 
4001*38fd1498Szrj   /* Try to keep the asm a bit more readable.  */
4002*38fd1498Szrj   if ((flag_verbose_asm || flag_print_asm_name) && strlen (templ) < 9)
4003*38fd1498Szrj     putc ('\t', asm_out_file);
4004*38fd1498Szrj 
4005*38fd1498Szrj   /* Write out the variable names for operands, if we know them.  */
4006*38fd1498Szrj   if (flag_verbose_asm)
4007*38fd1498Szrj     output_asm_operand_names (operands, oporder, ops);
4008*38fd1498Szrj   if (flag_print_asm_name)
4009*38fd1498Szrj     output_asm_name ();
4010*38fd1498Szrj 
4011*38fd1498Szrj   putc ('\n', asm_out_file);
4012*38fd1498Szrj }
4013*38fd1498Szrj 
4014*38fd1498Szrj /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol.  */
4015*38fd1498Szrj 
4016*38fd1498Szrj void
4017*38fd1498Szrj output_asm_label (rtx x)
4018*38fd1498Szrj {
4019*38fd1498Szrj   char buf[256];
4020*38fd1498Szrj 
4021*38fd1498Szrj   if (GET_CODE (x) == LABEL_REF)
4022*38fd1498Szrj     x = label_ref_label (x);
4023*38fd1498Szrj   if (LABEL_P (x)
4024*38fd1498Szrj       || (NOTE_P (x)
4025*38fd1498Szrj 	  && NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL))
4026*38fd1498Szrj     ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
4027*38fd1498Szrj   else
4028*38fd1498Szrj     output_operand_lossage ("'%%l' operand isn't a label");
4029*38fd1498Szrj 
4030*38fd1498Szrj   assemble_name (asm_out_file, buf);
4031*38fd1498Szrj }
4032*38fd1498Szrj 
4033*38fd1498Szrj /* Marks SYMBOL_REFs in x as referenced through use of assemble_external.  */
4034*38fd1498Szrj 
4035*38fd1498Szrj void
4036*38fd1498Szrj mark_symbol_refs_as_used (rtx x)
4037*38fd1498Szrj {
4038*38fd1498Szrj   subrtx_iterator::array_type array;
4039*38fd1498Szrj   FOR_EACH_SUBRTX (iter, array, x, ALL)
4040*38fd1498Szrj     {
4041*38fd1498Szrj       const_rtx x = *iter;
4042*38fd1498Szrj       if (GET_CODE (x) == SYMBOL_REF)
4043*38fd1498Szrj 	if (tree t = SYMBOL_REF_DECL (x))
4044*38fd1498Szrj 	  assemble_external (t);
4045*38fd1498Szrj     }
4046*38fd1498Szrj }
4047*38fd1498Szrj 
4048*38fd1498Szrj /* Print operand X using machine-dependent assembler syntax.
4049*38fd1498Szrj    CODE is a non-digit that preceded the operand-number in the % spec,
4050*38fd1498Szrj    such as 'z' if the spec was `%z3'.  CODE is 0 if there was no char
4051*38fd1498Szrj    between the % and the digits.
4052*38fd1498Szrj    When CODE is a non-letter, X is 0.
4053*38fd1498Szrj 
4054*38fd1498Szrj    The meanings of the letters are machine-dependent and controlled
4055*38fd1498Szrj    by TARGET_PRINT_OPERAND.  */
4056*38fd1498Szrj 
4057*38fd1498Szrj void
4058*38fd1498Szrj output_operand (rtx x, int code ATTRIBUTE_UNUSED)
4059*38fd1498Szrj {
4060*38fd1498Szrj   if (x && GET_CODE (x) == SUBREG)
4061*38fd1498Szrj     x = alter_subreg (&x, true);
4062*38fd1498Szrj 
4063*38fd1498Szrj   /* X must not be a pseudo reg.  */
4064*38fd1498Szrj   if (!targetm.no_register_allocation)
4065*38fd1498Szrj     gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
4066*38fd1498Szrj 
4067*38fd1498Szrj   targetm.asm_out.print_operand (asm_out_file, x, code);
4068*38fd1498Szrj 
4069*38fd1498Szrj   if (x == NULL_RTX)
4070*38fd1498Szrj     return;
4071*38fd1498Szrj 
4072*38fd1498Szrj   mark_symbol_refs_as_used (x);
4073*38fd1498Szrj }
4074*38fd1498Szrj 
4075*38fd1498Szrj /* Print a memory reference operand for address X using
4076*38fd1498Szrj    machine-dependent assembler syntax.  */
4077*38fd1498Szrj 
4078*38fd1498Szrj void
4079*38fd1498Szrj output_address (machine_mode mode, rtx x)
4080*38fd1498Szrj {
4081*38fd1498Szrj   bool changed = false;
4082*38fd1498Szrj   walk_alter_subreg (&x, &changed);
4083*38fd1498Szrj   targetm.asm_out.print_operand_address (asm_out_file, mode, x);
4084*38fd1498Szrj }
4085*38fd1498Szrj 
4086*38fd1498Szrj /* Print an integer constant expression in assembler syntax.
4087*38fd1498Szrj    Addition and subtraction are the only arithmetic
4088*38fd1498Szrj    that may appear in these expressions.  */
4089*38fd1498Szrj 
4090*38fd1498Szrj void
4091*38fd1498Szrj output_addr_const (FILE *file, rtx x)
4092*38fd1498Szrj {
4093*38fd1498Szrj   char buf[256];
4094*38fd1498Szrj 
4095*38fd1498Szrj  restart:
4096*38fd1498Szrj   switch (GET_CODE (x))
4097*38fd1498Szrj     {
4098*38fd1498Szrj     case PC:
4099*38fd1498Szrj       putc ('.', file);
4100*38fd1498Szrj       break;
4101*38fd1498Szrj 
4102*38fd1498Szrj     case SYMBOL_REF:
4103*38fd1498Szrj       if (SYMBOL_REF_DECL (x))
4104*38fd1498Szrj 	assemble_external (SYMBOL_REF_DECL (x));
4105*38fd1498Szrj #ifdef ASM_OUTPUT_SYMBOL_REF
4106*38fd1498Szrj       ASM_OUTPUT_SYMBOL_REF (file, x);
4107*38fd1498Szrj #else
4108*38fd1498Szrj       assemble_name (file, XSTR (x, 0));
4109*38fd1498Szrj #endif
4110*38fd1498Szrj       break;
4111*38fd1498Szrj 
4112*38fd1498Szrj     case LABEL_REF:
4113*38fd1498Szrj       x = label_ref_label (x);
4114*38fd1498Szrj       /* Fall through.  */
4115*38fd1498Szrj     case CODE_LABEL:
4116*38fd1498Szrj       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
4117*38fd1498Szrj #ifdef ASM_OUTPUT_LABEL_REF
4118*38fd1498Szrj       ASM_OUTPUT_LABEL_REF (file, buf);
4119*38fd1498Szrj #else
4120*38fd1498Szrj       assemble_name (file, buf);
4121*38fd1498Szrj #endif
4122*38fd1498Szrj       break;
4123*38fd1498Szrj 
4124*38fd1498Szrj     case CONST_INT:
4125*38fd1498Szrj       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
4126*38fd1498Szrj       break;
4127*38fd1498Szrj 
4128*38fd1498Szrj     case CONST:
4129*38fd1498Szrj       /* This used to output parentheses around the expression,
4130*38fd1498Szrj 	 but that does not work on the 386 (either ATT or BSD assembler).  */
4131*38fd1498Szrj       output_addr_const (file, XEXP (x, 0));
4132*38fd1498Szrj       break;
4133*38fd1498Szrj 
4134*38fd1498Szrj     case CONST_WIDE_INT:
4135*38fd1498Szrj       /* We do not know the mode here so we have to use a round about
4136*38fd1498Szrj 	 way to build a wide-int to get it printed properly.  */
4137*38fd1498Szrj       {
4138*38fd1498Szrj 	wide_int w = wide_int::from_array (&CONST_WIDE_INT_ELT (x, 0),
4139*38fd1498Szrj 					   CONST_WIDE_INT_NUNITS (x),
4140*38fd1498Szrj 					   CONST_WIDE_INT_NUNITS (x)
4141*38fd1498Szrj 					   * HOST_BITS_PER_WIDE_INT,
4142*38fd1498Szrj 					   false);
4143*38fd1498Szrj 	print_decs (w, file);
4144*38fd1498Szrj       }
4145*38fd1498Szrj       break;
4146*38fd1498Szrj 
4147*38fd1498Szrj     case CONST_DOUBLE:
4148*38fd1498Szrj       if (CONST_DOUBLE_AS_INT_P (x))
4149*38fd1498Szrj 	{
4150*38fd1498Szrj 	  /* We can use %d if the number is one word and positive.  */
4151*38fd1498Szrj 	  if (CONST_DOUBLE_HIGH (x))
4152*38fd1498Szrj 	    fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
4153*38fd1498Szrj 		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x),
4154*38fd1498Szrj 		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x));
4155*38fd1498Szrj 	  else if (CONST_DOUBLE_LOW (x) < 0)
4156*38fd1498Szrj 	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
4157*38fd1498Szrj 		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x));
4158*38fd1498Szrj 	  else
4159*38fd1498Szrj 	    fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
4160*38fd1498Szrj 	}
4161*38fd1498Szrj       else
4162*38fd1498Szrj 	/* We can't handle floating point constants;
4163*38fd1498Szrj 	   PRINT_OPERAND must handle them.  */
4164*38fd1498Szrj 	output_operand_lossage ("floating constant misused");
4165*38fd1498Szrj       break;
4166*38fd1498Szrj 
4167*38fd1498Szrj     case CONST_FIXED:
4168*38fd1498Szrj       fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x));
4169*38fd1498Szrj       break;
4170*38fd1498Szrj 
4171*38fd1498Szrj     case PLUS:
4172*38fd1498Szrj       /* Some assemblers need integer constants to appear last (eg masm).  */
4173*38fd1498Szrj       if (CONST_INT_P (XEXP (x, 0)))
4174*38fd1498Szrj 	{
4175*38fd1498Szrj 	  output_addr_const (file, XEXP (x, 1));
4176*38fd1498Szrj 	  if (INTVAL (XEXP (x, 0)) >= 0)
4177*38fd1498Szrj 	    fprintf (file, "+");
4178*38fd1498Szrj 	  output_addr_const (file, XEXP (x, 0));
4179*38fd1498Szrj 	}
4180*38fd1498Szrj       else
4181*38fd1498Szrj 	{
4182*38fd1498Szrj 	  output_addr_const (file, XEXP (x, 0));
4183*38fd1498Szrj 	  if (!CONST_INT_P (XEXP (x, 1))
4184*38fd1498Szrj 	      || INTVAL (XEXP (x, 1)) >= 0)
4185*38fd1498Szrj 	    fprintf (file, "+");
4186*38fd1498Szrj 	  output_addr_const (file, XEXP (x, 1));
4187*38fd1498Szrj 	}
4188*38fd1498Szrj       break;
4189*38fd1498Szrj 
4190*38fd1498Szrj     case MINUS:
4191*38fd1498Szrj       /* Avoid outputting things like x-x or x+5-x,
4192*38fd1498Szrj 	 since some assemblers can't handle that.  */
4193*38fd1498Szrj       x = simplify_subtraction (x);
4194*38fd1498Szrj       if (GET_CODE (x) != MINUS)
4195*38fd1498Szrj 	goto restart;
4196*38fd1498Szrj 
4197*38fd1498Szrj       output_addr_const (file, XEXP (x, 0));
4198*38fd1498Szrj       fprintf (file, "-");
4199*38fd1498Szrj       if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0)
4200*38fd1498Szrj 	  || GET_CODE (XEXP (x, 1)) == PC
4201*38fd1498Szrj 	  || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
4202*38fd1498Szrj 	output_addr_const (file, XEXP (x, 1));
4203*38fd1498Szrj       else
4204*38fd1498Szrj 	{
4205*38fd1498Szrj 	  fputs (targetm.asm_out.open_paren, file);
4206*38fd1498Szrj 	  output_addr_const (file, XEXP (x, 1));
4207*38fd1498Szrj 	  fputs (targetm.asm_out.close_paren, file);
4208*38fd1498Szrj 	}
4209*38fd1498Szrj       break;
4210*38fd1498Szrj 
4211*38fd1498Szrj     case ZERO_EXTEND:
4212*38fd1498Szrj     case SIGN_EXTEND:
4213*38fd1498Szrj     case SUBREG:
4214*38fd1498Szrj     case TRUNCATE:
4215*38fd1498Szrj       output_addr_const (file, XEXP (x, 0));
4216*38fd1498Szrj       break;
4217*38fd1498Szrj 
4218*38fd1498Szrj     default:
4219*38fd1498Szrj       if (targetm.asm_out.output_addr_const_extra (file, x))
4220*38fd1498Szrj 	break;
4221*38fd1498Szrj 
4222*38fd1498Szrj       output_operand_lossage ("invalid expression as operand");
4223*38fd1498Szrj     }
4224*38fd1498Szrj }
4225*38fd1498Szrj 
4226*38fd1498Szrj /* Output a quoted string.  */
4227*38fd1498Szrj 
4228*38fd1498Szrj void
4229*38fd1498Szrj output_quoted_string (FILE *asm_file, const char *string)
4230*38fd1498Szrj {
4231*38fd1498Szrj #ifdef OUTPUT_QUOTED_STRING
4232*38fd1498Szrj   OUTPUT_QUOTED_STRING (asm_file, string);
4233*38fd1498Szrj #else
4234*38fd1498Szrj   char c;
4235*38fd1498Szrj 
4236*38fd1498Szrj   putc ('\"', asm_file);
4237*38fd1498Szrj   while ((c = *string++) != 0)
4238*38fd1498Szrj     {
4239*38fd1498Szrj       if (ISPRINT (c))
4240*38fd1498Szrj 	{
4241*38fd1498Szrj 	  if (c == '\"' || c == '\\')
4242*38fd1498Szrj 	    putc ('\\', asm_file);
4243*38fd1498Szrj 	  putc (c, asm_file);
4244*38fd1498Szrj 	}
4245*38fd1498Szrj       else
4246*38fd1498Szrj 	fprintf (asm_file, "\\%03o", (unsigned char) c);
4247*38fd1498Szrj     }
4248*38fd1498Szrj   putc ('\"', asm_file);
4249*38fd1498Szrj #endif
4250*38fd1498Szrj }
4251*38fd1498Szrj 
4252*38fd1498Szrj /* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */
4253*38fd1498Szrj 
4254*38fd1498Szrj void
4255*38fd1498Szrj fprint_whex (FILE *f, unsigned HOST_WIDE_INT value)
4256*38fd1498Szrj {
4257*38fd1498Szrj   char buf[2 + CHAR_BIT * sizeof (value) / 4];
4258*38fd1498Szrj   if (value == 0)
4259*38fd1498Szrj     putc ('0', f);
4260*38fd1498Szrj   else
4261*38fd1498Szrj     {
4262*38fd1498Szrj       char *p = buf + sizeof (buf);
4263*38fd1498Szrj       do
4264*38fd1498Szrj         *--p = "0123456789abcdef"[value % 16];
4265*38fd1498Szrj       while ((value /= 16) != 0);
4266*38fd1498Szrj       *--p = 'x';
4267*38fd1498Szrj       *--p = '0';
4268*38fd1498Szrj       fwrite (p, 1, buf + sizeof (buf) - p, f);
4269*38fd1498Szrj     }
4270*38fd1498Szrj }
4271*38fd1498Szrj 
4272*38fd1498Szrj /* Internal function that prints an unsigned long in decimal in reverse.
4273*38fd1498Szrj    The output string IS NOT null-terminated. */
4274*38fd1498Szrj 
4275*38fd1498Szrj static int
4276*38fd1498Szrj sprint_ul_rev (char *s, unsigned long value)
4277*38fd1498Szrj {
4278*38fd1498Szrj   int i = 0;
4279*38fd1498Szrj   do
4280*38fd1498Szrj     {
4281*38fd1498Szrj       s[i] = "0123456789"[value % 10];
4282*38fd1498Szrj       value /= 10;
4283*38fd1498Szrj       i++;
4284*38fd1498Szrj       /* alternate version, without modulo */
4285*38fd1498Szrj       /* oldval = value; */
4286*38fd1498Szrj       /* value /= 10; */
4287*38fd1498Szrj       /* s[i] = "0123456789" [oldval - 10*value]; */
4288*38fd1498Szrj       /* i++ */
4289*38fd1498Szrj     }
4290*38fd1498Szrj   while (value != 0);
4291*38fd1498Szrj   return i;
4292*38fd1498Szrj }
4293*38fd1498Szrj 
4294*38fd1498Szrj /* Write an unsigned long as decimal to a file, fast. */
4295*38fd1498Szrj 
4296*38fd1498Szrj void
4297*38fd1498Szrj fprint_ul (FILE *f, unsigned long value)
4298*38fd1498Szrj {
4299*38fd1498Szrj   /* python says: len(str(2**64)) == 20 */
4300*38fd1498Szrj   char s[20];
4301*38fd1498Szrj   int i;
4302*38fd1498Szrj 
4303*38fd1498Szrj   i = sprint_ul_rev (s, value);
4304*38fd1498Szrj 
4305*38fd1498Szrj   /* It's probably too small to bother with string reversal and fputs. */
4306*38fd1498Szrj   do
4307*38fd1498Szrj     {
4308*38fd1498Szrj       i--;
4309*38fd1498Szrj       putc (s[i], f);
4310*38fd1498Szrj     }
4311*38fd1498Szrj   while (i != 0);
4312*38fd1498Szrj }
4313*38fd1498Szrj 
4314*38fd1498Szrj /* Write an unsigned long as decimal to a string, fast.
4315*38fd1498Szrj    s must be wide enough to not overflow, at least 21 chars.
4316*38fd1498Szrj    Returns the length of the string (without terminating '\0'). */
4317*38fd1498Szrj 
4318*38fd1498Szrj int
4319*38fd1498Szrj sprint_ul (char *s, unsigned long value)
4320*38fd1498Szrj {
4321*38fd1498Szrj   int len = sprint_ul_rev (s, value);
4322*38fd1498Szrj   s[len] = '\0';
4323*38fd1498Szrj 
4324*38fd1498Szrj   std::reverse (s, s + len);
4325*38fd1498Szrj   return len;
4326*38fd1498Szrj }
4327*38fd1498Szrj 
4328*38fd1498Szrj /* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
4329*38fd1498Szrj    %R prints the value of REGISTER_PREFIX.
4330*38fd1498Szrj    %L prints the value of LOCAL_LABEL_PREFIX.
4331*38fd1498Szrj    %U prints the value of USER_LABEL_PREFIX.
4332*38fd1498Szrj    %I prints the value of IMMEDIATE_PREFIX.
4333*38fd1498Szrj    %O runs ASM_OUTPUT_OPCODE to transform what follows in the string.
4334*38fd1498Szrj    Also supported are %d, %i, %u, %x, %X, %o, %c, %s and %%.
4335*38fd1498Szrj 
4336*38fd1498Szrj    We handle alternate assembler dialects here, just like output_asm_insn.  */
4337*38fd1498Szrj 
4338*38fd1498Szrj void
4339*38fd1498Szrj asm_fprintf (FILE *file, const char *p, ...)
4340*38fd1498Szrj {
4341*38fd1498Szrj   char buf[10];
4342*38fd1498Szrj   char *q, c;
4343*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
4344*38fd1498Szrj   int dialect = 0;
4345*38fd1498Szrj #endif
4346*38fd1498Szrj   va_list argptr;
4347*38fd1498Szrj 
4348*38fd1498Szrj   va_start (argptr, p);
4349*38fd1498Szrj 
4350*38fd1498Szrj   buf[0] = '%';
4351*38fd1498Szrj 
4352*38fd1498Szrj   while ((c = *p++))
4353*38fd1498Szrj     switch (c)
4354*38fd1498Szrj       {
4355*38fd1498Szrj #ifdef ASSEMBLER_DIALECT
4356*38fd1498Szrj       case '{':
4357*38fd1498Szrj       case '}':
4358*38fd1498Szrj       case '|':
4359*38fd1498Szrj 	p = do_assembler_dialects (p, &dialect);
4360*38fd1498Szrj 	break;
4361*38fd1498Szrj #endif
4362*38fd1498Szrj 
4363*38fd1498Szrj       case '%':
4364*38fd1498Szrj 	c = *p++;
4365*38fd1498Szrj 	q = &buf[1];
4366*38fd1498Szrj 	while (strchr ("-+ #0", c))
4367*38fd1498Szrj 	  {
4368*38fd1498Szrj 	    *q++ = c;
4369*38fd1498Szrj 	    c = *p++;
4370*38fd1498Szrj 	  }
4371*38fd1498Szrj 	while (ISDIGIT (c) || c == '.')
4372*38fd1498Szrj 	  {
4373*38fd1498Szrj 	    *q++ = c;
4374*38fd1498Szrj 	    c = *p++;
4375*38fd1498Szrj 	  }
4376*38fd1498Szrj 	switch (c)
4377*38fd1498Szrj 	  {
4378*38fd1498Szrj 	  case '%':
4379*38fd1498Szrj 	    putc ('%', file);
4380*38fd1498Szrj 	    break;
4381*38fd1498Szrj 
4382*38fd1498Szrj 	  case 'd':  case 'i':  case 'u':
4383*38fd1498Szrj 	  case 'x':  case 'X':  case 'o':
4384*38fd1498Szrj 	  case 'c':
4385*38fd1498Szrj 	    *q++ = c;
4386*38fd1498Szrj 	    *q = 0;
4387*38fd1498Szrj 	    fprintf (file, buf, va_arg (argptr, int));
4388*38fd1498Szrj 	    break;
4389*38fd1498Szrj 
4390*38fd1498Szrj 	  case 'w':
4391*38fd1498Szrj 	    /* This is a prefix to the 'd', 'i', 'u', 'x', 'X', and
4392*38fd1498Szrj 	       'o' cases, but we do not check for those cases.  It
4393*38fd1498Szrj 	       means that the value is a HOST_WIDE_INT, which may be
4394*38fd1498Szrj 	       either `long' or `long long'.  */
4395*38fd1498Szrj 	    memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT));
4396*38fd1498Szrj 	    q += strlen (HOST_WIDE_INT_PRINT);
4397*38fd1498Szrj 	    *q++ = *p++;
4398*38fd1498Szrj 	    *q = 0;
4399*38fd1498Szrj 	    fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT));
4400*38fd1498Szrj 	    break;
4401*38fd1498Szrj 
4402*38fd1498Szrj 	  case 'l':
4403*38fd1498Szrj 	    *q++ = c;
4404*38fd1498Szrj #ifdef HAVE_LONG_LONG
4405*38fd1498Szrj 	    if (*p == 'l')
4406*38fd1498Szrj 	      {
4407*38fd1498Szrj 		*q++ = *p++;
4408*38fd1498Szrj 		*q++ = *p++;
4409*38fd1498Szrj 		*q = 0;
4410*38fd1498Szrj 		fprintf (file, buf, va_arg (argptr, long long));
4411*38fd1498Szrj 	      }
4412*38fd1498Szrj 	    else
4413*38fd1498Szrj #endif
4414*38fd1498Szrj 	      {
4415*38fd1498Szrj 		*q++ = *p++;
4416*38fd1498Szrj 		*q = 0;
4417*38fd1498Szrj 		fprintf (file, buf, va_arg (argptr, long));
4418*38fd1498Szrj 	      }
4419*38fd1498Szrj 
4420*38fd1498Szrj 	    break;
4421*38fd1498Szrj 
4422*38fd1498Szrj 	  case 's':
4423*38fd1498Szrj 	    *q++ = c;
4424*38fd1498Szrj 	    *q = 0;
4425*38fd1498Szrj 	    fprintf (file, buf, va_arg (argptr, char *));
4426*38fd1498Szrj 	    break;
4427*38fd1498Szrj 
4428*38fd1498Szrj 	  case 'O':
4429*38fd1498Szrj #ifdef ASM_OUTPUT_OPCODE
4430*38fd1498Szrj 	    ASM_OUTPUT_OPCODE (asm_out_file, p);
4431*38fd1498Szrj #endif
4432*38fd1498Szrj 	    break;
4433*38fd1498Szrj 
4434*38fd1498Szrj 	  case 'R':
4435*38fd1498Szrj #ifdef REGISTER_PREFIX
4436*38fd1498Szrj 	    fprintf (file, "%s", REGISTER_PREFIX);
4437*38fd1498Szrj #endif
4438*38fd1498Szrj 	    break;
4439*38fd1498Szrj 
4440*38fd1498Szrj 	  case 'I':
4441*38fd1498Szrj #ifdef IMMEDIATE_PREFIX
4442*38fd1498Szrj 	    fprintf (file, "%s", IMMEDIATE_PREFIX);
4443*38fd1498Szrj #endif
4444*38fd1498Szrj 	    break;
4445*38fd1498Szrj 
4446*38fd1498Szrj 	  case 'L':
4447*38fd1498Szrj #ifdef LOCAL_LABEL_PREFIX
4448*38fd1498Szrj 	    fprintf (file, "%s", LOCAL_LABEL_PREFIX);
4449*38fd1498Szrj #endif
4450*38fd1498Szrj 	    break;
4451*38fd1498Szrj 
4452*38fd1498Szrj 	  case 'U':
4453*38fd1498Szrj 	    fputs (user_label_prefix, file);
4454*38fd1498Szrj 	    break;
4455*38fd1498Szrj 
4456*38fd1498Szrj #ifdef ASM_FPRINTF_EXTENSIONS
4457*38fd1498Szrj 	    /* Uppercase letters are reserved for general use by asm_fprintf
4458*38fd1498Szrj 	       and so are not available to target specific code.  In order to
4459*38fd1498Szrj 	       prevent the ASM_FPRINTF_EXTENSIONS macro from using them then,
4460*38fd1498Szrj 	       they are defined here.  As they get turned into real extensions
4461*38fd1498Szrj 	       to asm_fprintf they should be removed from this list.  */
4462*38fd1498Szrj 	  case 'A': case 'B': case 'C': case 'D': case 'E':
4463*38fd1498Szrj 	  case 'F': case 'G': case 'H': case 'J': case 'K':
4464*38fd1498Szrj 	  case 'M': case 'N': case 'P': case 'Q': case 'S':
4465*38fd1498Szrj 	  case 'T': case 'V': case 'W': case 'Y': case 'Z':
4466*38fd1498Szrj 	    break;
4467*38fd1498Szrj 
4468*38fd1498Szrj 	  ASM_FPRINTF_EXTENSIONS (file, argptr, p)
4469*38fd1498Szrj #endif
4470*38fd1498Szrj 	  default:
4471*38fd1498Szrj 	    gcc_unreachable ();
4472*38fd1498Szrj 	  }
4473*38fd1498Szrj 	break;
4474*38fd1498Szrj 
4475*38fd1498Szrj       default:
4476*38fd1498Szrj 	putc (c, file);
4477*38fd1498Szrj       }
4478*38fd1498Szrj   va_end (argptr);
4479*38fd1498Szrj }
4480*38fd1498Szrj 
4481*38fd1498Szrj /* Return nonzero if this function has no function calls.  */
4482*38fd1498Szrj 
4483*38fd1498Szrj int
4484*38fd1498Szrj leaf_function_p (void)
4485*38fd1498Szrj {
4486*38fd1498Szrj   rtx_insn *insn;
4487*38fd1498Szrj 
4488*38fd1498Szrj   /* Ensure we walk the entire function body.  */
4489*38fd1498Szrj   gcc_assert (!in_sequence_p ());
4490*38fd1498Szrj 
4491*38fd1498Szrj   /* Some back-ends (e.g. s390) want leaf functions to stay leaf
4492*38fd1498Szrj      functions even if they call mcount.  */
4493*38fd1498Szrj   if (crtl->profile && !targetm.keep_leaf_when_profiled ())
4494*38fd1498Szrj     return 0;
4495*38fd1498Szrj 
4496*38fd1498Szrj   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4497*38fd1498Szrj     {
4498*38fd1498Szrj       if (CALL_P (insn)
4499*38fd1498Szrj 	  && ! SIBLING_CALL_P (insn))
4500*38fd1498Szrj 	return 0;
4501*38fd1498Szrj       if (NONJUMP_INSN_P (insn)
4502*38fd1498Szrj 	  && GET_CODE (PATTERN (insn)) == SEQUENCE
4503*38fd1498Szrj 	  && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
4504*38fd1498Szrj 	  && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
4505*38fd1498Szrj 	return 0;
4506*38fd1498Szrj     }
4507*38fd1498Szrj 
4508*38fd1498Szrj   return 1;
4509*38fd1498Szrj }
4510*38fd1498Szrj 
4511*38fd1498Szrj /* Return 1 if branch is a forward branch.
4512*38fd1498Szrj    Uses insn_shuid array, so it works only in the final pass.  May be used by
4513*38fd1498Szrj    output templates to customary add branch prediction hints.
4514*38fd1498Szrj  */
4515*38fd1498Szrj int
4516*38fd1498Szrj final_forward_branch_p (rtx_insn *insn)
4517*38fd1498Szrj {
4518*38fd1498Szrj   int insn_id, label_id;
4519*38fd1498Szrj 
4520*38fd1498Szrj   gcc_assert (uid_shuid);
4521*38fd1498Szrj   insn_id = INSN_SHUID (insn);
4522*38fd1498Szrj   label_id = INSN_SHUID (JUMP_LABEL (insn));
4523*38fd1498Szrj   /* We've hit some insns that does not have id information available.  */
4524*38fd1498Szrj   gcc_assert (insn_id && label_id);
4525*38fd1498Szrj   return insn_id < label_id;
4526*38fd1498Szrj }
4527*38fd1498Szrj 
4528*38fd1498Szrj /* On some machines, a function with no call insns
4529*38fd1498Szrj    can run faster if it doesn't create its own register window.
4530*38fd1498Szrj    When output, the leaf function should use only the "output"
4531*38fd1498Szrj    registers.  Ordinarily, the function would be compiled to use
4532*38fd1498Szrj    the "input" registers to find its arguments; it is a candidate
4533*38fd1498Szrj    for leaf treatment if it uses only the "input" registers.
4534*38fd1498Szrj    Leaf function treatment means renumbering so the function
4535*38fd1498Szrj    uses the "output" registers instead.  */
4536*38fd1498Szrj 
4537*38fd1498Szrj #ifdef LEAF_REGISTERS
4538*38fd1498Szrj 
4539*38fd1498Szrj /* Return 1 if this function uses only the registers that can be
4540*38fd1498Szrj    safely renumbered.  */
4541*38fd1498Szrj 
4542*38fd1498Szrj int
4543*38fd1498Szrj only_leaf_regs_used (void)
4544*38fd1498Szrj {
4545*38fd1498Szrj   int i;
4546*38fd1498Szrj   const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS;
4547*38fd1498Szrj 
4548*38fd1498Szrj   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4549*38fd1498Szrj     if ((df_regs_ever_live_p (i) || global_regs[i])
4550*38fd1498Szrj 	&& ! permitted_reg_in_leaf_functions[i])
4551*38fd1498Szrj       return 0;
4552*38fd1498Szrj 
4553*38fd1498Szrj   if (crtl->uses_pic_offset_table
4554*38fd1498Szrj       && pic_offset_table_rtx != 0
4555*38fd1498Szrj       && REG_P (pic_offset_table_rtx)
4556*38fd1498Szrj       && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)])
4557*38fd1498Szrj     return 0;
4558*38fd1498Szrj 
4559*38fd1498Szrj   return 1;
4560*38fd1498Szrj }
4561*38fd1498Szrj 
4562*38fd1498Szrj /* Scan all instructions and renumber all registers into those
4563*38fd1498Szrj    available in leaf functions.  */
4564*38fd1498Szrj 
4565*38fd1498Szrj static void
4566*38fd1498Szrj leaf_renumber_regs (rtx_insn *first)
4567*38fd1498Szrj {
4568*38fd1498Szrj   rtx_insn *insn;
4569*38fd1498Szrj 
4570*38fd1498Szrj   /* Renumber only the actual patterns.
4571*38fd1498Szrj      The reg-notes can contain frame pointer refs,
4572*38fd1498Szrj      and renumbering them could crash, and should not be needed.  */
4573*38fd1498Szrj   for (insn = first; insn; insn = NEXT_INSN (insn))
4574*38fd1498Szrj     if (INSN_P (insn))
4575*38fd1498Szrj       leaf_renumber_regs_insn (PATTERN (insn));
4576*38fd1498Szrj }
4577*38fd1498Szrj 
4578*38fd1498Szrj /* Scan IN_RTX and its subexpressions, and renumber all regs into those
4579*38fd1498Szrj    available in leaf functions.  */
4580*38fd1498Szrj 
4581*38fd1498Szrj void
4582*38fd1498Szrj leaf_renumber_regs_insn (rtx in_rtx)
4583*38fd1498Szrj {
4584*38fd1498Szrj   int i, j;
4585*38fd1498Szrj   const char *format_ptr;
4586*38fd1498Szrj 
4587*38fd1498Szrj   if (in_rtx == 0)
4588*38fd1498Szrj     return;
4589*38fd1498Szrj 
4590*38fd1498Szrj   /* Renumber all input-registers into output-registers.
4591*38fd1498Szrj      renumbered_regs would be 1 for an output-register;
4592*38fd1498Szrj      they  */
4593*38fd1498Szrj 
4594*38fd1498Szrj   if (REG_P (in_rtx))
4595*38fd1498Szrj     {
4596*38fd1498Szrj       int newreg;
4597*38fd1498Szrj 
4598*38fd1498Szrj       /* Don't renumber the same reg twice.  */
4599*38fd1498Szrj       if (in_rtx->used)
4600*38fd1498Szrj 	return;
4601*38fd1498Szrj 
4602*38fd1498Szrj       newreg = REGNO (in_rtx);
4603*38fd1498Szrj       /* Don't try to renumber pseudo regs.  It is possible for a pseudo reg
4604*38fd1498Szrj 	 to reach here as part of a REG_NOTE.  */
4605*38fd1498Szrj       if (newreg >= FIRST_PSEUDO_REGISTER)
4606*38fd1498Szrj 	{
4607*38fd1498Szrj 	  in_rtx->used = 1;
4608*38fd1498Szrj 	  return;
4609*38fd1498Szrj 	}
4610*38fd1498Szrj       newreg = LEAF_REG_REMAP (newreg);
4611*38fd1498Szrj       gcc_assert (newreg >= 0);
4612*38fd1498Szrj       df_set_regs_ever_live (REGNO (in_rtx), false);
4613*38fd1498Szrj       df_set_regs_ever_live (newreg, true);
4614*38fd1498Szrj       SET_REGNO (in_rtx, newreg);
4615*38fd1498Szrj       in_rtx->used = 1;
4616*38fd1498Szrj       return;
4617*38fd1498Szrj     }
4618*38fd1498Szrj 
4619*38fd1498Szrj   if (INSN_P (in_rtx))
4620*38fd1498Szrj     {
4621*38fd1498Szrj       /* Inside a SEQUENCE, we find insns.
4622*38fd1498Szrj 	 Renumber just the patterns of these insns,
4623*38fd1498Szrj 	 just as we do for the top-level insns.  */
4624*38fd1498Szrj       leaf_renumber_regs_insn (PATTERN (in_rtx));
4625*38fd1498Szrj       return;
4626*38fd1498Szrj     }
4627*38fd1498Szrj 
4628*38fd1498Szrj   format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
4629*38fd1498Szrj 
4630*38fd1498Szrj   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
4631*38fd1498Szrj     switch (*format_ptr++)
4632*38fd1498Szrj       {
4633*38fd1498Szrj       case 'e':
4634*38fd1498Szrj 	leaf_renumber_regs_insn (XEXP (in_rtx, i));
4635*38fd1498Szrj 	break;
4636*38fd1498Szrj 
4637*38fd1498Szrj       case 'E':
4638*38fd1498Szrj 	if (XVEC (in_rtx, i) != NULL)
4639*38fd1498Szrj 	  for (j = 0; j < XVECLEN (in_rtx, i); j++)
4640*38fd1498Szrj 	    leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j));
4641*38fd1498Szrj 	break;
4642*38fd1498Szrj 
4643*38fd1498Szrj       case 'S':
4644*38fd1498Szrj       case 's':
4645*38fd1498Szrj       case '0':
4646*38fd1498Szrj       case 'i':
4647*38fd1498Szrj       case 'w':
4648*38fd1498Szrj       case 'p':
4649*38fd1498Szrj       case 'n':
4650*38fd1498Szrj       case 'u':
4651*38fd1498Szrj 	break;
4652*38fd1498Szrj 
4653*38fd1498Szrj       default:
4654*38fd1498Szrj 	gcc_unreachable ();
4655*38fd1498Szrj       }
4656*38fd1498Szrj }
4657*38fd1498Szrj #endif
4658*38fd1498Szrj 
4659*38fd1498Szrj /* Turn the RTL into assembly.  */
4660*38fd1498Szrj static unsigned int
4661*38fd1498Szrj rest_of_handle_final (void)
4662*38fd1498Szrj {
4663*38fd1498Szrj   const char *fnname = get_fnname_from_decl (current_function_decl);
4664*38fd1498Szrj 
4665*38fd1498Szrj   /* Turn debug markers into notes if the var-tracking pass has not
4666*38fd1498Szrj      been invoked.  */
4667*38fd1498Szrj   if (!flag_var_tracking && MAY_HAVE_DEBUG_MARKER_INSNS)
4668*38fd1498Szrj     delete_vta_debug_insns (false);
4669*38fd1498Szrj 
4670*38fd1498Szrj   assemble_start_function (current_function_decl, fnname);
4671*38fd1498Szrj   rtx_insn *first = get_insns ();
4672*38fd1498Szrj   int seen = 0;
4673*38fd1498Szrj   final_start_function_1 (&first, asm_out_file, &seen, optimize);
4674*38fd1498Szrj   final_1 (first, asm_out_file, seen, optimize);
4675*38fd1498Szrj   if (flag_ipa_ra
4676*38fd1498Szrj       && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)))
4677*38fd1498Szrj     collect_fn_hard_reg_usage ();
4678*38fd1498Szrj   final_end_function ();
4679*38fd1498Szrj 
4680*38fd1498Szrj   /* The IA-64 ".handlerdata" directive must be issued before the ".endp"
4681*38fd1498Szrj      directive that closes the procedure descriptor.  Similarly, for x64 SEH.
4682*38fd1498Szrj      Otherwise it's not strictly necessary, but it doesn't hurt either.  */
4683*38fd1498Szrj   output_function_exception_table (crtl->has_bb_partition ? 1 : 0);
4684*38fd1498Szrj 
4685*38fd1498Szrj   assemble_end_function (current_function_decl, fnname);
4686*38fd1498Szrj 
4687*38fd1498Szrj   /* Free up reg info memory.  */
4688*38fd1498Szrj   free_reg_info ();
4689*38fd1498Szrj 
4690*38fd1498Szrj   if (! quiet_flag)
4691*38fd1498Szrj     fflush (asm_out_file);
4692*38fd1498Szrj 
4693*38fd1498Szrj   /* Write DBX symbols if requested.  */
4694*38fd1498Szrj 
4695*38fd1498Szrj   /* Note that for those inline functions where we don't initially
4696*38fd1498Szrj      know for certain that we will be generating an out-of-line copy,
4697*38fd1498Szrj      the first invocation of this routine (rest_of_compilation) will
4698*38fd1498Szrj      skip over this code by doing a `goto exit_rest_of_compilation;'.
4699*38fd1498Szrj      Later on, wrapup_global_declarations will (indirectly) call
4700*38fd1498Szrj      rest_of_compilation again for those inline functions that need
4701*38fd1498Szrj      to have out-of-line copies generated.  During that call, we
4702*38fd1498Szrj      *will* be routed past here.  */
4703*38fd1498Szrj 
4704*38fd1498Szrj   timevar_push (TV_SYMOUT);
4705*38fd1498Szrj   if (!DECL_IGNORED_P (current_function_decl))
4706*38fd1498Szrj     debug_hooks->function_decl (current_function_decl);
4707*38fd1498Szrj   timevar_pop (TV_SYMOUT);
4708*38fd1498Szrj 
4709*38fd1498Szrj   /* Release the blocks that are linked to DECL_INITIAL() to free the memory.  */
4710*38fd1498Szrj   DECL_INITIAL (current_function_decl) = error_mark_node;
4711*38fd1498Szrj 
4712*38fd1498Szrj   if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
4713*38fd1498Szrj       && targetm.have_ctors_dtors)
4714*38fd1498Szrj     targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0),
4715*38fd1498Szrj 				 decl_init_priority_lookup
4716*38fd1498Szrj 				   (current_function_decl));
4717*38fd1498Szrj   if (DECL_STATIC_DESTRUCTOR (current_function_decl)
4718*38fd1498Szrj       && targetm.have_ctors_dtors)
4719*38fd1498Szrj     targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
4720*38fd1498Szrj 				decl_fini_priority_lookup
4721*38fd1498Szrj 				  (current_function_decl));
4722*38fd1498Szrj   return 0;
4723*38fd1498Szrj }
4724*38fd1498Szrj 
4725*38fd1498Szrj namespace {
4726*38fd1498Szrj 
4727*38fd1498Szrj const pass_data pass_data_final =
4728*38fd1498Szrj {
4729*38fd1498Szrj   RTL_PASS, /* type */
4730*38fd1498Szrj   "final", /* name */
4731*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
4732*38fd1498Szrj   TV_FINAL, /* tv_id */
4733*38fd1498Szrj   0, /* properties_required */
4734*38fd1498Szrj   0, /* properties_provided */
4735*38fd1498Szrj   0, /* properties_destroyed */
4736*38fd1498Szrj   0, /* todo_flags_start */
4737*38fd1498Szrj   0, /* todo_flags_finish */
4738*38fd1498Szrj };
4739*38fd1498Szrj 
4740*38fd1498Szrj class pass_final : public rtl_opt_pass
4741*38fd1498Szrj {
4742*38fd1498Szrj public:
4743*38fd1498Szrj   pass_final (gcc::context *ctxt)
4744*38fd1498Szrj     : rtl_opt_pass (pass_data_final, ctxt)
4745*38fd1498Szrj   {}
4746*38fd1498Szrj 
4747*38fd1498Szrj   /* opt_pass methods: */
4748*38fd1498Szrj   virtual unsigned int execute (function *) { return rest_of_handle_final (); }
4749*38fd1498Szrj 
4750*38fd1498Szrj }; // class pass_final
4751*38fd1498Szrj 
4752*38fd1498Szrj } // anon namespace
4753*38fd1498Szrj 
4754*38fd1498Szrj rtl_opt_pass *
4755*38fd1498Szrj make_pass_final (gcc::context *ctxt)
4756*38fd1498Szrj {
4757*38fd1498Szrj   return new pass_final (ctxt);
4758*38fd1498Szrj }
4759*38fd1498Szrj 
4760*38fd1498Szrj 
4761*38fd1498Szrj static unsigned int
4762*38fd1498Szrj rest_of_handle_shorten_branches (void)
4763*38fd1498Szrj {
4764*38fd1498Szrj   /* Shorten branches.  */
4765*38fd1498Szrj   shorten_branches (get_insns ());
4766*38fd1498Szrj   return 0;
4767*38fd1498Szrj }
4768*38fd1498Szrj 
4769*38fd1498Szrj namespace {
4770*38fd1498Szrj 
4771*38fd1498Szrj const pass_data pass_data_shorten_branches =
4772*38fd1498Szrj {
4773*38fd1498Szrj   RTL_PASS, /* type */
4774*38fd1498Szrj   "shorten", /* name */
4775*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
4776*38fd1498Szrj   TV_SHORTEN_BRANCH, /* tv_id */
4777*38fd1498Szrj   0, /* properties_required */
4778*38fd1498Szrj   0, /* properties_provided */
4779*38fd1498Szrj   0, /* properties_destroyed */
4780*38fd1498Szrj   0, /* todo_flags_start */
4781*38fd1498Szrj   0, /* todo_flags_finish */
4782*38fd1498Szrj };
4783*38fd1498Szrj 
4784*38fd1498Szrj class pass_shorten_branches : public rtl_opt_pass
4785*38fd1498Szrj {
4786*38fd1498Szrj public:
4787*38fd1498Szrj   pass_shorten_branches (gcc::context *ctxt)
4788*38fd1498Szrj     : rtl_opt_pass (pass_data_shorten_branches, ctxt)
4789*38fd1498Szrj   {}
4790*38fd1498Szrj 
4791*38fd1498Szrj   /* opt_pass methods: */
4792*38fd1498Szrj   virtual unsigned int execute (function *)
4793*38fd1498Szrj     {
4794*38fd1498Szrj       return rest_of_handle_shorten_branches ();
4795*38fd1498Szrj     }
4796*38fd1498Szrj 
4797*38fd1498Szrj }; // class pass_shorten_branches
4798*38fd1498Szrj 
4799*38fd1498Szrj } // anon namespace
4800*38fd1498Szrj 
4801*38fd1498Szrj rtl_opt_pass *
4802*38fd1498Szrj make_pass_shorten_branches (gcc::context *ctxt)
4803*38fd1498Szrj {
4804*38fd1498Szrj   return new pass_shorten_branches (ctxt);
4805*38fd1498Szrj }
4806*38fd1498Szrj 
4807*38fd1498Szrj 
4808*38fd1498Szrj static unsigned int
4809*38fd1498Szrj rest_of_clean_state (void)
4810*38fd1498Szrj {
4811*38fd1498Szrj   rtx_insn *insn, *next;
4812*38fd1498Szrj   FILE *final_output = NULL;
4813*38fd1498Szrj   int save_unnumbered = flag_dump_unnumbered;
4814*38fd1498Szrj   int save_noaddr = flag_dump_noaddr;
4815*38fd1498Szrj 
4816*38fd1498Szrj   if (flag_dump_final_insns)
4817*38fd1498Szrj     {
4818*38fd1498Szrj       final_output = fopen (flag_dump_final_insns, "a");
4819*38fd1498Szrj       if (!final_output)
4820*38fd1498Szrj 	{
4821*38fd1498Szrj 	  error ("could not open final insn dump file %qs: %m",
4822*38fd1498Szrj 		 flag_dump_final_insns);
4823*38fd1498Szrj 	  flag_dump_final_insns = NULL;
4824*38fd1498Szrj 	}
4825*38fd1498Szrj       else
4826*38fd1498Szrj 	{
4827*38fd1498Szrj 	  flag_dump_noaddr = flag_dump_unnumbered = 1;
4828*38fd1498Szrj 	  if (flag_compare_debug_opt || flag_compare_debug)
4829*38fd1498Szrj 	    dump_flags |= TDF_NOUID | TDF_COMPARE_DEBUG;
4830*38fd1498Szrj 	  dump_function_header (final_output, current_function_decl,
4831*38fd1498Szrj 				dump_flags);
4832*38fd1498Szrj 	  final_insns_dump_p = true;
4833*38fd1498Szrj 
4834*38fd1498Szrj 	  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4835*38fd1498Szrj 	    if (LABEL_P (insn))
4836*38fd1498Szrj 	      INSN_UID (insn) = CODE_LABEL_NUMBER (insn);
4837*38fd1498Szrj 	    else
4838*38fd1498Szrj 	      {
4839*38fd1498Szrj 		if (NOTE_P (insn))
4840*38fd1498Szrj 		  set_block_for_insn (insn, NULL);
4841*38fd1498Szrj 		INSN_UID (insn) = 0;
4842*38fd1498Szrj 	      }
4843*38fd1498Szrj 	}
4844*38fd1498Szrj     }
4845*38fd1498Szrj 
4846*38fd1498Szrj   /* It is very important to decompose the RTL instruction chain here:
4847*38fd1498Szrj      debug information keeps pointing into CODE_LABEL insns inside the function
4848*38fd1498Szrj      body.  If these remain pointing to the other insns, we end up preserving
4849*38fd1498Szrj      whole RTL chain and attached detailed debug info in memory.  */
4850*38fd1498Szrj   for (insn = get_insns (); insn; insn = next)
4851*38fd1498Szrj     {
4852*38fd1498Szrj       next = NEXT_INSN (insn);
4853*38fd1498Szrj       SET_NEXT_INSN (insn) = NULL;
4854*38fd1498Szrj       SET_PREV_INSN (insn) = NULL;
4855*38fd1498Szrj 
4856*38fd1498Szrj       rtx_insn *call_insn = insn;
4857*38fd1498Szrj       if (NONJUMP_INSN_P (call_insn)
4858*38fd1498Szrj 	  && GET_CODE (PATTERN (call_insn)) == SEQUENCE)
4859*38fd1498Szrj 	{
4860*38fd1498Szrj 	  rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (call_insn));
4861*38fd1498Szrj 	  call_insn = seq->insn (0);
4862*38fd1498Szrj 	}
4863*38fd1498Szrj       if (CALL_P (call_insn))
4864*38fd1498Szrj 	{
4865*38fd1498Szrj 	  rtx note
4866*38fd1498Szrj 	    = find_reg_note (call_insn, REG_CALL_ARG_LOCATION, NULL_RTX);
4867*38fd1498Szrj 	  if (note)
4868*38fd1498Szrj 	    remove_note (call_insn, note);
4869*38fd1498Szrj 	}
4870*38fd1498Szrj 
4871*38fd1498Szrj       if (final_output
4872*38fd1498Szrj 	  && (!NOTE_P (insn)
4873*38fd1498Szrj 	      || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
4874*38fd1498Szrj 		  && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT
4875*38fd1498Szrj 		  && NOTE_KIND (insn) != NOTE_INSN_INLINE_ENTRY
4876*38fd1498Szrj 		  && NOTE_KIND (insn) != NOTE_INSN_BLOCK_BEG
4877*38fd1498Szrj 		  && NOTE_KIND (insn) != NOTE_INSN_BLOCK_END
4878*38fd1498Szrj 		  && NOTE_KIND (insn) != NOTE_INSN_DELETED_DEBUG_LABEL)))
4879*38fd1498Szrj 	print_rtl_single (final_output, insn);
4880*38fd1498Szrj     }
4881*38fd1498Szrj 
4882*38fd1498Szrj   if (final_output)
4883*38fd1498Szrj     {
4884*38fd1498Szrj       flag_dump_noaddr = save_noaddr;
4885*38fd1498Szrj       flag_dump_unnumbered = save_unnumbered;
4886*38fd1498Szrj       final_insns_dump_p = false;
4887*38fd1498Szrj 
4888*38fd1498Szrj       if (fclose (final_output))
4889*38fd1498Szrj 	{
4890*38fd1498Szrj 	  error ("could not close final insn dump file %qs: %m",
4891*38fd1498Szrj 		 flag_dump_final_insns);
4892*38fd1498Szrj 	  flag_dump_final_insns = NULL;
4893*38fd1498Szrj 	}
4894*38fd1498Szrj     }
4895*38fd1498Szrj 
4896*38fd1498Szrj   flag_rerun_cse_after_global_opts = 0;
4897*38fd1498Szrj   reload_completed = 0;
4898*38fd1498Szrj   epilogue_completed = 0;
4899*38fd1498Szrj #ifdef STACK_REGS
4900*38fd1498Szrj   regstack_completed = 0;
4901*38fd1498Szrj #endif
4902*38fd1498Szrj 
4903*38fd1498Szrj   /* Clear out the insn_length contents now that they are no
4904*38fd1498Szrj      longer valid.  */
4905*38fd1498Szrj   init_insn_lengths ();
4906*38fd1498Szrj 
4907*38fd1498Szrj   /* Show no temporary slots allocated.  */
4908*38fd1498Szrj   init_temp_slots ();
4909*38fd1498Szrj 
4910*38fd1498Szrj   free_bb_for_insn ();
4911*38fd1498Szrj 
4912*38fd1498Szrj   if (cfun->gimple_df)
4913*38fd1498Szrj     delete_tree_ssa (cfun);
4914*38fd1498Szrj 
4915*38fd1498Szrj   /* We can reduce stack alignment on call site only when we are sure that
4916*38fd1498Szrj      the function body just produced will be actually used in the final
4917*38fd1498Szrj      executable.  */
4918*38fd1498Szrj   if (decl_binds_to_current_def_p (current_function_decl))
4919*38fd1498Szrj     {
4920*38fd1498Szrj       unsigned int pref = crtl->preferred_stack_boundary;
4921*38fd1498Szrj       if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary)
4922*38fd1498Szrj         pref = crtl->stack_alignment_needed;
4923*38fd1498Szrj       cgraph_node::rtl_info (current_function_decl)
4924*38fd1498Szrj 	->preferred_incoming_stack_boundary = pref;
4925*38fd1498Szrj     }
4926*38fd1498Szrj 
4927*38fd1498Szrj   /* Make sure volatile mem refs aren't considered valid operands for
4928*38fd1498Szrj      arithmetic insns.  We must call this here if this is a nested inline
4929*38fd1498Szrj      function, since the above code leaves us in the init_recog state,
4930*38fd1498Szrj      and the function context push/pop code does not save/restore volatile_ok.
4931*38fd1498Szrj 
4932*38fd1498Szrj      ??? Maybe it isn't necessary for expand_start_function to call this
4933*38fd1498Szrj      anymore if we do it here?  */
4934*38fd1498Szrj 
4935*38fd1498Szrj   init_recog_no_volatile ();
4936*38fd1498Szrj 
4937*38fd1498Szrj   /* We're done with this function.  Free up memory if we can.  */
4938*38fd1498Szrj   free_after_parsing (cfun);
4939*38fd1498Szrj   free_after_compilation (cfun);
4940*38fd1498Szrj   return 0;
4941*38fd1498Szrj }
4942*38fd1498Szrj 
4943*38fd1498Szrj namespace {
4944*38fd1498Szrj 
4945*38fd1498Szrj const pass_data pass_data_clean_state =
4946*38fd1498Szrj {
4947*38fd1498Szrj   RTL_PASS, /* type */
4948*38fd1498Szrj   "*clean_state", /* name */
4949*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
4950*38fd1498Szrj   TV_FINAL, /* tv_id */
4951*38fd1498Szrj   0, /* properties_required */
4952*38fd1498Szrj   0, /* properties_provided */
4953*38fd1498Szrj   PROP_rtl, /* properties_destroyed */
4954*38fd1498Szrj   0, /* todo_flags_start */
4955*38fd1498Szrj   0, /* todo_flags_finish */
4956*38fd1498Szrj };
4957*38fd1498Szrj 
4958*38fd1498Szrj class pass_clean_state : public rtl_opt_pass
4959*38fd1498Szrj {
4960*38fd1498Szrj public:
4961*38fd1498Szrj   pass_clean_state (gcc::context *ctxt)
4962*38fd1498Szrj     : rtl_opt_pass (pass_data_clean_state, ctxt)
4963*38fd1498Szrj   {}
4964*38fd1498Szrj 
4965*38fd1498Szrj   /* opt_pass methods: */
4966*38fd1498Szrj   virtual unsigned int execute (function *)
4967*38fd1498Szrj     {
4968*38fd1498Szrj       return rest_of_clean_state ();
4969*38fd1498Szrj     }
4970*38fd1498Szrj 
4971*38fd1498Szrj }; // class pass_clean_state
4972*38fd1498Szrj 
4973*38fd1498Szrj } // anon namespace
4974*38fd1498Szrj 
4975*38fd1498Szrj rtl_opt_pass *
4976*38fd1498Szrj make_pass_clean_state (gcc::context *ctxt)
4977*38fd1498Szrj {
4978*38fd1498Szrj   return new pass_clean_state (ctxt);
4979*38fd1498Szrj }
4980*38fd1498Szrj 
4981*38fd1498Szrj /* Return true if INSN is a call to the current function.  */
4982*38fd1498Szrj 
4983*38fd1498Szrj static bool
4984*38fd1498Szrj self_recursive_call_p (rtx_insn *insn)
4985*38fd1498Szrj {
4986*38fd1498Szrj   tree fndecl = get_call_fndecl (insn);
4987*38fd1498Szrj   return (fndecl == current_function_decl
4988*38fd1498Szrj 	  && decl_binds_to_current_def_p (fndecl));
4989*38fd1498Szrj }
4990*38fd1498Szrj 
4991*38fd1498Szrj /* Collect hard register usage for the current function.  */
4992*38fd1498Szrj 
4993*38fd1498Szrj static void
4994*38fd1498Szrj collect_fn_hard_reg_usage (void)
4995*38fd1498Szrj {
4996*38fd1498Szrj   rtx_insn *insn;
4997*38fd1498Szrj #ifdef STACK_REGS
4998*38fd1498Szrj   int i;
4999*38fd1498Szrj #endif
5000*38fd1498Szrj   struct cgraph_rtl_info *node;
5001*38fd1498Szrj   HARD_REG_SET function_used_regs;
5002*38fd1498Szrj 
5003*38fd1498Szrj   /* ??? To be removed when all the ports have been fixed.  */
5004*38fd1498Szrj   if (!targetm.call_fusage_contains_non_callee_clobbers)
5005*38fd1498Szrj     return;
5006*38fd1498Szrj 
5007*38fd1498Szrj   CLEAR_HARD_REG_SET (function_used_regs);
5008*38fd1498Szrj 
5009*38fd1498Szrj   for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn))
5010*38fd1498Szrj     {
5011*38fd1498Szrj       HARD_REG_SET insn_used_regs;
5012*38fd1498Szrj 
5013*38fd1498Szrj       if (!NONDEBUG_INSN_P (insn))
5014*38fd1498Szrj 	continue;
5015*38fd1498Szrj 
5016*38fd1498Szrj       if (CALL_P (insn)
5017*38fd1498Szrj 	  && !self_recursive_call_p (insn))
5018*38fd1498Szrj 	{
5019*38fd1498Szrj 	  if (!get_call_reg_set_usage (insn, &insn_used_regs,
5020*38fd1498Szrj 				       call_used_reg_set))
5021*38fd1498Szrj 	    return;
5022*38fd1498Szrj 
5023*38fd1498Szrj 	  IOR_HARD_REG_SET (function_used_regs, insn_used_regs);
5024*38fd1498Szrj 	}
5025*38fd1498Szrj 
5026*38fd1498Szrj       find_all_hard_reg_sets (insn, &insn_used_regs, false);
5027*38fd1498Szrj       IOR_HARD_REG_SET (function_used_regs, insn_used_regs);
5028*38fd1498Szrj     }
5029*38fd1498Szrj 
5030*38fd1498Szrj   /* Be conservative - mark fixed and global registers as used.  */
5031*38fd1498Szrj   IOR_HARD_REG_SET (function_used_regs, fixed_reg_set);
5032*38fd1498Szrj 
5033*38fd1498Szrj #ifdef STACK_REGS
5034*38fd1498Szrj   /* Handle STACK_REGS conservatively, since the df-framework does not
5035*38fd1498Szrj      provide accurate information for them.  */
5036*38fd1498Szrj 
5037*38fd1498Szrj   for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
5038*38fd1498Szrj     SET_HARD_REG_BIT (function_used_regs, i);
5039*38fd1498Szrj #endif
5040*38fd1498Szrj 
5041*38fd1498Szrj   /* The information we have gathered is only interesting if it exposes a
5042*38fd1498Szrj      register from the call_used_regs that is not used in this function.  */
5043*38fd1498Szrj   if (hard_reg_set_subset_p (call_used_reg_set, function_used_regs))
5044*38fd1498Szrj     return;
5045*38fd1498Szrj 
5046*38fd1498Szrj   node = cgraph_node::rtl_info (current_function_decl);
5047*38fd1498Szrj   gcc_assert (node != NULL);
5048*38fd1498Szrj 
5049*38fd1498Szrj   COPY_HARD_REG_SET (node->function_used_regs, function_used_regs);
5050*38fd1498Szrj   node->function_used_regs_valid = 1;
5051*38fd1498Szrj }
5052*38fd1498Szrj 
5053*38fd1498Szrj /* Get the declaration of the function called by INSN.  */
5054*38fd1498Szrj 
5055*38fd1498Szrj static tree
5056*38fd1498Szrj get_call_fndecl (rtx_insn *insn)
5057*38fd1498Szrj {
5058*38fd1498Szrj   rtx note, datum;
5059*38fd1498Szrj 
5060*38fd1498Szrj   note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX);
5061*38fd1498Szrj   if (note == NULL_RTX)
5062*38fd1498Szrj     return NULL_TREE;
5063*38fd1498Szrj 
5064*38fd1498Szrj   datum = XEXP (note, 0);
5065*38fd1498Szrj   if (datum != NULL_RTX)
5066*38fd1498Szrj     return SYMBOL_REF_DECL (datum);
5067*38fd1498Szrj 
5068*38fd1498Szrj   return NULL_TREE;
5069*38fd1498Szrj }
5070*38fd1498Szrj 
5071*38fd1498Szrj /* Return the cgraph_rtl_info of the function called by INSN.  Returns NULL for
5072*38fd1498Szrj    call targets that can be overwritten.  */
5073*38fd1498Szrj 
5074*38fd1498Szrj static struct cgraph_rtl_info *
5075*38fd1498Szrj get_call_cgraph_rtl_info (rtx_insn *insn)
5076*38fd1498Szrj {
5077*38fd1498Szrj   tree fndecl;
5078*38fd1498Szrj 
5079*38fd1498Szrj   if (insn == NULL_RTX)
5080*38fd1498Szrj     return NULL;
5081*38fd1498Szrj 
5082*38fd1498Szrj   fndecl = get_call_fndecl (insn);
5083*38fd1498Szrj   if (fndecl == NULL_TREE
5084*38fd1498Szrj       || !decl_binds_to_current_def_p (fndecl))
5085*38fd1498Szrj     return NULL;
5086*38fd1498Szrj 
5087*38fd1498Szrj   return cgraph_node::rtl_info (fndecl);
5088*38fd1498Szrj }
5089*38fd1498Szrj 
5090*38fd1498Szrj /* Find hard registers used by function call instruction INSN, and return them
5091*38fd1498Szrj    in REG_SET.  Return DEFAULT_SET in REG_SET if not found.  */
5092*38fd1498Szrj 
5093*38fd1498Szrj bool
5094*38fd1498Szrj get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set,
5095*38fd1498Szrj 			HARD_REG_SET default_set)
5096*38fd1498Szrj {
5097*38fd1498Szrj   if (flag_ipa_ra)
5098*38fd1498Szrj     {
5099*38fd1498Szrj       struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn);
5100*38fd1498Szrj       if (node != NULL
5101*38fd1498Szrj 	  && node->function_used_regs_valid)
5102*38fd1498Szrj 	{
5103*38fd1498Szrj 	  COPY_HARD_REG_SET (*reg_set, node->function_used_regs);
5104*38fd1498Szrj 	  AND_HARD_REG_SET (*reg_set, default_set);
5105*38fd1498Szrj 	  return true;
5106*38fd1498Szrj 	}
5107*38fd1498Szrj     }
5108*38fd1498Szrj 
5109*38fd1498Szrj   COPY_HARD_REG_SET (*reg_set, default_set);
5110*38fd1498Szrj   return false;
5111*38fd1498Szrj }
5112