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