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 280823 : init_final (const char *filename ATTRIBUTE_UNUSED)
211 : {
212 280823 : app_on = 0;
213 280823 : final_sequence = 0;
214 :
215 : #ifdef ASSEMBLER_DIALECT
216 280823 : dialect_number = ASSEMBLER_DIALECT;
217 : #endif
218 280823 : }
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 1486293 : default_function_pro_epilogue (FILE *)
226 : {
227 1486293 : }
228 :
229 : void
230 63742 : default_function_switched_text_sections (FILE *file ATTRIBUTE_UNUSED,
231 : tree decl ATTRIBUTE_UNUSED,
232 : bool new_is_cold ATTRIBUTE_UNUSED)
233 : {
234 63742 : }
235 :
236 : /* Default target hook that outputs nothing to a stream. */
237 : void
238 3066140 : no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED)
239 : {
240 3066140 : }
241 :
242 : /* Enable APP processing of subsequent output.
243 : Used before the output from an `asm' statement. */
244 :
245 : void
246 48253 : app_enable (void)
247 : {
248 48253 : if (! app_on)
249 : {
250 45045 : fputs (ASM_APP_ON, asm_out_file);
251 45045 : app_on = 1;
252 : }
253 48253 : }
254 :
255 : /* Disable APP processing of subsequent output.
256 : Called from varasm.cc before most kinds of output. */
257 :
258 : void
259 152465263 : app_disable (void)
260 : {
261 152465263 : if (app_on)
262 : {
263 44007 : fputs (ASM_APP_OFF, asm_out_file);
264 44007 : app_on = 0;
265 : }
266 152465263 : }
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 1487107 : init_insn_lengths (void)
320 : {
321 1487107 : if (uid_shuid)
322 : {
323 1482709 : free (uid_shuid);
324 1482709 : uid_shuid = 0;
325 : }
326 1487107 : if (insn_lengths)
327 : {
328 1482709 : free (insn_lengths);
329 1482709 : insn_lengths = 0;
330 1482709 : insn_lengths_max_uid = 0;
331 : }
332 1487107 : if (HAVE_ATTR_length)
333 1487107 : INSN_ADDRESSES_FREE ();
334 1487107 : if (uid_align)
335 : {
336 1482709 : free (uid_align);
337 1482709 : uid_align = 0;
338 : }
339 1487107 : }
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 395149413 : get_attr_length_1 (rtx_insn *insn, int (*fallback_fn) (rtx_insn *))
346 : {
347 395149413 : rtx body;
348 395149413 : int i;
349 395149413 : int length = 0;
350 :
351 395149413 : if (!HAVE_ATTR_length)
352 : return 0;
353 :
354 395149413 : if (insn_lengths_max_uid > INSN_UID (insn))
355 3457 : return insn_lengths[INSN_UID (insn)];
356 : else
357 395145956 : switch (GET_CODE (insn))
358 : {
359 : case NOTE:
360 : case BARRIER:
361 : case CODE_LABEL:
362 : case DEBUG_INSN:
363 : return 0;
364 :
365 9609419 : case CALL_INSN:
366 9609419 : case JUMP_INSN:
367 9609419 : body = PATTERN (insn);
368 9609419 : if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
369 121 : length = asm_insn_count (body) * fallback_fn (insn);
370 : else
371 9609298 : length = fallback_fn (insn);
372 : break;
373 :
374 374635256 : case INSN:
375 374635256 : body = PATTERN (insn);
376 374635256 : if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
377 : return 0;
378 :
379 374293895 : else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
380 7943 : length = asm_insn_count (body) * fallback_fn (insn);
381 374285952 : 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 374285952 : 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 376627914 : get_attr_length (rtx_insn *insn)
402 : {
403 376627914 : 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 18521499 : get_attr_min_length (rtx_insn *insn)
410 : {
411 18521499 : 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 8205 : final_addr_vec_align (rtx_jump_table_data *addr_vec)
474 : {
475 8205 : int align = GET_MODE_SIZE (addr_vec->get_data_mode ());
476 :
477 16315 : if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
478 0 : align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
479 8205 : 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 28205142 : align_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth)
537 : {
538 28205142 : int uid = INSN_UID (start);
539 28205142 : rtx align_label;
540 28205142 : int known_align = 1 << known_align_log;
541 28205142 : int end_shuid = INSN_SHUID (end);
542 28205142 : int fuzz = 0;
543 :
544 41653370 : for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
545 : {
546 16157971 : int align_addr, new_align;
547 :
548 16157971 : uid = INSN_UID (align_label);
549 16157971 : align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid];
550 16157971 : if (uid_shuid[uid] > end_shuid)
551 : break;
552 13448228 : align_flags alignment = LABEL_TO_ALIGNMENT (align_label);
553 13448228 : new_align = 1 << alignment.levels[0].log;
554 13448228 : if (new_align < known_align)
555 0 : continue;
556 13448228 : fuzz += (-align_addr ^ growth) & (new_align - known_align);
557 13448228 : known_align = new_align;
558 : }
559 28205142 : 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 28205142 : insn_current_reference_address (rtx_insn *branch)
576 : {
577 28205142 : rtx dest;
578 28205142 : int seq_uid;
579 :
580 28205142 : if (! INSN_ADDRESSES_SET_P ())
581 : return 0;
582 :
583 28205142 : rtx_insn *seq = NEXT_INSN (PREV_INSN (branch));
584 28205142 : seq_uid = INSN_UID (seq);
585 28205142 : 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 28205142 : dest = JUMP_LABEL (branch);
593 :
594 : /* BRANCH has no proper alignment chain set, so use SEQ.
595 : BRANCH also has no INSN_SHUID. */
596 28205142 : if (INSN_SHUID (seq) < INSN_SHUID (dest))
597 : {
598 : /* Forward branch. */
599 20302376 : return (insn_last_address + insn_lengths[seq_uid]
600 20302376 : - align_fuzz (seq, dest, length_unit_log, ~0));
601 : }
602 : else
603 : {
604 : /* Backward branch. */
605 7902766 : return (insn_current_address
606 7902766 : + align_fuzz (dest, seq, length_unit_log, ~0));
607 : }
608 : }
609 :
610 : /* Compute branch alignments based on CFG profile. */
611 :
612 : void
613 1480948 : compute_alignments (void)
614 : {
615 1480948 : basic_block bb;
616 1480948 : align_flags max_alignment;
617 :
618 1480948 : label_align.truncate (0);
619 :
620 1480948 : max_labelno = max_label_num ();
621 1480948 : min_labelno = get_first_label_num ();
622 1480948 : 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 1480948 : if (! optimize || optimize_function_for_size_p (cfun))
626 505344 : return;
627 :
628 975604 : 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 975604 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
635 975604 : profile_count count_threshold = cfun->cfg->count_max / param_align_threshold;
636 :
637 975604 : 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 11526764 : FOR_EACH_BB_FN (bb, cfun)
644 : {
645 10551160 : rtx_insn *label = BB_HEAD (bb);
646 10551160 : bool has_fallthru = 0;
647 10551160 : edge e;
648 10551160 : edge_iterator ei;
649 :
650 17315994 : if (!LABEL_P (label)
651 10551160 : || optimize_bb_for_size_p (bb))
652 : {
653 6764834 : 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 6766329 : continue;
660 : }
661 3786326 : max_alignment = LABEL_ALIGN (label);
662 3786326 : profile_count fallthru_count = profile_count::zero ();
663 3786326 : profile_count branch_count = profile_count::zero ();
664 :
665 11047498 : FOR_EACH_EDGE (e, ei, bb->preds)
666 : {
667 7261172 : if (e->flags & EDGE_FALLTHRU)
668 2326048 : has_fallthru = 1, fallthru_count += e->count ();
669 : else
670 4935124 : branch_count += e->count ();
671 : }
672 3786326 : 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 3786326 : 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 3784831 : if (!has_fallthru
701 3784831 : && (branch_count > count_threshold
702 421753 : || (bb->count > bb->prev_bb->count * 10
703 27476 : && (bb->prev_bb->count
704 2747300 : <= ENTRY_BLOCK_PTR_FOR_FN (cfun)->count / 2))))
705 : {
706 1065007 : align_flags alignment = JUMP_ALIGN (label);
707 1065007 : if (dump_file)
708 38 : fprintf (dump_file, " jump alignment added.\n");
709 1065007 : 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 3784831 : if (has_fallthru
714 2324988 : && !(single_succ_p (bb)
715 801430 : && single_succ (bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
716 1982091 : && optimize_bb_for_speed_p (bb)
717 1982091 : && branch_count + fallthru_count > count_threshold
718 6109825 : && (branch_count > fallthru_count * param_align_loop_iterations))
719 : {
720 307173 : align_flags alignment = LOOP_ALIGN (label);
721 307173 : if (dump_file)
722 11 : fprintf (dump_file, " internal loop alignment added.\n");
723 307173 : max_alignment = align_flags::max (max_alignment, alignment);
724 : }
725 3784831 : LABEL_TO_ALIGNMENT (label) = max_alignment;
726 : }
727 :
728 975604 : loop_optimizer_finalize ();
729 975604 : 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 287872 : pass_compute_alignments (gcc::context *ctxt)
792 575744 : : rtl_opt_pass (pass_data_compute_alignments, ctxt)
793 : {}
794 :
795 : /* opt_pass methods: */
796 1480948 : unsigned int execute (function *) final override
797 : {
798 1480948 : compute_alignments ();
799 1480948 : return 0;
800 : }
801 :
802 : }; // class pass_compute_alignments
803 :
804 : } // anon namespace
805 :
806 : rtl_opt_pass *
807 287872 : make_pass_compute_alignments (gcc::context *ctxt)
808 : {
809 287872 : 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 1482709 : shorten_branches (rtx_insn *first)
826 : {
827 1482709 : rtx_insn *insn;
828 1482709 : int max_uid;
829 1482709 : int i;
830 1482709 : rtx_insn *seq;
831 1482709 : bool something_changed = true;
832 1482709 : char *varying_length;
833 1482709 : rtx body;
834 1482709 : int uid;
835 1482709 : rtx align_tab[MAX_CODE_ALIGN + 1];
836 :
837 : /* Compute maximum UID and allocate label_align / uid_shuid. */
838 1482709 : max_uid = get_max_uid ();
839 :
840 : /* Free uid_shuid before reallocating it. */
841 1482709 : free (uid_shuid);
842 :
843 1482709 : uid_shuid = XNEWVEC (int, max_uid);
844 :
845 1482709 : 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 1482709 : align_flags max_alignment;
855 :
856 205045915 : for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
857 : {
858 203563206 : INSN_SHUID (insn) = i++;
859 203563206 : if (INSN_P (insn))
860 93823039 : continue;
861 :
862 109740167 : if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
863 : {
864 : /* Merge in alignments computed by compute_alignments. */
865 6893827 : align_flags alignment = LABEL_TO_ALIGNMENT (label);
866 6893827 : max_alignment = align_flags::max (max_alignment, alignment);
867 :
868 6893827 : rtx_jump_table_data *table = jump_table_for_label (label);
869 6893827 : if (!table)
870 : {
871 6885622 : align_flags alignment = LABEL_ALIGN (label);
872 6885622 : 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 6893827 : if ((JUMP_TABLES_IN_TEXT_SECTION
877 6893827 : || 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 6893827 : LABEL_TO_ALIGNMENT (label) = max_alignment;
884 6893827 : max_alignment = align_flags ();
885 : }
886 102846340 : else if (BARRIER_P (insn))
887 : {
888 : rtx_insn *label;
889 :
890 27264989 : for (label = insn; label && ! INSN_P (label);
891 22509592 : label = NEXT_INSN (label))
892 25733057 : if (LABEL_P (label))
893 : {
894 3223465 : align_flags alignment
895 3223465 : = align_flags (LABEL_ALIGN_AFTER_BARRIER (insn));
896 3223465 : max_alignment = align_flags::max (max_alignment, alignment);
897 3223465 : break;
898 : }
899 : }
900 : }
901 1482709 : if (!HAVE_ATTR_length)
902 : return;
903 :
904 : /* Allocate the rest of the arrays. */
905 1482709 : insn_lengths = XNEWVEC (int, max_uid);
906 1482709 : 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 1482709 : INSN_ADDRESSES_ALLOC (max_uid);
910 :
911 1482709 : 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 1482709 : uid_align = XCNEWVEC (rtx, max_uid);
919 :
920 26688762 : for (i = MAX_CODE_ALIGN + 1; --i >= 0;)
921 25206053 : align_tab[i] = NULL_RTX;
922 1482709 : seq = get_last_insn ();
923 205045915 : for (; seq; seq = PREV_INSN (seq))
924 : {
925 203563206 : int uid = INSN_UID (seq);
926 203563206 : int log;
927 203563206 : log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq).levels[0].log : 0);
928 203563206 : uid_align[uid] = align_tab[0];
929 203563206 : if (log)
930 : {
931 : /* Found an alignment label. */
932 1312082 : gcc_checking_assert (log < MAX_CODE_ALIGN + 1);
933 1312082 : uid_align[uid] = align_tab[log];
934 6560500 : for (i = log - 1; i >= 0; i--)
935 5248418 : 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 1482709 : 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 1482709 : int (*length_fun) (rtx_insn *) = increasing ? insn_min_length : insn_default_length;
1009 :
1010 1482709 : for (insn_current_address = 0, insn = first;
1011 205045915 : insn != 0;
1012 203563206 : insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
1013 : {
1014 203563206 : uid = INSN_UID (insn);
1015 :
1016 203563206 : insn_lengths[uid] = 0;
1017 :
1018 203563206 : if (LABEL_P (insn))
1019 : {
1020 6893827 : int log = LABEL_TO_ALIGNMENT (insn).levels[0].log;
1021 6893827 : if (log)
1022 : {
1023 1312082 : int align = 1 << log;
1024 1312082 : int new_address = (insn_current_address + align - 1) & -align;
1025 1312082 : insn_lengths[uid] = new_address - insn_current_address;
1026 : }
1027 : }
1028 :
1029 203563206 : INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
1030 :
1031 203563206 : if (NOTE_P (insn) || BARRIER_P (insn)
1032 100725071 : || LABEL_P (insn) || DEBUG_INSN_P (insn))
1033 109731966 : continue;
1034 93831240 : if (insn->deleted ())
1035 0 : continue;
1036 :
1037 93831240 : body = PATTERN (insn);
1038 93831240 : 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 8205 : if (JUMP_TABLES_IN_TEXT_SECTION
1043 8205 : || 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 93823035 : else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
1050 109467 : insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
1051 93713568 : 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 93713568 : else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
1093 : {
1094 92669778 : insn_lengths[uid] = length_fun (insn);
1095 92669778 : 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 2780459 : while (something_changed)
1111 : {
1112 1740112 : something_changed = false;
1113 1740112 : insn_current_align = MAX_CODE_ALIGN - 1;
1114 368762621 : for (insn_current_address = 0, insn = first;
1115 368762621 : insn != 0;
1116 367022509 : insn = NEXT_INSN (insn))
1117 : {
1118 367022509 : int new_length;
1119 : #ifdef ADJUST_INSN_LENGTH
1120 : int tmp_length;
1121 : #endif
1122 367022509 : int length_align;
1123 :
1124 367022509 : uid = INSN_UID (insn);
1125 :
1126 367022509 : if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
1127 : {
1128 12276931 : 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 12276931 : if (log > insn_current_align)
1152 : {
1153 2650374 : int align = 1 << log;
1154 2650374 : int new_address= (insn_current_address + align - 1) & -align;
1155 2650374 : insn_lengths[uid] = new_address - insn_current_address;
1156 2650374 : insn_current_align = log;
1157 2650374 : insn_current_address = new_address;
1158 : }
1159 : else
1160 9626557 : insn_lengths[uid] = 0;
1161 12276931 : INSN_ADDRESSES (uid) = insn_current_address;
1162 12276931 : continue;
1163 12276931 : }
1164 :
1165 354745578 : length_align = INSN_LENGTH_ALIGNMENT (insn);
1166 354745578 : if (length_align < insn_current_align)
1167 4390486 : insn_current_align = length_align;
1168 :
1169 354745578 : insn_last_address = INSN_ADDRESSES (uid);
1170 354745578 : 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 354745578 : if (! (varying_length[uid]))
1291 : {
1292 338751592 : if (NONJUMP_INSN_P (insn)
1293 338751592 : && 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 338751592 : insn_current_address += insn_lengths[uid];
1310 :
1311 338751592 : continue;
1312 338751592 : }
1313 :
1314 15993986 : 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 15993986 : new_length = insn_current_length (insn);
1353 15993986 : 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 15993986 : if (new_length != insn_lengths[uid]
1364 5375197 : && (!increasing || new_length > insn_lengths[uid]))
1365 : {
1366 5375197 : insn_lengths[uid] = new_length;
1367 5375197 : something_changed = true;
1368 : }
1369 : else
1370 10618789 : insn_current_address += insn_lengths[uid] - new_length;
1371 : }
1372 : /* For a non-optimizing compile, do only a single pass. */
1373 1740112 : if (!increasing)
1374 : break;
1375 : }
1376 1482709 : crtl->max_insn_address = insn_current_address;
1377 1482709 : 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 117531 : asm_insn_count (rtx body)
1386 : {
1387 117531 : const char *templ;
1388 :
1389 117531 : if (GET_CODE (body) == ASM_INPUT)
1390 3579 : templ = XSTR (body, 0);
1391 : else
1392 113952 : templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
1393 :
1394 117531 : 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 879277 : asm_str_count (const char *templ)
1401 : {
1402 879277 : int count = 1;
1403 :
1404 879277 : if (!*templ)
1405 : return 0;
1406 :
1407 5570690 : for (; *templ; templ++)
1408 5252072 : if (IS_ASM_LOGICAL_LINE_SEPARATOR (*templ, templ)
1409 5244586 : || *templ == '\n')
1410 241892 : count++;
1411 :
1412 : return count;
1413 : }
1414 :
1415 : /* Return true if DWARF2 debug info can be emitted for DECL. */
1416 :
1417 : static bool
1418 3036326 : dwarf2_debug_info_emitted_p (tree decl)
1419 : {
1420 : /* When DWARF2 debug info is not generated internally. */
1421 3036326 : if (!dwarf_debuginfo_p () && !dwarf_based_debuginfo_p ())
1422 : return false;
1423 :
1424 1166582 : 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 16936007 : change_scope (rtx_insn *orig_insn, tree s1, tree s2)
1447 : {
1448 16936007 : rtx_insn *insn = orig_insn;
1449 16936007 : tree com = NULL_TREE;
1450 16936007 : tree ts1 = s1, ts2 = s2;
1451 16936007 : tree s;
1452 :
1453 55163889 : while (ts1 != ts2)
1454 : {
1455 38227882 : gcc_assert (ts1 && ts2);
1456 38227882 : if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
1457 15478737 : ts1 = BLOCK_SUPERCONTEXT (ts1);
1458 22749145 : else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
1459 15478737 : ts2 = BLOCK_SUPERCONTEXT (ts2);
1460 : else
1461 : {
1462 7270408 : ts1 = BLOCK_SUPERCONTEXT (ts1);
1463 7270408 : ts2 = BLOCK_SUPERCONTEXT (ts2);
1464 : }
1465 : }
1466 39685152 : com = ts1;
1467 :
1468 : /* Close scopes. */
1469 : s = s1;
1470 39685152 : while (s != com)
1471 : {
1472 22749145 : rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
1473 22749145 : NOTE_BLOCK (note) = s;
1474 22749145 : s = BLOCK_SUPERCONTEXT (s);
1475 : }
1476 :
1477 : /* Open scopes. */
1478 : s = s2;
1479 39685152 : while (s != com)
1480 : {
1481 22749145 : insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
1482 22749145 : NOTE_BLOCK (insn) = s;
1483 22749145 : s = BLOCK_SUPERCONTEXT (s);
1484 : }
1485 16936007 : }
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 572820 : reemit_insn_block_notes (void)
1492 : {
1493 572820 : tree cur_block = DECL_INITIAL (cfun->decl);
1494 572820 : rtx_insn *insn;
1495 :
1496 572820 : insn = get_insns ();
1497 145470442 : for (; insn; insn = NEXT_INSN (insn))
1498 : {
1499 144897622 : tree this_block;
1500 :
1501 : /* Prevent lexical blocks from straddling section boundaries. */
1502 144897622 : if (NOTE_P (insn))
1503 91848176 : switch (NOTE_KIND (insn))
1504 : {
1505 : case NOTE_INSN_SWITCH_TEXT_SECTIONS:
1506 : {
1507 79896 : for (tree s = cur_block; s != DECL_INITIAL (cfun->decl);
1508 58954 : s = BLOCK_SUPERCONTEXT (s))
1509 : {
1510 58954 : rtx_note *note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
1511 58954 : NOTE_BLOCK (note) = s;
1512 58954 : note = emit_note_after (NOTE_INSN_BLOCK_BEG, insn);
1513 58954 : NOTE_BLOCK (note) = s;
1514 : }
1515 : }
1516 : break;
1517 :
1518 10764850 : case NOTE_INSN_BEGIN_STMT:
1519 10764850 : case NOTE_INSN_INLINE_ENTRY:
1520 10764850 : this_block = LOCATION_BLOCK (NOTE_MARKER_LOCATION (insn));
1521 10756264 : if (!this_block)
1522 13952 : continue;
1523 10750898 : goto set_cur_block_to_this_block;
1524 :
1525 81062384 : default:
1526 81062384 : continue;
1527 81062384 : }
1528 :
1529 53070388 : if (!active_insn_p (insn))
1530 7240227 : continue;
1531 :
1532 : /* Avoid putting scope notes between jump table and its label. */
1533 45830161 : if (JUMP_TABLE_DATA_P (insn))
1534 7276 : continue;
1535 :
1536 45822885 : this_block = insn_scope (insn);
1537 : /* For sequences compute scope resulting from merging all scopes
1538 : of instructions nested inside. */
1539 45822885 : 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 45822885 : if (! this_block)
1549 : {
1550 10364594 : if (INSN_LOCATION (insn) == UNKNOWN_LOCATION)
1551 5061221 : continue;
1552 : else
1553 5303373 : this_block = DECL_INITIAL (cfun->decl);
1554 : }
1555 :
1556 35458291 : set_cur_block_to_this_block:
1557 51512562 : if (this_block != cur_block)
1558 : {
1559 16363187 : change_scope (insn, cur_block, this_block);
1560 16363187 : cur_block = this_block;
1561 : }
1562 : }
1563 :
1564 : /* change_scope emits before the insn, not after. */
1565 572820 : rtx_note *note = emit_note (NOTE_INSN_DELETED);
1566 572820 : change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
1567 572820 : delete_insn (note);
1568 :
1569 572820 : reorder_blocks ();
1570 572820 : }
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 58749175 : set_next_view_needed (int *seen)
1613 : {
1614 58749175 : if (debug_variable_location_views)
1615 58749175 : *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 46602066 : clear_next_view_needed (int *seen)
1623 : {
1624 46602066 : *seen &= ~SEEN_NEXT_VIEW;
1625 38007672 : }
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 89890981 : maybe_output_next_view (int *seen)
1632 : {
1633 89890981 : if ((*seen & SEEN_NEXT_VIEW) != 0)
1634 : {
1635 8594394 : clear_next_view_needed (seen);
1636 8594394 : (*debug_hooks->source_line) (last_linenum, last_columnnum,
1637 : last_filename, last_discriminator,
1638 : false);
1639 : }
1640 89890981 : }
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 2912020 : in_initial_view_p (rtx_insn *insn)
1657 : {
1658 2912020 : return (!DECL_IGNORED_P (current_function_decl)
1659 2883734 : && debug_variable_location_views
1660 1912215 : && insn && GET_CODE (insn) == NOTE
1661 4666614 : && (NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
1662 818853 : || 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 1486293 : final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
1680 : int optimize_p ATTRIBUTE_UNUSED)
1681 : {
1682 1486293 : block_depth = 0;
1683 :
1684 1486293 : this_is_asm_operands = 0;
1685 :
1686 1486293 : need_profile_function = false;
1687 :
1688 1486293 : last_filename = LOCATION_FILE (prologue_location);
1689 1486293 : last_linenum = LOCATION_LINE (prologue_location);
1690 1486293 : last_columnnum = LOCATION_COLUMN (prologue_location);
1691 1486293 : last_discriminator = 0;
1692 1486293 : force_source_line = false;
1693 :
1694 1486293 : high_block_linenum = high_function_linenum = last_linenum;
1695 :
1696 1486293 : rtx_insn *first = *firstp;
1697 1486293 : if (in_initial_view_p (first))
1698 : {
1699 1423966 : do
1700 : {
1701 1423966 : final_scan_insn (first, file, 0, 0, seen);
1702 1423966 : first = NEXT_INSN (first);
1703 : }
1704 1423966 : while (in_initial_view_p (first));
1705 488225 : *firstp = first;
1706 : }
1707 :
1708 1486293 : if (!DECL_IGNORED_P (current_function_decl))
1709 1458007 : debug_hooks->begin_prologue (last_linenum, last_columnnum,
1710 : last_filename);
1711 :
1712 1486293 : if (!dwarf2_debug_info_emitted_p (current_function_decl))
1713 926040 : dwarf2out_begin_prologue (0, 0, NULL);
1714 :
1715 1486293 : if (DECL_IGNORED_P (current_function_decl) && last_linenum && last_filename)
1716 22116 : 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 1486293 : if (targetm.profile_before_prologue () && crtl->profile)
1726 : {
1727 330 : if (targetm.asm_out.function_prologue == default_function_pro_epilogue
1728 330 : && targetm.have_prologue ())
1729 : {
1730 : rtx_insn *insn;
1731 660 : for (insn = first; insn; insn = NEXT_INSN (insn))
1732 660 : if (!NOTE_P (insn))
1733 : {
1734 : insn = NULL;
1735 : break;
1736 : }
1737 660 : else if (NOTE_KIND (insn) == NOTE_INSN_BASIC_BLOCK
1738 330 : || NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
1739 : break;
1740 330 : else if (NOTE_KIND (insn) == NOTE_INSN_DELETED
1741 0 : || NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
1742 330 : continue;
1743 : else
1744 : {
1745 : insn = NULL;
1746 : break;
1747 : }
1748 :
1749 330 : if (insn)
1750 330 : 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 1486293 : if (write_symbols)
1761 : {
1762 572820 : reemit_insn_block_notes ();
1763 572820 : 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 572820 : TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
1768 : }
1769 :
1770 1486293 : unsigned HOST_WIDE_INT min_frame_size
1771 1486293 : = constant_lower_bound (get_frame_size ());
1772 1486293 : 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 1486293 : 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 1486293 : if (! targetm.have_prologue ())
1786 0 : profile_after_prologue (file);
1787 1486293 : }
1788 :
1789 : /* This is an exported final_start_function_1, callable without SEEN. */
1790 :
1791 : void
1792 5344 : final_start_function (rtx_insn *first, FILE *file,
1793 : int optimize_p ATTRIBUTE_UNUSED)
1794 : {
1795 5344 : int seen = 0;
1796 5344 : final_start_function_1 (&first, file, &seen, optimize_p);
1797 5344 : gcc_assert (seen == 0);
1798 5344 : }
1799 :
1800 : static void
1801 1482710 : profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
1802 : {
1803 1482710 : if (!targetm.profile_before_prologue () && crtl->profile)
1804 12 : profile_function (file);
1805 1482710 : }
1806 :
1807 : static void
1808 342 : 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 342 : rtx sval = NULL, chain = NULL;
1815 :
1816 342 : if (cfun->returns_struct)
1817 0 : sval = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl),
1818 : true);
1819 342 : if (cfun->static_chain_decl)
1820 1 : chain = targetm.calls.static_chain (current_function_decl, true);
1821 : #endif /* ASM_OUTPUT_REG_PUSH */
1822 :
1823 342 : 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 342 : switch_to_section (current_function_section ());
1833 :
1834 : #ifdef ASM_OUTPUT_REG_PUSH
1835 342 : if (sval && REG_P (sval))
1836 0 : ASM_OUTPUT_REG_PUSH (file, REGNO (sval));
1837 342 : if (chain && REG_P (chain))
1838 1 : ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
1839 : #endif
1840 :
1841 342 : FUNCTION_PROFILER (file, current_function_funcdef_no);
1842 :
1843 : #ifdef ASM_OUTPUT_REG_PUSH
1844 342 : if (chain && REG_P (chain))
1845 1 : ASM_OUTPUT_REG_POP (file, REGNO (chain));
1846 342 : if (sval && REG_P (sval))
1847 0 : ASM_OUTPUT_REG_POP (file, REGNO (sval));
1848 : #endif
1849 342 : }
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 1486293 : final_end_function (void)
1857 : {
1858 1486293 : app_disable ();
1859 :
1860 1486293 : if (!DECL_IGNORED_P (current_function_decl))
1861 1458007 : 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 1486293 : targetm.asm_out.function_epilogue (asm_out_file);
1866 :
1867 : /* And debug output. */
1868 1486293 : if (!DECL_IGNORED_P (current_function_decl))
1869 1458007 : debug_hooks->end_epilogue (last_linenum, last_filename);
1870 :
1871 1486293 : if (!dwarf2_debug_info_emitted_p (current_function_decl)
1872 1486293 : && dwarf2out_do_frame ())
1873 925985 : dwarf2out_end_epilogue (last_linenum, last_filename);
1874 :
1875 1486293 : some_local_dynamic_name = 0;
1876 1486293 : }
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 259687479 : 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 259687479 : basic_block bb;
1887 :
1888 259687479 : 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 1482710 : final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)
1931 : {
1932 1482710 : rtx_insn *insn, *next;
1933 :
1934 : /* Used for -dA dump. */
1935 1482710 : basic_block *start_to_bb = NULL;
1936 1482710 : basic_block *end_to_bb = NULL;
1937 1482710 : int bb_map_size = 0;
1938 1482710 : int bb_seqn = 0;
1939 :
1940 1482710 : last_ignored_compare = 0;
1941 :
1942 1482710 : init_recog ();
1943 :
1944 1482710 : CC_STATUS_INIT;
1945 :
1946 1482710 : 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 261170189 : for (insn = first; insn;)
1965 : {
1966 259687479 : if (HAVE_ATTR_length)
1967 : {
1968 259687479 : 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 57548212 : gcc_assert (NOTE_P (insn));
1973 57548212 : insn_current_address = -1;
1974 : }
1975 : else
1976 202139267 : 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 259687479 : insn_last_address = insn_current_address;
1980 : }
1981 :
1982 259687479 : dump_basic_block_info (file, insn, start_to_bb, end_to_bb,
1983 : bb_map_size, &bb_seqn);
1984 259687479 : insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
1985 : }
1986 :
1987 1482710 : maybe_output_next_view (&seen);
1988 :
1989 1482710 : 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 261170189 : for (insn = first; insn; insn = next)
1997 : {
1998 259687479 : next = NEXT_INSN (insn);
1999 259687479 : if (NOTE_P (insn)
2000 154206993 : && (NOTE_KIND (insn) == NOTE_INSN_CFI
2001 154206993 : || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL))
2002 11932010 : delete_insn (insn);
2003 : }
2004 1482710 : }
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 92669854 : get_insn_template (int code, rtx_insn *insn)
2025 : {
2026 92669854 : switch (insn_data[code].output_format)
2027 : {
2028 17682469 : case INSN_OUTPUT_FORMAT_SINGLE:
2029 17682469 : return insn_data[code].output.single;
2030 9968114 : case INSN_OUTPUT_FORMAT_MULTI:
2031 9968114 : return insn_data[code].output.multi[which_alternative];
2032 65019271 : case INSN_OUTPUT_FORMAT_FUNCTION:
2033 65019271 : gcc_assert (insn);
2034 65019271 : 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 37694958 : call_from_call_insn (const rtx_call_insn *insn)
2077 : {
2078 37694958 : rtx x;
2079 37694958 : gcc_assert (CALL_P (insn));
2080 37694958 : x = PATTERN (insn);
2081 :
2082 53993165 : while (GET_CODE (x) != CALL)
2083 : {
2084 16298207 : 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 1694092 : case PARALLEL:
2092 1694092 : x = XVECEXP (x, 0, 0);
2093 1694092 : break;
2094 14604115 : case SET:
2095 14604115 : x = XEXP (x, 1);
2096 14604115 : break;
2097 : }
2098 : }
2099 37694958 : return x;
2100 : }
2101 :
2102 : /* Return the CALL in X if there is one. */
2103 :
2104 : rtx
2105 31600331 : get_call_rtx_from (const rtx_insn *insn)
2106 : {
2107 31600331 : const rtx_call_insn *call_insn = as_a<const rtx_call_insn *> (insn);
2108 31600331 : 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 16410 : jumptable_relocatable (void)
2135 : {
2136 16410 : bool relocatable = false;
2137 :
2138 16410 : if (!CASE_VECTOR_PC_RELATIVE
2139 16410 : && !targetm.asm_out.generate_pic_addr_diff_vec ()
2140 16410 : && targetm_common.have_named_sections)
2141 14452 : relocatable = targetm.asm_out.reloc_rw_mask ();
2142 :
2143 16410 : 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 261111445 : final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
2160 : int nopeepholes ATTRIBUTE_UNUSED, int *seen)
2161 : {
2162 261111445 : rtx_insn *next;
2163 261111445 : rtx_jump_table_data *table;
2164 :
2165 261111445 : insn_counter++;
2166 :
2167 : /* Ignore deleted insns. These can occur when we split insns (due to a
2168 : template of "#") while not optimizing. */
2169 261111445 : if (insn->deleted ())
2170 0 : return NEXT_INSN (insn);
2171 :
2172 261111445 : switch (GET_CODE (insn))
2173 : {
2174 155630959 : case NOTE:
2175 155630959 : switch (NOTE_KIND (insn))
2176 : {
2177 : case NOTE_INSN_DELETED:
2178 : case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
2179 : break;
2180 :
2181 63742 : case NOTE_INSN_SWITCH_TEXT_SECTIONS:
2182 63742 : maybe_output_next_view (seen);
2183 :
2184 63742 : output_function_exception_table (0);
2185 :
2186 63742 : if (targetm.asm_out.unwind_emit)
2187 0 : targetm.asm_out.unwind_emit (asm_out_file, insn);
2188 :
2189 63742 : in_cold_section_p = !in_cold_section_p;
2190 :
2191 63742 : gcc_checking_assert (in_cold_section_p);
2192 63742 : if (in_cold_section_p)
2193 63742 : cold_function_name
2194 63742 : = clone_function_name (current_function_decl, "cold");
2195 :
2196 63742 : if (dwarf2out_do_frame ())
2197 : {
2198 63740 : dwarf2out_switch_text_section ();
2199 63740 : if (!dwarf2_debug_info_emitted_p (current_function_decl)
2200 63740 : && !DECL_IGNORED_P (current_function_decl))
2201 42663 : debug_hooks->switch_text_section ();
2202 : }
2203 2 : else if (!DECL_IGNORED_P (current_function_decl))
2204 1 : debug_hooks->switch_text_section ();
2205 63939 : if (DECL_IGNORED_P (current_function_decl) && last_linenum
2206 63939 : && last_filename)
2207 197 : debug_hooks->set_ignored_loc (last_linenum, last_columnnum,
2208 : last_filename);
2209 :
2210 63742 : switch_to_section (current_function_section ());
2211 63742 : 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 63742 : if (in_cold_section_p)
2217 : {
2218 : #ifdef ASM_DECLARE_COLD_FUNCTION_NAME
2219 63742 : 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 63742 : if (dwarf2out_do_frame ()
2228 63742 : && cfun->fde->dw_fde_second_begin != NULL)
2229 63740 : ASM_OUTPUT_LABEL (asm_out_file, cfun->fde->dw_fde_second_begin);
2230 : }
2231 : break;
2232 :
2233 14269836 : case NOTE_INSN_BASIC_BLOCK:
2234 14269836 : if (need_profile_function)
2235 : {
2236 330 : profile_function (asm_out_file);
2237 330 : need_profile_function = false;
2238 : }
2239 :
2240 14269836 : if (targetm.asm_out.unwind_emit)
2241 0 : targetm.asm_out.unwind_emit (asm_out_file, insn);
2242 :
2243 : break;
2244 :
2245 394979 : case NOTE_INSN_EH_REGION_BEG:
2246 394979 : ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
2247 : NOTE_EH_HANDLER (insn));
2248 394979 : break;
2249 :
2250 394979 : case NOTE_INSN_EH_REGION_END:
2251 394979 : ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
2252 : NOTE_EH_HANDLER (insn));
2253 394979 : break;
2254 :
2255 1482710 : case NOTE_INSN_PROLOGUE_END:
2256 1482710 : targetm.asm_out.function_end_prologue (file);
2257 1482710 : profile_after_prologue (file);
2258 :
2259 1482710 : if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
2260 : {
2261 625748 : *seen |= SEEN_EMITTED;
2262 625748 : force_source_line = true;
2263 : }
2264 : else
2265 856962 : *seen |= SEEN_NOTE;
2266 :
2267 : break;
2268 :
2269 1583430 : case NOTE_INSN_EPILOGUE_BEG:
2270 1583430 : if (!DECL_IGNORED_P (current_function_decl))
2271 1561125 : (*debug_hooks->begin_epilogue) (last_linenum, last_filename);
2272 1583430 : targetm.asm_out.function_begin_epilogue (file);
2273 1583430 : break;
2274 :
2275 11926179 : case NOTE_INSN_CFI:
2276 11926179 : dwarf2out_emit_cfi (NOTE_CFI (insn));
2277 11926179 : break;
2278 :
2279 5831 : case NOTE_INSN_CFI_LABEL:
2280 5831 : ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI",
2281 : NOTE_LABEL_NUMBER (insn));
2282 5831 : break;
2283 :
2284 1480949 : case NOTE_INSN_FUNCTION_BEG:
2285 1480949 : if (need_profile_function)
2286 : {
2287 0 : profile_function (asm_out_file);
2288 0 : need_profile_function = false;
2289 : }
2290 :
2291 1480949 : app_disable ();
2292 1480949 : if (!DECL_IGNORED_P (current_function_decl))
2293 1456246 : debug_hooks->end_prologue (last_linenum, last_filename);
2294 :
2295 1480949 : if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
2296 : {
2297 855201 : *seen |= SEEN_EMITTED;
2298 855201 : force_source_line = true;
2299 : }
2300 : else
2301 625748 : *seen |= SEEN_NOTE;
2302 :
2303 : break;
2304 :
2305 22808099 : case NOTE_INSN_BLOCK_BEG:
2306 22808099 : if (debug_info_level >= DINFO_LEVEL_NORMAL
2307 31388 : || dwarf_debuginfo_p ()
2308 22808099 : || write_symbols == VMS_DEBUG)
2309 : {
2310 22808099 : int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
2311 :
2312 22808099 : app_disable ();
2313 22808099 : ++block_depth;
2314 22808099 : high_block_linenum = last_linenum;
2315 :
2316 : /* Output debugging info about the symbol-block beginning. */
2317 22808099 : if (!DECL_IGNORED_P (current_function_decl))
2318 22808099 : debug_hooks->begin_block (last_linenum, n, NOTE_BLOCK (insn));
2319 :
2320 : /* Mark this block as output. */
2321 22808099 : TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
2322 22808099 : BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
2323 : }
2324 : break;
2325 :
2326 22808099 : case NOTE_INSN_BLOCK_END:
2327 22808099 : maybe_output_next_view (seen);
2328 :
2329 22808099 : if (debug_info_level >= DINFO_LEVEL_NORMAL
2330 31388 : || dwarf_debuginfo_p ()
2331 22808099 : || write_symbols == VMS_DEBUG)
2332 : {
2333 22808099 : int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
2334 :
2335 22808099 : app_disable ();
2336 :
2337 : /* End of a symbol-block. */
2338 22808099 : --block_depth;
2339 22808099 : gcc_assert (block_depth >= 0);
2340 :
2341 22808099 : if (!DECL_IGNORED_P (current_function_decl))
2342 22808099 : debug_hooks->end_block (high_block_linenum, n);
2343 22808099 : gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
2344 : == in_cold_section_p);
2345 : }
2346 : break;
2347 :
2348 57753 : 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 57753 : ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
2353 57753 : 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 58782354 : case NOTE_INSN_VAR_LOCATION:
2362 58782354 : if (!DECL_IGNORED_P (current_function_decl))
2363 : {
2364 58749175 : debug_hooks->var_location (insn);
2365 58749175 : set_next_view_needed (seen);
2366 : }
2367 : break;
2368 :
2369 4005957 : case NOTE_INSN_BEGIN_STMT:
2370 4005957 : gcc_checking_assert (cfun->debug_nonbind_markers);
2371 4005957 : if (!DECL_IGNORED_P (current_function_decl)
2372 4005957 : && notice_source_line (insn, NULL))
2373 : {
2374 10764840 : output_source_line:
2375 10764840 : (*debug_hooks->source_line) (last_linenum, last_columnnum,
2376 : last_filename, last_discriminator,
2377 : true);
2378 10764840 : clear_next_view_needed (seen);
2379 : }
2380 : break;
2381 :
2382 6758893 : case NOTE_INSN_INLINE_ENTRY:
2383 6758893 : gcc_checking_assert (cfun->debug_nonbind_markers);
2384 6758893 : if (!DECL_IGNORED_P (current_function_decl)
2385 6758893 : && notice_source_line (insn, NULL))
2386 : {
2387 6758883 : (*debug_hooks->inline_entry) (LOCATION_BLOCK
2388 : (NOTE_MARKER_LOCATION (insn)));
2389 6758883 : 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 6893829 : 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 6893829 : if (CODE_LABEL_NUMBER (insn) <= max_labelno)
2406 : {
2407 6893827 : align_flags alignment = LABEL_TO_ALIGNMENT (insn);
2408 8205909 : if (alignment.levels[0].log && NEXT_INSN (insn))
2409 : {
2410 : #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
2411 : /* Output both primary and secondary alignment. */
2412 1312082 : ASM_OUTPUT_MAX_SKIP_ALIGN (file, alignment.levels[0].log,
2413 : alignment.levels[0].maxskip);
2414 1312082 : 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 6893829 : CC_STATUS_INIT;
2426 :
2427 6893829 : if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn))
2428 69673 : debug_hooks->label (as_a <rtx_code_label *> (insn));
2429 :
2430 6893829 : 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 6893829 : table = jump_table_for_label (as_a <rtx_code_label *> (insn));
2436 6893829 : 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 8205 : if (! JUMP_TABLES_IN_TEXT_SECTION)
2444 : {
2445 8205 : int log_align;
2446 :
2447 8205 : switch_to_section (targetm.asm_out.function_rodata_section
2448 : (current_function_decl,
2449 8205 : jumptable_relocatable ()));
2450 :
2451 : #ifdef ADDR_VEC_ALIGN
2452 8205 : log_align = ADDR_VEC_ALIGN (table);
2453 : #else
2454 : log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
2455 : #endif
2456 8205 : ASM_OUTPUT_ALIGN (file, log_align);
2457 : }
2458 : else
2459 : switch_to_section (current_function_section ());
2460 :
2461 : #ifdef ASM_OUTPUT_CASE_LABEL
2462 8205 : 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 8205 : break;
2468 : }
2469 6885624 : if (LABEL_ALT_ENTRY_P (insn))
2470 0 : output_alternate_entry_point (file, insn);
2471 : else
2472 6885624 : targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
2473 : break;
2474 :
2475 93831258 : default:
2476 93831258 : {
2477 93831258 : rtx body = PATTERN (insn);
2478 93831258 : int insn_code_number;
2479 93831258 : const char *templ;
2480 93831258 : bool is_stmt, *is_stmt_p;
2481 :
2482 93831258 : if (MAY_HAVE_DEBUG_MARKER_INSNS && cfun->debug_nonbind_markers)
2483 : {
2484 21277852 : is_stmt = false;
2485 21277852 : 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 93831258 : 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 93831258 : if (GET_CODE (body) == USE /* These are just declarations. */
2497 93831258 : || GET_CODE (body) == CLOBBER)
2498 : break;
2499 :
2500 : /* Detect insns that are really jump-tables
2501 : and output them as such. */
2502 :
2503 92787467 : if (JUMP_TABLE_DATA_P (insn))
2504 : {
2505 : #if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
2506 8205 : int vlen, idx;
2507 : #endif
2508 :
2509 8205 : if (! JUMP_TABLES_IN_TEXT_SECTION)
2510 8205 : switch_to_section (targetm.asm_out.function_rodata_section
2511 : (current_function_decl,
2512 8205 : jumptable_relocatable ()));
2513 : else
2514 : switch_to_section (current_function_section ());
2515 :
2516 8205 : 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 8205 : vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
2537 176812 : for (idx = 0; idx < vlen; idx++)
2538 : {
2539 168607 : if (GET_CODE (body) == ADDR_VEC)
2540 : {
2541 : #ifdef ASM_OUTPUT_ADDR_VEC_ELT
2542 145331 : 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 8205 : switch_to_section (current_function_section ());
2569 :
2570 8205 : if (debug_variable_location_views
2571 8205 : && !DECL_IGNORED_P (current_function_decl))
2572 7272 : 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 92779262 : if (!DECL_IGNORED_P (current_function_decl)
2579 92779262 : && notice_source_line (insn, is_stmt_p))
2580 : {
2581 27242832 : if (flag_verbose_asm)
2582 32 : asm_show_source (last_filename, last_linenum);
2583 27242832 : (*debug_hooks->source_line) (last_linenum, last_columnnum,
2584 : last_filename, last_discriminator,
2585 : is_stmt);
2586 27242832 : clear_next_view_needed (seen);
2587 : }
2588 : else
2589 65536430 : maybe_output_next_view (seen);
2590 :
2591 92779262 : gcc_checking_assert (!DEBUG_INSN_P (insn));
2592 :
2593 92779262 : if (GET_CODE (body) == PARALLEL
2594 11649620 : && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
2595 92779262 : body = XVECEXP (body, 0, 0);
2596 :
2597 92779262 : if (GET_CODE (body) == ASM_INPUT)
2598 : {
2599 2890 : const char *string = XSTR (body, 0);
2600 :
2601 : /* There's no telling what that did to the condition codes. */
2602 2890 : CC_STATUS_INIT;
2603 :
2604 2890 : if (string[0])
2605 : {
2606 784 : expanded_location loc;
2607 :
2608 784 : app_enable ();
2609 784 : loc = expand_location (ASM_INPUT_SOURCE_LOCATION (body));
2610 784 : if (*loc.file && loc.line)
2611 784 : fprintf (asm_out_file, "%s %i \"%s\" 1\n",
2612 : ASM_COMMENT_START, loc.line, loc.file);
2613 784 : fprintf (asm_out_file, "\t%s\n", string);
2614 : #if HAVE_AS_LINE_ZERO
2615 784 : if (*loc.file && loc.line)
2616 784 : 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 92776372 : if (asm_noperands (body) >= 0)
2624 : {
2625 106577 : unsigned int noperands = asm_noperands (body);
2626 106577 : rtx *ops = XALLOCAVEC (rtx, noperands);
2627 106577 : const char *string;
2628 106577 : location_t loc;
2629 106577 : expanded_location expanded;
2630 :
2631 : /* There's no telling what that did to the condition codes. */
2632 106577 : CC_STATUS_INIT;
2633 :
2634 : /* Get out the operand values. */
2635 106577 : string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc);
2636 : /* Inhibit dying on what would otherwise be compiler bugs. */
2637 106577 : insn_noperands = noperands;
2638 106577 : this_is_asm_operands = insn;
2639 106577 : 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 106577 : if (string[0])
2647 : {
2648 35301 : app_enable ();
2649 35301 : if (expanded.file && expanded.line)
2650 35241 : fprintf (asm_out_file, "%s %i \"%s\" 1\n",
2651 : ASM_COMMENT_START, expanded.line, expanded.file);
2652 35301 : output_asm_insn (string, ops);
2653 : #if HAVE_AS_LINE_ZERO
2654 35301 : if (expanded.file && expanded.line)
2655 35241 : fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
2656 : #endif
2657 : }
2658 :
2659 106577 : if (targetm.asm_out.final_postscan_insn)
2660 0 : targetm.asm_out.final_postscan_insn (file, insn, ops,
2661 : insn_noperands);
2662 :
2663 106577 : this_is_asm_operands = 0;
2664 106577 : break;
2665 : }
2666 :
2667 92669795 : app_disable ();
2668 :
2669 92669795 : 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 92669795 : body = PATTERN (insn);
2718 :
2719 : /* Do machine-specific peephole optimizations if desired. */
2720 :
2721 92669795 : 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 92669795 : insn_code_number = recog_memoized (insn);
2757 92669795 : 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 92669795 : 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 92669795 : 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 92669795 : if (targetm.have_conditional_execution ()
2783 92669795 : && GET_CODE (PATTERN (insn)) == COND_EXEC)
2784 0 : current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
2785 :
2786 92669795 : current_output_insn = debug_insn = insn;
2787 :
2788 : /* Find the proper template for this insn. */
2789 92669795 : 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 92669795 : 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 92669795 : 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 92669795 : if (targetm.asm_out.unwind_emit_before_insn
2837 92669795 : && targetm.asm_out.unwind_emit)
2838 0 : targetm.asm_out.unwind_emit (asm_out_file, insn);
2839 :
2840 92669795 : rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn);
2841 6094627 : if (call_insn != NULL)
2842 : {
2843 6094627 : rtx x = call_from_call_insn (call_insn);
2844 6094627 : x = XEXP (x, 0);
2845 6094627 : if (x && MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
2846 : {
2847 5890373 : tree t;
2848 5890373 : x = XEXP (x, 0);
2849 5890373 : t = SYMBOL_REF_DECL (x);
2850 5890373 : if (t)
2851 5628704 : assemble_external (t);
2852 : }
2853 : }
2854 :
2855 : /* Output assembler code from the template. */
2856 92669795 : output_asm_insn (templ, recog_data.operand);
2857 :
2858 : /* Some target machines need to postscan each insn after
2859 : it is output. */
2860 92669795 : 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 92669795 : 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 50959883 : if ((debug_variable_location_views || call_insn != NULL)
2872 95621256 : && !DECL_IGNORED_P (current_function_decl))
2873 44614108 : debug_hooks->var_location (insn);
2874 :
2875 92669795 : current_output_insn = debug_insn = 0;
2876 : }
2877 : }
2878 261111445 : 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 261111445 : final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
2889 : int nopeepholes, int *seen)
2890 : {
2891 261111445 : static int *enclosing_seen;
2892 261111445 : static int recursion_counter;
2893 :
2894 261111445 : gcc_assert (seen || recursion_counter);
2895 261111445 : gcc_assert (!recursion_counter || !seen || seen == enclosing_seen);
2896 :
2897 261111445 : if (!recursion_counter++)
2898 261111445 : enclosing_seen = seen;
2899 0 : else if (!seen)
2900 0 : seen = enclosing_seen;
2901 :
2902 261111445 : rtx_insn *ret = final_scan_insn_1 (insn, file, optimize_p, nopeepholes, seen);
2903 :
2904 261111445 : if (!--recursion_counter)
2905 261111445 : enclosing_seen = NULL;
2906 :
2907 261111445 : 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 94670010 : compute_discriminator (location_t loc)
2943 : {
2944 94670010 : int discriminator;
2945 :
2946 94670010 : if (!decl_to_instance_map)
2947 94670010 : 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 94670010 : return discriminator;
2969 : }
2970 :
2971 : /* Return discriminator of the statement that produced this insn. */
2972 : int
2973 83905170 : insn_discriminator (const rtx_insn *insn)
2974 : {
2975 83905170 : 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 103438711 : notice_source_line (rtx_insn *insn, bool *is_stmt)
2984 : {
2985 103438711 : const char *filename;
2986 103438711 : int linenum, columnnum;
2987 103438711 : int discriminator;
2988 :
2989 103438711 : if (NOTE_MARKER_P (insn))
2990 : {
2991 10764850 : location_t loc = NOTE_MARKER_LOCATION (insn);
2992 10764850 : expanded_location xloc = expand_location (loc);
2993 10764850 : if (xloc.line == 0
2994 10764850 : && (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION
2995 20 : || LOCATION_LOCUS (loc) == BUILTINS_LOCATION))
2996 10 : return false;
2997 :
2998 10764840 : filename = xloc.file;
2999 10764840 : linenum = xloc.line;
3000 10764840 : columnnum = xloc.column;
3001 10764840 : discriminator = compute_discriminator (loc);
3002 10764840 : force_source_line = true;
3003 10764840 : }
3004 92673861 : 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 92673861 : else if (INSN_HAS_LOCATION (insn))
3012 : {
3013 83817010 : expanded_location xloc = insn_location (insn);
3014 83817010 : filename = xloc.file;
3015 83817010 : linenum = xloc.line;
3016 83817010 : columnnum = xloc.column;
3017 83817010 : discriminator = insn_discriminator (insn);
3018 : }
3019 : else
3020 : {
3021 : filename = NULL;
3022 : linenum = 0;
3023 : columnnum = 0;
3024 : discriminator = 0;
3025 : }
3026 :
3027 94581850 : if (filename == NULL)
3028 8856851 : return false;
3029 :
3030 94581850 : if (force_source_line
3031 82612216 : || filename != last_filename
3032 79665264 : || last_linenum != linenum
3033 67636707 : || (debug_column_info && last_columnnum != columnnum))
3034 : {
3035 31425943 : force_source_line = false;
3036 31425943 : last_filename = filename;
3037 31425943 : last_linenum = linenum;
3038 31425943 : last_columnnum = columnnum;
3039 31425943 : last_discriminator = discriminator;
3040 31425943 : if (is_stmt)
3041 12262944 : *is_stmt = true;
3042 31425943 : high_block_linenum = MAX (last_linenum, high_block_linenum);
3043 31425943 : high_function_linenum = MAX (last_linenum, high_function_linenum);
3044 31425943 : return true;
3045 : }
3046 :
3047 63155907 : 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 6581729 : last_discriminator = discriminator;
3053 6581729 : if (is_stmt)
3054 6169524 : *is_stmt = false;
3055 6581729 : 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 101128067 : cleanup_subreg_operands (rtx_insn *insn)
3066 : {
3067 101128067 : int i;
3068 101128067 : bool changed = false;
3069 101128067 : extract_insn_cached (insn);
3070 413534510 : 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 211278376 : if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
3078 : {
3079 121 : recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i], true);
3080 121 : changed = true;
3081 : }
3082 211278255 : 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 49628969 : recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i], &changed);
3086 : }
3087 :
3088 103127660 : for (i = 0; i < recog_data.n_dups; i++)
3089 : {
3090 1999593 : 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 1999593 : else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
3096 1999593 : || GET_CODE (*recog_data.dup_loc[i]) == MULT
3097 1999593 : || MEM_P (*recog_data.dup_loc[i]))
3098 558046 : *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed);
3099 : }
3100 101128067 : if (changed)
3101 121 : df_insn_rescan (insn);
3102 101128067 : }
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 3168536 : alter_subreg (rtx *xp, bool final_p)
3109 : {
3110 3168536 : rtx x = *xp;
3111 3168536 : rtx y = SUBREG_REG (x);
3112 :
3113 : /* simplify_subreg does not remove subreg from volatile references.
3114 : We are required to. */
3115 3168536 : if (MEM_P (y))
3116 : {
3117 228188 : 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 228188 : if (paradoxical_subreg_p (x))
3122 35631 : offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y));
3123 :
3124 228188 : if (final_p)
3125 46 : *xp = adjust_address (y, GET_MODE (x), offset);
3126 : else
3127 228142 : *xp = adjust_address_nv (y, GET_MODE (x), offset);
3128 : }
3129 2940348 : else if (REG_P (y) && HARD_REGISTER_P (y))
3130 : {
3131 5880694 : rtx new_rtx = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
3132 2940347 : SUBREG_BYTE (x));
3133 :
3134 2940347 : if (new_rtx != 0)
3135 2934934 : *xp = new_rtx;
3136 5413 : else if (final_p && REG_P (y))
3137 : {
3138 : /* Simplify_subreg can't handle some REG cases, but we have to. */
3139 2097 : unsigned int regno;
3140 2097 : poly_int64 offset;
3141 :
3142 2097 : regno = subreg_regno (x);
3143 2097 : if (subreg_lowpart_p (x))
3144 2097 : offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y));
3145 : else
3146 0 : offset = SUBREG_BYTE (x);
3147 2097 : *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, offset);
3148 : }
3149 : }
3150 :
3151 3168536 : return *xp;
3152 : }
3153 :
3154 : /* Do alter_subreg on all the SUBREGs contained in X. */
3155 :
3156 : static rtx
3157 168325874 : walk_alter_subreg (rtx *xp, bool *changed)
3158 : {
3159 168325874 : rtx x = *xp;
3160 168325874 : switch (GET_CODE (x))
3161 : {
3162 35165149 : case PLUS:
3163 35165149 : case MULT:
3164 35165149 : case AND:
3165 35165149 : case ASHIFT:
3166 35165149 : XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed);
3167 35165149 : XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1), changed);
3168 35165149 : break;
3169 :
3170 44244713 : case MEM:
3171 44244713 : case ZERO_EXTEND:
3172 44244713 : XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0), changed);
3173 44244713 : 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 168325873 : 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 252264034 : do_assembler_dialects (const char *p, int *dialect)
3326 : {
3327 252264034 : char c = *(p - 1);
3328 :
3329 252264034 : switch (c)
3330 : {
3331 126132016 : case '{':
3332 126132016 : {
3333 126132016 : int i;
3334 :
3335 126132016 : if (*dialect)
3336 0 : output_operand_lossage ("nested assembly dialect alternatives");
3337 : else
3338 126132016 : *dialect = 1;
3339 :
3340 : /* If we want the first dialect, do nothing. Otherwise, skip
3341 : DIALECT_NUMBER of strings ending with '|'. */
3342 126133132 : for (i = 0; i < dialect_number; i++)
3343 : {
3344 9419 : while (*p && *p != '}')
3345 : {
3346 8846 : if (*p == '|')
3347 : {
3348 1116 : p++;
3349 1116 : break;
3350 : }
3351 :
3352 : /* Skip over any character after a percent sign. */
3353 7730 : if (*p == '%')
3354 2745 : p++;
3355 7730 : if (*p)
3356 7730 : p++;
3357 : }
3358 :
3359 1689 : if (*p == '}')
3360 : break;
3361 : }
3362 :
3363 126132016 : if (*p == '\0')
3364 0 : output_operand_lossage ("unterminated assembly dialect alternative");
3365 : }
3366 : break;
3367 :
3368 64798443 : case '|':
3369 64798443 : if (*dialect)
3370 : {
3371 : /* Skip to close brace. */
3372 344785983 : do
3373 : {
3374 344785983 : 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 344785983 : if (*p == '%' && p[1])
3382 : {
3383 126990317 : p += 2;
3384 126990317 : continue;
3385 : }
3386 :
3387 217795666 : if (*p++ == '}')
3388 : break;
3389 : }
3390 : while (1);
3391 :
3392 64798442 : *dialect = 0;
3393 : }
3394 : else
3395 1 : putc (c, asm_out_file);
3396 : break;
3397 :
3398 61333575 : case '}':
3399 61333575 : if (! *dialect)
3400 1 : putc (c, asm_out_file);
3401 61333575 : *dialect = 0;
3402 61333575 : break;
3403 0 : default:
3404 0 : gcc_unreachable ();
3405 : }
3406 :
3407 252264034 : 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 104893229 : output_asm_insn (const char *templ, rtx *operands)
3429 : {
3430 104893229 : const char *p;
3431 104893229 : int c;
3432 : #ifdef ASSEMBLER_DIALECT
3433 104893229 : int dialect = 0;
3434 : #endif
3435 104893229 : int oporder[MAX_RECOG_OPERANDS+1];
3436 104893229 : char opoutput[MAX_RECOG_OPERANDS+1];
3437 104893229 : int ops = 0;
3438 :
3439 : /* An insn may return a null string template
3440 : in a case where no assembler code is needed. */
3441 104893229 : if (*templ == 0)
3442 13020630 : return;
3443 :
3444 91872599 : memset (opoutput, 0, sizeof opoutput);
3445 91872599 : p = templ;
3446 91872599 : putc ('\t', asm_out_file);
3447 :
3448 : #ifdef ASM_OUTPUT_OPCODE
3449 99602952 : ASM_OUTPUT_OPCODE (asm_out_file, p);
3450 : #endif
3451 :
3452 1126911802 : while ((c = *p++))
3453 1035039203 : switch (c)
3454 : {
3455 41317 : case '\n':
3456 41317 : if (flag_verbose_asm)
3457 0 : output_asm_operand_names (operands, oporder, ops);
3458 41317 : if (flag_print_asm_name)
3459 74 : output_asm_name ();
3460 :
3461 41317 : ops = 0;
3462 41317 : memset (opoutput, 0, sizeof opoutput);
3463 :
3464 41317 : putc (c, asm_out_file);
3465 : #ifdef ASM_OUTPUT_OPCODE
3466 120443 : while ((c = *p) == '\t')
3467 : {
3468 37809 : putc (c, asm_out_file);
3469 37809 : p++;
3470 : }
3471 41317 : ASM_OUTPUT_OPCODE (asm_out_file, p);
3472 : #endif
3473 : break;
3474 :
3475 : #ifdef ASSEMBLER_DIALECT
3476 252264034 : case '{':
3477 252264034 : case '}':
3478 252264034 : case '|':
3479 252264034 : p = do_assembler_dialects (p, &dialect);
3480 252264034 : break;
3481 : #endif
3482 :
3483 186240221 : 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 186240221 : if (*p == '%'
3488 : #ifdef ASSEMBLER_DIALECT
3489 186209794 : || *p == '{' || *p == '}' || *p == '|'
3490 : #endif
3491 : )
3492 : {
3493 147117 : putc (*p, asm_out_file);
3494 147117 : 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 186093104 : 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 186093085 : else if (ISALPHA (*p))
3510 : {
3511 49580819 : int letter = *p++;
3512 49580819 : unsigned long opnum;
3513 49580819 : char *endptr;
3514 49580819 : int letter2 = 0;
3515 :
3516 49580819 : if (letter == 'c' && *p == 'c')
3517 98 : letter2 = *p++;
3518 49580819 : opnum = strtoul (p, &endptr, 10);
3519 :
3520 49580819 : if (endptr == p)
3521 0 : output_operand_lossage ("operand number missing "
3522 : "after %%-letter");
3523 49580819 : 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 49580815 : else if (letter == 'l')
3530 8763818 : output_asm_label (operands[opnum]);
3531 40816997 : else if (letter == 'a')
3532 2276 : output_address (VOIDmode, operands[opnum]);
3533 40814721 : else if (letter == 'c')
3534 : {
3535 204294 : if (letter2 == 'c' || CONSTANT_ADDRESS_P (operands[opnum]))
3536 1391 : output_addr_const (asm_out_file, operands[opnum]);
3537 : else
3538 202903 : output_operand (operands[opnum], 'c');
3539 : }
3540 40610427 : 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 40610427 : output_operand (operands[opnum], letter);
3553 :
3554 49580819 : if (!opoutput[opnum])
3555 47270231 : oporder[ops++] = opnum;
3556 49580819 : opoutput[opnum] = 1;
3557 :
3558 49580819 : p = endptr;
3559 49580819 : c = *p;
3560 : }
3561 : /* % followed by a digit outputs an operand the default way. */
3562 136512266 : else if (ISDIGIT (*p))
3563 : {
3564 115004121 : unsigned long opnum;
3565 115004121 : char *endptr;
3566 :
3567 115004121 : opnum = strtoul (p, &endptr, 10);
3568 115004121 : 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 115004118 : output_operand (operands[opnum], 0);
3576 :
3577 115004121 : if (!opoutput[opnum])
3578 112711073 : oporder[ops++] = opnum;
3579 115004121 : opoutput[opnum] = 1;
3580 :
3581 115004121 : p = endptr;
3582 115004121 : 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 21508145 : else if (targetm.asm_out.print_operand_punct_valid_p ((unsigned char) *p))
3588 21508145 : output_operand (NULL_RTX, *p++);
3589 : else
3590 0 : output_operand_lossage ("invalid %%-code");
3591 : break;
3592 :
3593 596493631 : default:
3594 596493631 : putc (c, asm_out_file);
3595 : }
3596 :
3597 : /* Try to keep the asm a bit more readable. */
3598 91872599 : 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 91872599 : if (flag_verbose_asm)
3603 243 : output_asm_operand_names (operands, oporder, ops);
3604 91872599 : if (flag_print_asm_name)
3605 3537 : output_asm_name ();
3606 :
3607 91872599 : 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 8771017 : output_asm_label (rtx x)
3614 : {
3615 8771017 : char buf[256];
3616 :
3617 8771017 : if (GET_CODE (x) == LABEL_REF)
3618 7358 : x = label_ref_label (x);
3619 8771017 : if (LABEL_P (x)
3620 96 : || (NOTE_P (x)
3621 96 : && NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL))
3622 8771017 : 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 8771017 : assemble_name (asm_out_file, buf);
3627 8771017 : }
3628 :
3629 : /* Marks SYMBOL_REFs in x as referenced through use of assemble_external. */
3630 :
3631 : void
3632 155817448 : mark_symbol_refs_as_used (rtx x)
3633 : {
3634 155817448 : subrtx_iterator::array_type array;
3635 426089504 : FOR_EACH_SUBRTX (iter, array, x, ALL)
3636 : {
3637 270272056 : const_rtx x = *iter;
3638 270272056 : if (GET_CODE (x) == SYMBOL_REF)
3639 15953696 : if (tree t = SYMBOL_REF_DECL (x))
3640 14758459 : assemble_external (t);
3641 : }
3642 155817448 : }
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 177325593 : output_operand (rtx x, int code ATTRIBUTE_UNUSED)
3655 : {
3656 177325593 : if (x && GET_CODE (x) == SUBREG)
3657 0 : x = alter_subreg (&x, true);
3658 :
3659 : /* X must not be a pseudo reg. */
3660 177325593 : if (!targetm.no_register_allocation)
3661 177325593 : gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
3662 :
3663 177325593 : targetm.asm_out.print_operand (asm_out_file, x, code);
3664 :
3665 177325593 : if (x == NULL_RTX)
3666 : return;
3667 :
3668 155817448 : 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 3563848 : output_address (machine_mode mode, rtx x)
3676 : {
3677 3563848 : bool changed = false;
3678 3563848 : walk_alter_subreg (&x, &changed);
3679 3563848 : targetm.asm_out.print_operand_address (asm_out_file, mode, x);
3680 3563848 : }
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 159984179 : output_addr_const (FILE *file, rtx x)
3688 : {
3689 170275460 : char buf[256];
3690 :
3691 170275460 : restart:
3692 170275460 : switch (GET_CODE (x))
3693 : {
3694 555 : case PC:
3695 555 : putc ('.', file);
3696 555 : break;
3697 :
3698 121523393 : case SYMBOL_REF:
3699 121523393 : if (SYMBOL_REF_DECL (x))
3700 20565535 : assemble_external (SYMBOL_REF_DECL (x));
3701 : #ifdef ASM_OUTPUT_SYMBOL_REF
3702 121523393 : ASM_OUTPUT_SYMBOL_REF (file, x);
3703 : #else
3704 : assemble_name (file, XSTR (x, 0));
3705 : #endif
3706 : break;
3707 :
3708 15045 : case LABEL_REF:
3709 15045 : x = label_ref_label (x);
3710 : /* Fall through. */
3711 15045 : case CODE_LABEL:
3712 15045 : 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 15045 : assemble_name (file, buf);
3717 : #endif
3718 15045 : break;
3719 :
3720 38429775 : case CONST_INT:
3721 38429775 : fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
3722 38429775 : break;
3723 :
3724 2775261 : 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 2775261 : output_addr_const (file, XEXP (x, 0));
3728 2775261 : 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 2794830 : case PLUS:
3768 : /* Some assemblers need integer constants to appear last (eg masm). */
3769 2794830 : 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 2794830 : output_addr_const (file, XEXP (x, 0));
3779 2794830 : if (!CONST_INT_P (XEXP (x, 1))
3780 2794830 : || INTVAL (XEXP (x, 1)) >= 0)
3781 2765761 : fprintf (file, "+");
3782 2794830 : output_addr_const (file, XEXP (x, 1));
3783 : }
3784 : break;
3785 :
3786 4721254 : case MINUS:
3787 : /* Avoid outputting things like x-x or x+5-x,
3788 : since some assemblers can't handle that. */
3789 4721254 : x = simplify_subtraction (x);
3790 4721254 : if (GET_CODE (x) != MINUS)
3791 0 : goto restart;
3792 :
3793 4721254 : output_addr_const (file, XEXP (x, 0));
3794 4721254 : fprintf (file, "-");
3795 4721254 : if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0)
3796 4721254 : || GET_CODE (XEXP (x, 1)) == PC
3797 4720699 : || 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 15345 : default:
3815 15345 : if (targetm.asm_out.output_addr_const_extra (file, x))
3816 : break;
3817 :
3818 0 : output_operand_lossage ("invalid expression as operand");
3819 : }
3820 159984179 : }
3821 :
3822 : /* Output a quoted string. */
3823 :
3824 : void
3825 1548820 : 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 1548820 : char c;
3831 :
3832 1548820 : putc ('\"', asm_file);
3833 92069051 : while ((c = *string++) != 0)
3834 : {
3835 88971411 : if (ISPRINT (c))
3836 : {
3837 88971399 : if (c == '\"' || c == '\\')
3838 15 : putc ('\\', asm_file);
3839 88971399 : putc (c, asm_file);
3840 : }
3841 : else
3842 12 : fprintf (asm_file, "\\%03o", (unsigned char) c);
3843 : }
3844 1548820 : putc ('\"', asm_file);
3845 : #endif
3846 1548820 : }
3847 :
3848 : /* Write a HOST_WIDE_INT number in hex form 0x1234, fast. */
3849 :
3850 : void
3851 490682249 : fprint_whex (FILE *f, unsigned HOST_WIDE_INT value)
3852 : {
3853 490682249 : char buf[2 + CHAR_BIT * sizeof (value) / 4];
3854 490682249 : if (value == 0)
3855 47007636 : putc ('0', f);
3856 : else
3857 : {
3858 : char *p = buf + sizeof (buf);
3859 921603667 : do
3860 921603667 : *--p = "0123456789abcdef"[value % 16];
3861 921603667 : while ((value /= 16) != 0);
3862 443674613 : *--p = 'x';
3863 443674613 : *--p = '0';
3864 443674613 : fwrite (p, 1, buf + sizeof (buf) - p, f);
3865 : }
3866 490682249 : }
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 425751506 : sprint_ul_rev (char *s, unsigned long value)
3873 : {
3874 0 : int i = 0;
3875 1306248131 : do
3876 : {
3877 1306248131 : s[i] = "0123456789"[value % 10];
3878 1306248131 : value /= 10;
3879 1306248131 : i++;
3880 : /* alternate version, without modulo */
3881 : /* oldval = value; */
3882 : /* value /= 10; */
3883 : /* s[i] = "0123456789" [oldval - 10*value]; */
3884 : /* i++ */
3885 : }
3886 1306248131 : while (value != 0);
3887 311352434 : return i;
3888 : }
3889 :
3890 : /* Write an unsigned long as decimal to a file, fast. */
3891 :
3892 : void
3893 114399072 : fprint_ul (FILE *f, unsigned long value)
3894 : {
3895 : /* python says: len(str(2**64)) == 20 */
3896 114399072 : char s[20];
3897 114399072 : int i;
3898 :
3899 114399072 : i = sprint_ul_rev (s, value);
3900 :
3901 : /* It's probably too small to bother with string reversal and fputs. */
3902 213650144 : do
3903 : {
3904 213650144 : i--;
3905 213650144 : putc (s[i], f);
3906 : }
3907 213650144 : while (i != 0);
3908 114399072 : }
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 311352434 : sprint_ul (char *s, unsigned long value)
3916 : {
3917 311352434 : int len = sprint_ul_rev (s, value);
3918 311352434 : s[len] = '\0';
3919 :
3920 311352434 : std::reverse (s, s + len);
3921 311352434 : 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 2991379 : leaf_function_p (void)
4081 : {
4082 2991379 : rtx_insn *insn;
4083 :
4084 : /* Ensure we walk the entire function body. */
4085 2991379 : 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 2991379 : if (crtl->profile && !targetm.keep_leaf_when_profiled ())
4090 : return false;
4091 :
4092 79157374 : for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4093 : {
4094 78072502 : if (CALL_P (insn)
4095 2049573 : && ! SIBLING_CALL_P (insn)
4096 79978425 : && ! FAKE_CALL_P (insn))
4097 : return false;
4098 76166679 : if (NONJUMP_INSN_P (insn)
4099 36889059 : && GET_CODE (PATTERN (insn)) == SEQUENCE
4100 0 : && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
4101 76166679 : && ! 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 1480949 : rest_of_handle_final (void)
4260 : {
4261 1480949 : 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 1480949 : if (!flag_var_tracking && MAY_HAVE_DEBUG_MARKER_INSNS)
4266 1 : delete_vta_debug_insns (false);
4267 :
4268 1480949 : assemble_start_function (current_function_decl, fnname);
4269 1480949 : rtx_insn *first = get_insns ();
4270 1480949 : int seen = 0;
4271 1480949 : final_start_function_1 (&first, asm_out_file, &seen, optimize);
4272 1480949 : final_1 (first, asm_out_file, seen, optimize);
4273 1480949 : if (flag_ipa_ra
4274 955631 : && !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 2418936 : && !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)))
4279 937987 : collect_fn_hard_reg_usage ();
4280 1480949 : 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 2898156 : output_function_exception_table (crtl->has_bb_partition ? 1 : 0);
4286 :
4287 1480949 : assemble_end_function (current_function_decl, fnname);
4288 :
4289 : /* Free up reg info memory. */
4290 1480949 : free_reg_info ();
4291 :
4292 1480949 : 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 1480949 : timevar_push (TV_SYMOUT);
4305 1480949 : if (!DECL_IGNORED_P (current_function_decl))
4306 1456246 : debug_hooks->function_decl (current_function_decl);
4307 1480949 : timevar_pop (TV_SYMOUT);
4308 :
4309 : /* Release the blocks that are linked to DECL_INITIAL() to free the memory. */
4310 1480949 : DECL_INITIAL (current_function_decl) = error_mark_node;
4311 :
4312 1480949 : if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
4313 1480949 : && targetm.have_ctors_dtors)
4314 24127 : targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0),
4315 : decl_init_priority_lookup
4316 24127 : (current_function_decl));
4317 1480949 : if (DECL_STATIC_DESTRUCTOR (current_function_decl)
4318 1480949 : && targetm.have_ctors_dtors)
4319 1586 : targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
4320 : decl_fini_priority_lookup
4321 1586 : (current_function_decl));
4322 1480949 : 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 287872 : pass_final (gcc::context *ctxt)
4344 575744 : : rtl_opt_pass (pass_data_final, ctxt)
4345 : {}
4346 :
4347 : /* opt_pass methods: */
4348 1480949 : unsigned int execute (function *) final override
4349 : {
4350 1480949 : return rest_of_handle_final ();
4351 : }
4352 :
4353 : }; // class pass_final
4354 :
4355 : } // anon namespace
4356 :
4357 : rtl_opt_pass *
4358 287872 : make_pass_final (gcc::context *ctxt)
4359 : {
4360 287872 : return new pass_final (ctxt);
4361 : }
4362 :
4363 :
4364 : static unsigned int
4365 1480948 : rest_of_handle_shorten_branches (void)
4366 : {
4367 : /* Shorten branches. */
4368 0 : shorten_branches (get_insns ());
4369 1480948 : 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 287872 : pass_shorten_branches (gcc::context *ctxt)
4391 575744 : : rtl_opt_pass (pass_data_shorten_branches, ctxt)
4392 : {}
4393 :
4394 : /* opt_pass methods: */
4395 1480948 : unsigned int execute (function *) final override
4396 : {
4397 1480948 : return rest_of_handle_shorten_branches ();
4398 : }
4399 :
4400 : }; // class pass_shorten_branches
4401 :
4402 : } // anon namespace
4403 :
4404 : rtl_opt_pass *
4405 287872 : make_pass_shorten_branches (gcc::context *ctxt)
4406 : {
4407 287872 : return new pass_shorten_branches (ctxt);
4408 : }
4409 :
4410 :
4411 : static unsigned int
4412 1481763 : rest_of_clean_state (void)
4413 : {
4414 1481763 : rtx_insn *insn, *next;
4415 1481763 : FILE *final_output = NULL;
4416 1481763 : int save_unnumbered = flag_dump_unnumbered;
4417 1481763 : int save_noaddr = flag_dump_noaddr;
4418 :
4419 1481763 : 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 147857 : for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4438 143873 : if (LABEL_P (insn))
4439 4899 : INSN_UID (insn) = CODE_LABEL_NUMBER (insn);
4440 : else
4441 : {
4442 138974 : if (NOTE_P (insn))
4443 65835 : set_block_for_insn (insn, NULL);
4444 138974 : 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 250699367 : for (insn = get_insns (); insn; insn = next)
4454 : {
4455 249217604 : next = NEXT_INSN (insn);
4456 249217604 : SET_NEXT_INSN (insn) = NULL;
4457 249217604 : SET_PREV_INSN (insn) = NULL;
4458 :
4459 249217604 : rtx_insn *call_insn = insn;
4460 249217604 : if (NONJUMP_INSN_P (call_insn)
4461 249217604 : && 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 249217604 : if (CALL_P (call_insn))
4467 : {
4468 6093887 : rtx note
4469 6093887 : = find_reg_note (call_insn, REG_CALL_ARG_LOCATION, NULL_RTX);
4470 6093887 : if (note)
4471 3141975 : remove_note (call_insn, note);
4472 : }
4473 :
4474 249217604 : if (final_output
4475 143873 : && (!NOTE_P (insn)
4476 65835 : || (NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION
4477 : && NOTE_KIND (insn) != NOTE_INSN_BEGIN_STMT
4478 65835 : && 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 1481763 : 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 1481763 : flag_rerun_cse_after_global_opts = 0;
4500 1481763 : reload_completed = 0;
4501 1481763 : epilogue_completed = 0;
4502 : #ifdef STACK_REGS
4503 1481763 : regstack_completed = 0;
4504 : #endif
4505 :
4506 : /* Clear out the insn_length contents now that they are no
4507 : longer valid. */
4508 1481763 : init_insn_lengths ();
4509 :
4510 : /* Show no temporary slots allocated. */
4511 1481763 : init_temp_slots ();
4512 :
4513 1481763 : free_bb_for_insn ();
4514 :
4515 1481763 : if (cfun->gimple_df)
4516 1481721 : 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 1481763 : if (flag_ipa_stack_alignment
4522 1481763 : && decl_binds_to_current_def_p (current_function_decl))
4523 : {
4524 1237883 : unsigned int pref = crtl->preferred_stack_boundary;
4525 1237883 : if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary)
4526 : pref = crtl->stack_alignment_needed;
4527 1237883 : cgraph_node::rtl_info (current_function_decl)
4528 1237883 : ->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 1481763 : init_recog_no_volatile ();
4540 :
4541 : /* We're done with this function. Free up memory if we can. */
4542 1481763 : free_after_parsing (cfun);
4543 1481763 : free_after_compilation (cfun);
4544 1481763 : 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 287872 : pass_clean_state (gcc::context *ctxt)
4566 575744 : : rtl_opt_pass (pass_data_clean_state, ctxt)
4567 : {}
4568 :
4569 : /* opt_pass methods: */
4570 1481763 : unsigned int execute (function *) final override
4571 : {
4572 1481763 : return rest_of_clean_state ();
4573 : }
4574 :
4575 : }; // class pass_clean_state
4576 :
4577 : } // anon namespace
4578 :
4579 : rtl_opt_pass *
4580 287872 : make_pass_clean_state (gcc::context *ctxt)
4581 : {
4582 287872 : 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 813381 : self_recursive_call_p (rtx_insn *insn)
4589 : {
4590 813381 : tree fndecl = get_call_fndecl (insn);
4591 813381 : return (fndecl == current_function_decl
4592 813381 : && decl_binds_to_current_def_p (fndecl));
4593 : }
4594 :
4595 : /* Collect hard register usage for the current function. */
4596 :
4597 : static void
4598 937987 : collect_fn_hard_reg_usage (void)
4599 : {
4600 937987 : rtx_insn *insn;
4601 : #ifdef STACK_REGS
4602 937987 : int i;
4603 : #endif
4604 937987 : struct cgraph_rtl_info *node;
4605 937987 : HARD_REG_SET function_used_regs;
4606 :
4607 : /* ??? To be removed when all the ports have been fixed. */
4608 937987 : if (!targetm.call_fusage_contains_non_callee_clobbers)
4609 637229 : return;
4610 :
4611 : /* Be conservative - mark fixed and global registers as used. */
4612 937987 : 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 8441883 : for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
4619 7503896 : SET_HARD_REG_BIT (function_used_regs, i);
4620 : #endif
4621 :
4622 48896928 : for (insn = get_insns (); insn != NULL_RTX; insn = next_insn (insn))
4623 : {
4624 48596170 : HARD_REG_SET insn_used_regs;
4625 :
4626 48596170 : if (!NONDEBUG_INSN_P (insn))
4627 31341627 : continue;
4628 :
4629 17254543 : if (CALL_P (insn)
4630 17254543 : && !self_recursive_call_p (insn))
4631 810331 : function_used_regs
4632 1620662 : |= insn_callee_abi (insn).full_and_partial_reg_clobbers ();
4633 :
4634 17254543 : find_all_hard_reg_sets (insn, &insn_used_regs, false);
4635 17254543 : function_used_regs |= insn_used_regs;
4636 :
4637 34509086 : if (hard_reg_set_subset_p (crtl->abi->full_and_partial_reg_clobbers (),
4638 : function_used_regs))
4639 637229 : return;
4640 : }
4641 :
4642 : /* Mask out fully-saved registers, so that they don't affect equality
4643 : comparisons between function_abis. */
4644 300758 : function_used_regs &= crtl->abi->full_and_partial_reg_clobbers ();
4645 :
4646 300758 : node = cgraph_node::rtl_info (current_function_decl);
4647 300758 : gcc_assert (node != NULL);
4648 :
4649 300758 : node->function_used_regs = function_used_regs;
4650 : }
|