b96ab5e0544aa717d87428451ca5975cf4aba2d2
[platform/upstream/gcc.git] / gcc / print-rtl.c
1 /* Print RTL for GCC.
2    Copyright (C) 1987-2019 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 file is compiled twice: once for the generator programs,
21    once for the compiler.  */
22 #ifdef GENERATOR_FILE
23 #include "bconfig.h"
24 #else
25 #include "config.h"
26 #endif
27
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "rtl.h"
32
33 /* These headers all define things which are not available in
34    generator programs.  */
35 #ifndef GENERATOR_FILE
36 #include "alias.h"
37 #include "tree.h"
38 #include "basic-block.h"
39 #include "print-tree.h"
40 #include "flags.h"
41 #include "predict.h"
42 #include "function.h"
43 #include "cfg.h"
44 #include "basic-block.h"
45 #include "diagnostic.h"
46 #include "tree-pretty-print.h"
47 #include "alloc-pool.h"
48 #include "cselib.h"
49 #include "dumpfile.h"   /* for dump_flags */
50 #include "dwarf2out.h"
51 #include "pretty-print.h"
52 #endif
53
54 #include "print-rtl.h"
55 #include "rtl-iter.h"
56
57 /* Disable warnings about quoting issues in the pp_xxx calls below
58    that (intentionally) don't follow GCC diagnostic conventions.  */
59 #if __GNUC__ >= 10
60 #  pragma GCC diagnostic push
61 #  pragma GCC diagnostic ignored "-Wformat-diag"
62 #endif
63
64 /* String printed at beginning of each RTL when it is dumped.
65    This string is set to ASM_COMMENT_START when the RTL is dumped in
66    the assembly output file.  */
67 const char *print_rtx_head = "";
68
69 #ifdef GENERATOR_FILE
70 /* These are defined from the .opt file when not used in generator
71    programs.  */
72
73 /* Nonzero means suppress output of instruction numbers
74    in debugging dumps.
75    This must be defined here so that programs like gencodes can be linked.  */
76 int flag_dump_unnumbered = 0;
77
78 /* Nonzero means suppress output of instruction numbers for previous
79    and next insns in debugging dumps.
80    This must be defined here so that programs like gencodes can be linked.  */
81 int flag_dump_unnumbered_links = 0;
82 #endif
83
84 /* Constructor for rtx_writer.  */
85
86 rtx_writer::rtx_writer (FILE *outf, int ind, bool simple, bool compact,
87                         rtx_reuse_manager *reuse_manager)
88 : m_outfile (outf), m_sawclose (0), m_indent (ind),
89   m_in_call_function_usage (false), m_simple (simple), m_compact (compact),
90   m_rtx_reuse_manager (reuse_manager)
91 {
92 }
93
94 #ifndef GENERATOR_FILE
95
96 /* rtx_reuse_manager's ctor.  */
97
98 rtx_reuse_manager::rtx_reuse_manager ()
99 : m_next_id (0)
100 {
101 }
102
103 /* Determine if X is of a kind suitable for dumping via reuse_rtx.  */
104
105 static bool
106 uses_rtx_reuse_p (const_rtx x)
107 {
108   if (x == NULL)
109     return false;
110
111   switch (GET_CODE (x))
112     {
113     case DEBUG_EXPR:
114     case VALUE:
115     case SCRATCH:
116       return true;
117
118     /* We don't use reuse_rtx for consts.  */
119     CASE_CONST_UNIQUE:
120     default:
121       return false;
122     }
123 }
124
125 /* Traverse X and its descendents, determining if we see any rtx more than
126    once.  Any rtx suitable for "reuse_rtx" that is seen more than once is
127    assigned an ID.  */
128
129 void
130 rtx_reuse_manager::preprocess (const_rtx x)
131 {
132   subrtx_iterator::array_type array;
133   FOR_EACH_SUBRTX (iter, array, x, NONCONST)
134     if (uses_rtx_reuse_p (*iter))
135       {
136         if (int *count = m_rtx_occurrence_count.get (*iter))
137           {
138             if (*(count++) == 1)
139               m_rtx_reuse_ids.put (*iter, m_next_id++);
140           }
141         else
142           m_rtx_occurrence_count.put (*iter, 1);
143       }
144 }
145
146 /* Return true iff X has been assigned a reuse ID.  If it has,
147    and OUT is non-NULL, then write the reuse ID to *OUT.  */
148
149 bool
150 rtx_reuse_manager::has_reuse_id (const_rtx x, int *out)
151 {
152   int *id = m_rtx_reuse_ids.get (x);
153   if (id)
154     {
155       if (out)
156         *out = *id;
157       return true;
158     }
159   else
160     return false;
161 }
162
163 /* Determine if set_seen_def has been called for the given reuse ID.  */
164
165 bool
166 rtx_reuse_manager::seen_def_p (int reuse_id)
167 {
168   return bitmap_bit_p (m_defs_seen, reuse_id);
169 }
170
171 /* Record that the definition of the given reuse ID has been seen.  */
172
173 void
174 rtx_reuse_manager::set_seen_def (int reuse_id)
175 {
176   bitmap_set_bit (m_defs_seen, reuse_id);
177 }
178
179 #endif /* #ifndef GENERATOR_FILE */
180
181 #ifndef GENERATOR_FILE
182 void
183 print_mem_expr (FILE *outfile, const_tree expr)
184 {
185   fputc (' ', outfile);
186   print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags);
187 }
188 #endif
189
190 /* Print X to FILE.  */
191
192 static void
193 print_poly_int (FILE *file, poly_int64 x)
194 {
195   HOST_WIDE_INT const_x;
196   if (x.is_constant (&const_x))
197     fprintf (file, HOST_WIDE_INT_PRINT_DEC, const_x);
198   else
199     {
200       fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC, x.coeffs[0]);
201       for (int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
202         fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, x.coeffs[i]);
203       fprintf (file, "]");
204     }
205 }
206
207 /* Subroutine of print_rtx_operand for handling code '0'.
208    0 indicates a field for internal use that should not be printed.
209    However there are various special cases, such as the third field
210    of a NOTE, where it indicates that the field has several different
211    valid contents.  */
212
213 void
214 rtx_writer::print_rtx_operand_code_0 (const_rtx in_rtx ATTRIBUTE_UNUSED,
215                                       int idx ATTRIBUTE_UNUSED)
216 {
217 #ifndef GENERATOR_FILE
218   if (idx == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
219     {
220       int flags = SYMBOL_REF_FLAGS (in_rtx);
221       if (flags)
222         fprintf (m_outfile, " [flags %#x]", flags);
223       tree decl = SYMBOL_REF_DECL (in_rtx);
224       if (decl)
225         print_node_brief (m_outfile, "", decl, dump_flags);
226     }
227   else if (idx == 3 && NOTE_P (in_rtx))
228     {
229       switch (NOTE_KIND (in_rtx))
230         {
231         case NOTE_INSN_EH_REGION_BEG:
232         case NOTE_INSN_EH_REGION_END:
233           if (flag_dump_unnumbered)
234             fprintf (m_outfile, " #");
235           else
236             fprintf (m_outfile, " %d", NOTE_EH_HANDLER (in_rtx));
237           m_sawclose = 1;
238           break;
239
240         case NOTE_INSN_BLOCK_BEG:
241         case NOTE_INSN_BLOCK_END:
242           dump_addr (m_outfile, " ", NOTE_BLOCK (in_rtx));
243           m_sawclose = 1;
244           break;
245
246         case NOTE_INSN_BASIC_BLOCK:
247           {
248             basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
249             if (bb != 0)
250               fprintf (m_outfile, " [bb %d]", bb->index);
251             break;
252           }
253
254         case NOTE_INSN_DELETED_LABEL:
255         case NOTE_INSN_DELETED_DEBUG_LABEL:
256           {
257             const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
258             if (label)
259               fprintf (m_outfile, " (\"%s\")", label);
260             else
261               fprintf (m_outfile, " \"\"");
262           }
263           break;
264
265         case NOTE_INSN_SWITCH_TEXT_SECTIONS:
266           {
267             basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
268             if (bb != 0)
269               fprintf (m_outfile, " [bb %d]", bb->index);
270             break;
271           }
272
273         case NOTE_INSN_VAR_LOCATION:
274           fputc (' ', m_outfile);
275           print_rtx (NOTE_VAR_LOCATION (in_rtx));
276           break;
277
278         case NOTE_INSN_CFI:
279           fputc ('\n', m_outfile);
280           output_cfi_directive (m_outfile, NOTE_CFI (in_rtx));
281           fputc ('\t', m_outfile);
282           break;
283
284         case NOTE_INSN_BEGIN_STMT:
285         case NOTE_INSN_INLINE_ENTRY:
286 #ifndef GENERATOR_FILE
287           {
288             expanded_location xloc
289               = expand_location (NOTE_MARKER_LOCATION (in_rtx));
290             fprintf (m_outfile, " %s:%i", xloc.file, xloc.line);
291           }
292 #endif
293           break;
294
295         default:
296           break;
297         }
298     }
299   else if (idx == 7 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL
300            && !m_compact)
301     {
302       /* Output the JUMP_LABEL reference.  */
303       fprintf (m_outfile, "\n%s%*s -> ", print_rtx_head, m_indent * 2, "");
304       if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
305         fprintf (m_outfile, "return");
306       else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
307         fprintf (m_outfile, "simple_return");
308       else
309         fprintf (m_outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
310     }
311   else if (idx == 0 && GET_CODE (in_rtx) == VALUE)
312     {
313       cselib_val *val = CSELIB_VAL_PTR (in_rtx);
314
315       fprintf (m_outfile, " %u:%u", val->uid, val->hash);
316       dump_addr (m_outfile, " @", in_rtx);
317       dump_addr (m_outfile, "/", (void*)val);
318     }
319   else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
320     {
321       fprintf (m_outfile, " D#%i",
322                DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
323     }
324   else if (idx == 0 && GET_CODE (in_rtx) == ENTRY_VALUE)
325     {
326       m_indent += 2;
327       if (!m_sawclose)
328         fprintf (m_outfile, " ");
329       print_rtx (ENTRY_VALUE_EXP (in_rtx));
330       m_indent -= 2;
331     }
332 #endif
333 }
334
335 /* Subroutine of print_rtx_operand for handling code 'e'.
336    Also called by print_rtx_operand_code_u for handling code 'u'
337    for LABEL_REFs when they don't reference a CODE_LABEL.  */
338
339 void
340 rtx_writer::print_rtx_operand_code_e (const_rtx in_rtx, int idx)
341 {
342   m_indent += 2;
343   if (idx == 6 && INSN_P (in_rtx))
344     /* Put REG_NOTES on their own line.  */
345     fprintf (m_outfile, "\n%s%*s",
346              print_rtx_head, m_indent * 2, "");
347   if (!m_sawclose)
348     fprintf (m_outfile, " ");
349   if (idx == 7 && CALL_P (in_rtx))
350     {
351       m_in_call_function_usage = true;
352       print_rtx (XEXP (in_rtx, idx));
353       m_in_call_function_usage = false;
354     }
355   else
356     print_rtx (XEXP (in_rtx, idx));
357   m_indent -= 2;
358 }
359
360 /* Subroutine of print_rtx_operand for handling codes 'E' and 'V'.  */
361
362 void
363 rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx)
364 {
365   m_indent += 2;
366   if (m_sawclose)
367     {
368       fprintf (m_outfile, "\n%s%*s",
369       print_rtx_head, m_indent * 2, "");
370       m_sawclose = 0;
371     }
372   fputs (" [", m_outfile);
373   if (XVEC (in_rtx, idx) != NULL)
374     {
375       m_indent += 2;
376       if (XVECLEN (in_rtx, idx))
377         m_sawclose = 1;
378
379       for (int j = 0; j < XVECLEN (in_rtx, idx); j++)
380         {
381           int j1;
382
383           print_rtx (XVECEXP (in_rtx, idx, j));
384           for (j1 = j + 1; j1 < XVECLEN (in_rtx, idx); j1++)
385             if (XVECEXP (in_rtx, idx, j) != XVECEXP (in_rtx, idx, j1))
386               break;
387
388           if (j1 != j + 1)
389             {
390               fprintf (m_outfile, " repeated x%i", j1 - j);
391               j = j1 - 1;
392             }
393         }
394
395       m_indent -= 2;
396     }
397   if (m_sawclose)
398     fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, "");
399
400   fputs ("]", m_outfile);
401   m_sawclose = 1;
402   m_indent -= 2;
403 }
404
405 /* Subroutine of print_rtx_operand for handling code 'i'.  */
406
407 void
408 rtx_writer::print_rtx_operand_code_i (const_rtx in_rtx, int idx)
409 {
410   if (idx == 4 && INSN_P (in_rtx))
411     {
412 #ifndef GENERATOR_FILE
413       const rtx_insn *in_insn = as_a <const rtx_insn *> (in_rtx);
414
415       /*  Pretty-print insn locations.  Ignore scoping as it is mostly
416           redundant with line number information and do not print anything
417           when there is no location information available.  */
418       if (INSN_HAS_LOCATION (in_insn))
419         {
420           expanded_location xloc = insn_location (in_insn);
421           fprintf (m_outfile, " \"%s\":%i:%i", xloc.file, xloc.line,
422                    xloc.column);
423         }
424 #endif
425     }
426   else if (idx == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
427     {
428 #ifndef GENERATOR_FILE
429       if (ASM_OPERANDS_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
430         fprintf (m_outfile, " %s:%i",
431                  LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
432                  LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
433 #endif
434     }
435   else if (idx == 1 && GET_CODE (in_rtx) == ASM_INPUT)
436     {
437 #ifndef GENERATOR_FILE
438       if (ASM_INPUT_SOURCE_LOCATION (in_rtx) != UNKNOWN_LOCATION)
439         fprintf (m_outfile, " %s:%i",
440                  LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
441                  LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
442 #endif
443     }
444   else if (idx == 5 && NOTE_P (in_rtx))
445     {
446       /* This field is only used for NOTE_INSN_DELETED_LABEL, and
447          other times often contains garbage from INSN->NOTE death.  */
448       if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL
449           || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL)
450         fprintf (m_outfile, " %d",  XINT (in_rtx, idx));
451     }
452 #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
453   else if (idx == 1
454            && GET_CODE (in_rtx) == UNSPEC_VOLATILE
455            && XINT (in_rtx, 1) >= 0
456            && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES)
457     fprintf (m_outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]);
458 #endif
459 #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
460   else if (idx == 1
461            && (GET_CODE (in_rtx) == UNSPEC
462                || GET_CODE (in_rtx) == UNSPEC_VOLATILE)
463            && XINT (in_rtx, 1) >= 0
464            && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES)
465     fprintf (m_outfile, " %s", unspec_strings[XINT (in_rtx, 1)]);
466 #endif
467   else
468     {
469       int value = XINT (in_rtx, idx);
470       const char *name;
471       int is_insn = INSN_P (in_rtx);
472
473       /* Don't print INSN_CODEs in compact mode.  */
474       if (m_compact && is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx))
475         {
476           m_sawclose = 0;
477           return;
478         }
479
480       if (flag_dump_unnumbered
481           && (is_insn || NOTE_P (in_rtx)))
482         fputc ('#', m_outfile);
483       else
484         fprintf (m_outfile, " %d", value);
485
486       if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, idx)
487           && XINT (in_rtx, idx) >= 0
488           && (name = get_insn_name (XINT (in_rtx, idx))) != NULL)
489         fprintf (m_outfile, " {%s}", name);
490       m_sawclose = 0;
491     }
492 }
493
494 /* Subroutine of print_rtx_operand for handling code 'r'.  */
495
496 void
497 rtx_writer::print_rtx_operand_code_r (const_rtx in_rtx)
498 {
499   int is_insn = INSN_P (in_rtx);
500   unsigned int regno = REGNO (in_rtx);
501
502 #ifndef GENERATOR_FILE
503   /* For hard registers and virtuals, always print the
504      regno, except in compact mode.  */
505   if (regno <= LAST_VIRTUAL_REGISTER && !m_compact)
506     fprintf (m_outfile, " %d", regno);
507   if (regno < FIRST_PSEUDO_REGISTER)
508     fprintf (m_outfile, " %s", reg_names[regno]);
509   else if (regno <= LAST_VIRTUAL_REGISTER)
510     {
511       if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
512         fprintf (m_outfile, " virtual-incoming-args");
513       else if (regno == VIRTUAL_STACK_VARS_REGNUM)
514         fprintf (m_outfile, " virtual-stack-vars");
515       else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
516         fprintf (m_outfile, " virtual-stack-dynamic");
517       else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
518         fprintf (m_outfile, " virtual-outgoing-args");
519       else if (regno == VIRTUAL_CFA_REGNUM)
520         fprintf (m_outfile, " virtual-cfa");
521       else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
522         fprintf (m_outfile, " virtual-preferred-stack-boundary");
523       else
524         fprintf (m_outfile, " virtual-reg-%d", regno-FIRST_VIRTUAL_REGISTER);
525     }
526   else
527 #endif
528     if (flag_dump_unnumbered && is_insn)
529       fputc ('#', m_outfile);
530     else if (m_compact)
531       {
532         /* In compact mode, print pseudos with '< and '>' wrapping the regno,
533            offseting it by (LAST_VIRTUAL_REGISTER + 1), so that the
534            first non-virtual pseudo is dumped as "<0>".  */
535         gcc_assert (regno > LAST_VIRTUAL_REGISTER);
536         fprintf (m_outfile, " <%d>", regno - (LAST_VIRTUAL_REGISTER + 1));
537       }
538     else
539       fprintf (m_outfile, " %d", regno);
540
541 #ifndef GENERATOR_FILE
542   if (REG_ATTRS (in_rtx))
543     {
544       fputs (" [", m_outfile);
545       if (regno != ORIGINAL_REGNO (in_rtx))
546         fprintf (m_outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
547       if (REG_EXPR (in_rtx))
548         print_mem_expr (m_outfile, REG_EXPR (in_rtx));
549
550       if (maybe_ne (REG_OFFSET (in_rtx), 0))
551         {
552           fprintf (m_outfile, "+");
553           print_poly_int (m_outfile, REG_OFFSET (in_rtx));
554         }
555       fputs (" ]", m_outfile);
556     }
557   if (regno != ORIGINAL_REGNO (in_rtx))
558     fprintf (m_outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
559 #endif
560 }
561
562 /* Subroutine of print_rtx_operand for handling code 'u'.  */
563
564 void
565 rtx_writer::print_rtx_operand_code_u (const_rtx in_rtx, int idx)
566 {
567   /* Don't print insn UIDs for PREV/NEXT_INSN in compact mode.  */
568   if (m_compact && INSN_CHAIN_CODE_P (GET_CODE (in_rtx)) && idx < 2)
569     return;
570
571   if (XEXP (in_rtx, idx) != NULL)
572     {
573       rtx sub = XEXP (in_rtx, idx);
574       enum rtx_code subc = GET_CODE (sub);
575
576       if (GET_CODE (in_rtx) == LABEL_REF)
577         {
578           if (subc == NOTE
579               && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL)
580             {
581               if (flag_dump_unnumbered)
582                 fprintf (m_outfile, " [# deleted]");
583               else
584                 fprintf (m_outfile, " [%d deleted]", INSN_UID (sub));
585               m_sawclose = 0;
586               return;
587             }
588
589           if (subc != CODE_LABEL)
590             {
591               print_rtx_operand_code_e (in_rtx, idx);
592               return;
593             }
594         }
595
596       if (flag_dump_unnumbered
597           || (flag_dump_unnumbered_links && idx <= 1
598               && (INSN_P (in_rtx) || NOTE_P (in_rtx)
599                   || LABEL_P (in_rtx) || BARRIER_P (in_rtx))))
600         fputs (" #", m_outfile);
601       else
602         fprintf (m_outfile, " %d", INSN_UID (sub));
603     }
604   else
605     fputs (" 0", m_outfile);
606   m_sawclose = 0;
607 }
608
609 /* Subroutine of print_rtx.   Print operand IDX of IN_RTX.  */
610
611 void
612 rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
613 {
614   const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
615
616   switch (format_ptr[idx])
617     {
618       const char *str;
619
620     case 'T':
621       str = XTMPL (in_rtx, idx);
622       goto string;
623
624     case 'S':
625     case 's':
626       str = XSTR (in_rtx, idx);
627     string:
628
629       if (str == 0)
630         fputs (" (nil)", m_outfile);
631       else
632         fprintf (m_outfile, " (\"%s\")", str);
633       m_sawclose = 1;
634       break;
635
636     case '0':
637       print_rtx_operand_code_0 (in_rtx, idx);
638       break;
639
640     case 'e':
641       print_rtx_operand_code_e (in_rtx, idx);
642       break;
643
644     case 'E':
645     case 'V':
646       print_rtx_operand_codes_E_and_V (in_rtx, idx);
647       break;
648
649     case 'w':
650       if (! m_simple)
651         fprintf (m_outfile, " ");
652       fprintf (m_outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, idx));
653       if (! m_simple && !m_compact)
654         fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
655                  (unsigned HOST_WIDE_INT) XWINT (in_rtx, idx));
656       break;
657
658     case 'i':
659       print_rtx_operand_code_i (in_rtx, idx);
660       break;
661
662     case 'p':
663       fprintf (m_outfile, " ");
664       print_poly_int (m_outfile, SUBREG_BYTE (in_rtx));
665       break;
666
667     case 'r':
668       print_rtx_operand_code_r (in_rtx);
669       break;
670
671     /* Print NOTE_INSN names rather than integer codes.  */
672
673     case 'n':
674       fprintf (m_outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, idx)));
675       m_sawclose = 0;
676       break;
677
678     case 'u':
679       print_rtx_operand_code_u (in_rtx, idx);
680       break;
681
682     case 't':
683 #ifndef GENERATOR_FILE
684       if (idx == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
685         print_mem_expr (m_outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
686       else if (idx == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF)
687         print_mem_expr (m_outfile, DEBUG_PARAMETER_REF_DECL (in_rtx));
688       else
689         dump_addr (m_outfile, " ", XTREE (in_rtx, idx));
690 #endif
691       break;
692
693     case '*':
694       fputs (" Unknown", m_outfile);
695       m_sawclose = 0;
696       break;
697
698     case 'B':
699       /* Don't print basic block ids in compact mode.  */
700       if (m_compact)
701         break;
702 #ifndef GENERATOR_FILE
703       if (XBBDEF (in_rtx, idx))
704         fprintf (m_outfile, " %i", XBBDEF (in_rtx, idx)->index);
705 #endif
706       break;
707
708     default:
709       gcc_unreachable ();
710     }
711 }
712
713 /* Subroutine of rtx_writer::print_rtx.
714    In compact mode, determine if operand IDX of IN_RTX is interesting
715    to dump, or (if in a trailing position) it can be omitted.  */
716
717 bool
718 rtx_writer::operand_has_default_value_p (const_rtx in_rtx, int idx)
719 {
720   const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
721
722   switch (format_ptr[idx])
723     {
724     case 'e':
725     case 'u':
726       return XEXP (in_rtx, idx) == NULL_RTX;
727
728     case 's':
729       return XSTR (in_rtx, idx) == NULL;
730
731     case '0':
732       switch (GET_CODE (in_rtx))
733         {
734         case JUMP_INSN:
735           /* JUMP_LABELs are always omitted in compact mode, so treat
736              any value here as omittable, so that earlier operands can
737              potentially be omitted also.  */
738           return m_compact;
739
740         default:
741           return false;
742
743         }
744
745     default:
746       return false;
747     }
748 }
749
750 /* Print IN_RTX onto m_outfile.  This is the recursive part of printing.  */
751
752 void
753 rtx_writer::print_rtx (const_rtx in_rtx)
754 {
755   int idx = 0;
756
757   if (m_sawclose)
758     {
759       if (m_simple)
760         fputc (' ', m_outfile);
761       else
762         fprintf (m_outfile, "\n%s%*s", print_rtx_head, m_indent * 2, "");
763       m_sawclose = 0;
764     }
765
766   if (in_rtx == 0)
767     {
768       fputs ("(nil)", m_outfile);
769       m_sawclose = 1;
770       return;
771     }
772   else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
773     {
774        fprintf (m_outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx),
775                 print_rtx_head, m_indent * 2, "");
776        m_sawclose = 1;
777        return;
778     }
779
780   fputc ('(', m_outfile);
781
782   /* Print name of expression code.  */
783
784   /* Handle reuse.  */
785 #ifndef GENERATOR_FILE
786   if (m_rtx_reuse_manager)
787     {
788       int reuse_id;
789       if (m_rtx_reuse_manager->has_reuse_id (in_rtx, &reuse_id))
790         {
791           /* Have we already seen the defn of this rtx?  */
792           if (m_rtx_reuse_manager->seen_def_p (reuse_id))
793             {
794               fprintf (m_outfile, "reuse_rtx %i)", reuse_id);
795               m_sawclose = 1;
796               return;
797             }
798           else
799             {
800               /* First time we've seen this reused-rtx.  */
801               fprintf (m_outfile, "%i|", reuse_id);
802               m_rtx_reuse_manager->set_seen_def (reuse_id);
803             }
804         }
805     }
806 #endif /* #ifndef GENERATOR_FILE */
807
808   /* In compact mode, prefix the code of insns with "c",
809      giving "cinsn", "cnote" etc.  */
810   if (m_compact && is_a <const rtx_insn *, const struct rtx_def> (in_rtx))
811     {
812       /* "ccode_label" is slightly awkward, so special-case it as
813          just "clabel".  */
814       rtx_code code = GET_CODE (in_rtx);
815       if (code == CODE_LABEL)
816         fprintf (m_outfile, "clabel");
817       else
818         fprintf (m_outfile, "c%s", GET_RTX_NAME (code));
819     }
820   else if (m_simple && CONST_INT_P (in_rtx))
821     ; /* no code.  */
822   else
823     fprintf (m_outfile, "%s", GET_RTX_NAME (GET_CODE (in_rtx)));
824
825   if (! m_simple)
826     {
827       if (RTX_FLAG (in_rtx, in_struct))
828         fputs ("/s", m_outfile);
829
830       if (RTX_FLAG (in_rtx, volatil))
831         fputs ("/v", m_outfile);
832
833       if (RTX_FLAG (in_rtx, unchanging))
834         fputs ("/u", m_outfile);
835
836       if (RTX_FLAG (in_rtx, frame_related))
837         fputs ("/f", m_outfile);
838
839       if (RTX_FLAG (in_rtx, jump))
840         fputs ("/j", m_outfile);
841
842       if (RTX_FLAG (in_rtx, call))
843         fputs ("/c", m_outfile);
844
845       if (RTX_FLAG (in_rtx, return_val))
846         fputs ("/i", m_outfile);
847
848       /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
849       if ((GET_CODE (in_rtx) == EXPR_LIST
850            || GET_CODE (in_rtx) == INSN_LIST
851            || GET_CODE (in_rtx) == INT_LIST)
852           && (int)GET_MODE (in_rtx) < REG_NOTE_MAX
853           && !m_in_call_function_usage)
854         fprintf (m_outfile, ":%s",
855                  GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
856
857       /* For other rtl, print the mode if it's not VOID.  */
858       else if (GET_MODE (in_rtx) != VOIDmode)
859         fprintf (m_outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
860
861 #ifndef GENERATOR_FILE
862       if (GET_CODE (in_rtx) == VAR_LOCATION)
863         {
864           if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
865             fputs (" <debug string placeholder>", m_outfile);
866           else
867             print_mem_expr (m_outfile, PAT_VAR_LOCATION_DECL (in_rtx));
868           fputc (' ', m_outfile);
869           print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
870           if (PAT_VAR_LOCATION_STATUS (in_rtx)
871               == VAR_INIT_STATUS_UNINITIALIZED)
872             fprintf (m_outfile, " [uninit]");
873           m_sawclose = 1;
874           idx = GET_RTX_LENGTH (VAR_LOCATION);
875         }
876 #endif
877     }
878
879 #ifndef GENERATOR_FILE
880   if (CONST_DOUBLE_AS_FLOAT_P (in_rtx))
881     idx = 5;
882 #endif
883
884   /* For insns, print the INSN_UID.  */
885   if (INSN_CHAIN_CODE_P (GET_CODE (in_rtx)))
886     {
887       if (flag_dump_unnumbered)
888         fprintf (m_outfile, " #");
889       else
890         fprintf (m_outfile, " %d", INSN_UID (in_rtx));
891     }
892
893   /* Determine which is the final operand to print.
894      In compact mode, skip trailing operands that have the default values
895      e.g. trailing "(nil)" values.  */
896   int limit = GET_RTX_LENGTH (GET_CODE (in_rtx));
897   if (m_compact)
898     while (limit > idx && operand_has_default_value_p (in_rtx, limit - 1))
899       limit--;
900
901   /* Get the format string and skip the first elements if we have handled
902      them already.  */
903
904   for (; idx < limit; idx++)
905     print_rtx_operand (in_rtx, idx);
906
907   switch (GET_CODE (in_rtx))
908     {
909 #ifndef GENERATOR_FILE
910     case MEM:
911       if (__builtin_expect (final_insns_dump_p, false))
912         fprintf (m_outfile, " [");
913       else
914         fprintf (m_outfile, " [" HOST_WIDE_INT_PRINT_DEC,
915                  (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx));
916
917       if (MEM_EXPR (in_rtx))
918         print_mem_expr (m_outfile, MEM_EXPR (in_rtx));
919       else
920         fputc (' ', m_outfile);
921
922       if (MEM_OFFSET_KNOWN_P (in_rtx))
923         {
924           fprintf (m_outfile, "+");
925           print_poly_int (m_outfile, MEM_OFFSET (in_rtx));
926         }
927
928       if (MEM_SIZE_KNOWN_P (in_rtx))
929         {
930           fprintf (m_outfile, " S");
931           print_poly_int (m_outfile, MEM_SIZE (in_rtx));
932         }
933
934       if (MEM_ALIGN (in_rtx) != 1)
935         fprintf (m_outfile, " A%u", MEM_ALIGN (in_rtx));
936
937       if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx)))
938         fprintf (m_outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));
939
940       fputc (']', m_outfile);
941       break;
942
943     case CONST_DOUBLE:
944       if (FLOAT_MODE_P (GET_MODE (in_rtx)))
945         {
946           char s[60];
947
948           real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
949                            sizeof (s), 0, 1);
950           fprintf (m_outfile, " %s", s);
951
952           real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
953                                sizeof (s), 0, 1);
954           fprintf (m_outfile, " [%s]", s);
955         }
956       break;
957
958     case CONST_WIDE_INT:
959       fprintf (m_outfile, " ");
960       cwi_output_hex (m_outfile, in_rtx);
961       break;
962
963     case CONST_POLY_INT:
964       fprintf (m_outfile, " [");
965       print_dec (CONST_POLY_INT_COEFFS (in_rtx)[0], m_outfile, SIGNED);
966       for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
967         {
968           fprintf (m_outfile, ", ");
969           print_dec (CONST_POLY_INT_COEFFS (in_rtx)[i], m_outfile, SIGNED);
970         }
971       fprintf (m_outfile, "]");
972       break;
973 #endif
974
975     case CODE_LABEL:
976       if (!m_compact)
977         fprintf (m_outfile, " [%d uses]", LABEL_NUSES (in_rtx));
978       switch (LABEL_KIND (in_rtx))
979         {
980           case LABEL_NORMAL: break;
981           case LABEL_STATIC_ENTRY: fputs (" [entry]", m_outfile); break;
982           case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", m_outfile); break;
983           case LABEL_WEAK_ENTRY: fputs (" [weak entry]", m_outfile); break;
984           default: gcc_unreachable ();
985         }
986       break;
987
988     default:
989       break;
990     }
991
992   fputc (')', m_outfile);
993   m_sawclose = 1;
994 }
995
996 /* Emit a closing parenthesis and newline.  */
997
998 void
999 rtx_writer::finish_directive ()
1000 {
1001   fprintf (m_outfile, ")\n");
1002   m_sawclose = 0;
1003 }
1004
1005 /* Print an rtx on the current line of FILE.  Initially indent IND
1006    characters.  */
1007
1008 void
1009 print_inline_rtx (FILE *outf, const_rtx x, int ind)
1010 {
1011   rtx_writer w (outf, ind, false, false, NULL);
1012   w.print_rtx (x);
1013 }
1014
1015 /* Call this function from the debugger to see what X looks like.  */
1016
1017 DEBUG_FUNCTION void
1018 debug_rtx (const_rtx x)
1019 {
1020   rtx_writer w (stderr, 0, false, false, NULL);
1021   w.print_rtx (x);
1022   fprintf (stderr, "\n");
1023 }
1024
1025 /* Dump rtx REF.  */
1026
1027 DEBUG_FUNCTION void
1028 debug (const rtx_def &ref)
1029 {
1030   debug_rtx (&ref);
1031 }
1032
1033 DEBUG_FUNCTION void
1034 debug (const rtx_def *ptr)
1035 {
1036   if (ptr)
1037     debug (*ptr);
1038   else
1039     fprintf (stderr, "<nil>\n");
1040 }
1041
1042 /* Like debug_rtx but with no newline, as debug_helper will add one.
1043
1044    Note: No debug_slim(rtx_insn *) variant implemented, as this
1045    function can serve for both rtx and rtx_insn.  */
1046
1047 static void
1048 debug_slim (const_rtx x)
1049 {
1050   rtx_writer w (stderr, 0, false, false, NULL);
1051   w.print_rtx (x);
1052 }
1053
1054 DEFINE_DEBUG_VEC (rtx_def *)
1055 DEFINE_DEBUG_VEC (rtx_insn *)
1056 DEFINE_DEBUG_HASH_SET (rtx_def *)
1057 DEFINE_DEBUG_HASH_SET (rtx_insn *)
1058
1059 /* Count of rtx's to print with debug_rtx_list.
1060    This global exists because gdb user defined commands have no arguments.  */
1061
1062 DEBUG_VARIABLE int debug_rtx_count = 0; /* 0 is treated as equivalent to 1 */
1063
1064 /* Call this function to print list from X on.
1065
1066    N is a count of the rtx's to print. Positive values print from the specified
1067    rtx_insn on.  Negative values print a window around the rtx_insn.
1068    EG: -5 prints 2 rtx_insn's on either side (in addition to the specified
1069    rtx_insn).  */
1070
1071 DEBUG_FUNCTION void
1072 debug_rtx_list (const rtx_insn *x, int n)
1073 {
1074   int i,count;
1075   const rtx_insn *insn;
1076
1077   count = n == 0 ? 1 : n < 0 ? -n : n;
1078
1079   /* If we are printing a window, back up to the start.  */
1080
1081   if (n < 0)
1082     for (i = count / 2; i > 0; i--)
1083       {
1084         if (PREV_INSN (x) == 0)
1085           break;
1086         x = PREV_INSN (x);
1087       }
1088
1089   for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
1090     {
1091       debug_rtx (insn);
1092       fprintf (stderr, "\n");
1093     }
1094 }
1095
1096 /* Call this function to print an rtx_insn list from START to END
1097    inclusive.  */
1098
1099 DEBUG_FUNCTION void
1100 debug_rtx_range (const rtx_insn *start, const rtx_insn *end)
1101 {
1102   while (1)
1103     {
1104       debug_rtx (start);
1105       fprintf (stderr, "\n");
1106       if (!start || start == end)
1107         break;
1108       start = NEXT_INSN (start);
1109     }
1110 }
1111
1112 /* Call this function to search an rtx_insn list to find one with insn uid UID,
1113    and then call debug_rtx_list to print it, using DEBUG_RTX_COUNT.
1114    The found insn is returned to enable further debugging analysis.  */
1115
1116 DEBUG_FUNCTION const rtx_insn *
1117 debug_rtx_find (const rtx_insn *x, int uid)
1118 {
1119   while (x != 0 && INSN_UID (x) != uid)
1120     x = NEXT_INSN (x);
1121   if (x != 0)
1122     {
1123       debug_rtx_list (x, debug_rtx_count);
1124       return x;
1125     }
1126   else
1127     {
1128       fprintf (stderr, "insn uid %d not found\n", uid);
1129       return 0;
1130     }
1131 }
1132
1133 /* External entry point for printing a chain of insns
1134    starting with RTX_FIRST.
1135    A blank line separates insns.
1136
1137    If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
1138
1139 void
1140 rtx_writer::print_rtl (const_rtx rtx_first)
1141 {
1142   const rtx_insn *tmp_rtx;
1143
1144   if (rtx_first == 0)
1145     {
1146       fputs (print_rtx_head, m_outfile);
1147       fputs ("(nil)\n", m_outfile);
1148     }
1149   else
1150     switch (GET_CODE (rtx_first))
1151       {
1152       case INSN:
1153       case JUMP_INSN:
1154       case CALL_INSN:
1155       case NOTE:
1156       case CODE_LABEL:
1157       case JUMP_TABLE_DATA:
1158       case BARRIER:
1159         for (tmp_rtx = as_a <const rtx_insn *> (rtx_first);
1160              tmp_rtx != 0;
1161              tmp_rtx = NEXT_INSN (tmp_rtx))
1162           {
1163             fputs (print_rtx_head, m_outfile);
1164             print_rtx (tmp_rtx);
1165             fprintf (m_outfile, "\n");
1166           }
1167         break;
1168
1169       default:
1170         fputs (print_rtx_head, m_outfile);
1171         print_rtx (rtx_first);
1172       }
1173 }
1174
1175 /* External entry point for printing a chain of insns
1176    starting with RTX_FIRST onto file OUTF.
1177    A blank line separates insns.
1178
1179    If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
1180
1181 void
1182 print_rtl (FILE *outf, const_rtx rtx_first)
1183 {
1184   rtx_writer w (outf, 0, false, false, NULL);
1185   w.print_rtl (rtx_first);
1186 }
1187
1188 /* Like print_rtx, except specify a file.  */
1189 /* Return nonzero if we actually printed anything.  */
1190
1191 int
1192 print_rtl_single (FILE *outf, const_rtx x)
1193 {
1194   rtx_writer w (outf, 0, false, false, NULL);
1195   return w.print_rtl_single_with_indent (x, 0);
1196 }
1197
1198 /* Like print_rtl_single, except specify an indentation.  */
1199
1200 int
1201 rtx_writer::print_rtl_single_with_indent (const_rtx x, int ind)
1202 {
1203   char *s_indent = (char *) alloca ((size_t) ind + 1);
1204   memset ((void *) s_indent, ' ', (size_t) ind);
1205   s_indent[ind] = '\0';
1206   fputs (s_indent, m_outfile);
1207   fputs (print_rtx_head, m_outfile);
1208
1209   int old_indent = m_indent;
1210   m_indent = ind;
1211   m_sawclose = 0;
1212   print_rtx (x);
1213   putc ('\n', m_outfile);
1214   m_indent = old_indent;
1215   return 1;
1216 }
1217
1218
1219 /* Like print_rtl except without all the detail; for example,
1220    if RTX is a CONST_INT then print in decimal format.  */
1221
1222 void
1223 print_simple_rtl (FILE *outf, const_rtx x)
1224 {
1225   rtx_writer w (outf, 0, true, false, NULL);
1226   w.print_rtl (x);
1227 }
1228
1229 /* Print the elements of VEC to FILE.  */
1230
1231 void
1232 print_rtx_insn_vec (FILE *file, const vec<rtx_insn *> &vec)
1233 {
1234   fputc('{', file);
1235
1236   unsigned int len = vec.length ();
1237   for (unsigned int i = 0; i < len; i++)
1238     {
1239       print_rtl (file, vec[i]);
1240       if (i < len - 1)
1241         fputs (", ", file);
1242     }
1243
1244   fputc ('}', file);
1245 }
1246
1247 #ifndef GENERATOR_FILE
1248 /* The functions below  try to print RTL in a form resembling assembler
1249    mnemonics.  Because this form is more concise than the "traditional" form
1250    of RTL printing in Lisp-style, the form printed by this file is called
1251    "slim".  RTL dumps in slim format can be obtained by appending the "-slim"
1252    option to -fdump-rtl-<pass>.  Control flow graph output as a DOT file is
1253    always printed in slim form.
1254
1255    The normal interface to the functionality provided in this pretty-printer
1256    is through the dump_*_slim functions to print to a stream, or via the
1257    print_*_slim functions to print into a user's pretty-printer.
1258
1259    It is also possible to obtain a string for a single pattern as a string
1260    pointer, via str_pattern_slim, but this usage is discouraged.  */
1261
1262 /* For insns we print patterns, and for some patterns we print insns...  */
1263 static void print_insn_with_notes (pretty_printer *, const rtx_insn *);
1264
1265 /* This recognizes rtx'en classified as expressions.  These are always
1266    represent some action on values or results of other expression, that
1267    may be stored in objects representing values.  */
1268
1269 static void
1270 print_exp (pretty_printer *pp, const_rtx x, int verbose)
1271 {
1272   const char *st[4];
1273   const char *fun;
1274   rtx op[4];
1275   int i;
1276
1277   fun = (char *) 0;
1278   for (i = 0; i < 4; i++)
1279     {
1280       st[i] = (char *) 0;
1281       op[i] = NULL_RTX;
1282     }
1283
1284   switch (GET_CODE (x))
1285     {
1286     case PLUS:
1287       op[0] = XEXP (x, 0);
1288       if (CONST_INT_P (XEXP (x, 1))
1289           && INTVAL (XEXP (x, 1)) < 0)
1290         {
1291           st[1] = "-";
1292           op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
1293         }
1294       else
1295         {
1296           st[1] = "+";
1297           op[1] = XEXP (x, 1);
1298         }
1299       break;
1300     case LO_SUM:
1301       op[0] = XEXP (x, 0);
1302       st[1] = "+low(";
1303       op[1] = XEXP (x, 1);
1304       st[2] = ")";
1305       break;
1306     case MINUS:
1307       op[0] = XEXP (x, 0);
1308       st[1] = "-";
1309       op[1] = XEXP (x, 1);
1310       break;
1311     case COMPARE:
1312       fun = "cmp";
1313       op[0] = XEXP (x, 0);
1314       op[1] = XEXP (x, 1);
1315       break;
1316     case NEG:
1317       st[0] = "-";
1318       op[0] = XEXP (x, 0);
1319       break;
1320     case FMA:
1321       st[0] = "{";
1322       op[0] = XEXP (x, 0);
1323       st[1] = "*";
1324       op[1] = XEXP (x, 1);
1325       st[2] = "+";
1326       op[2] = XEXP (x, 2);
1327       st[3] = "}";
1328       break;
1329     case MULT:
1330       op[0] = XEXP (x, 0);
1331       st[1] = "*";
1332       op[1] = XEXP (x, 1);
1333       break;
1334     case DIV:
1335       op[0] = XEXP (x, 0);
1336       st[1] = "/";
1337       op[1] = XEXP (x, 1);
1338       break;
1339     case UDIV:
1340       fun = "udiv";
1341       op[0] = XEXP (x, 0);
1342       op[1] = XEXP (x, 1);
1343       break;
1344     case MOD:
1345       op[0] = XEXP (x, 0);
1346       st[1] = "%";
1347       op[1] = XEXP (x, 1);
1348       break;
1349     case UMOD:
1350       fun = "umod";
1351       op[0] = XEXP (x, 0);
1352       op[1] = XEXP (x, 1);
1353       break;
1354     case SMIN:
1355       fun = "smin";
1356       op[0] = XEXP (x, 0);
1357       op[1] = XEXP (x, 1);
1358       break;
1359     case SMAX:
1360       fun = "smax";
1361       op[0] = XEXP (x, 0);
1362       op[1] = XEXP (x, 1);
1363       break;
1364     case UMIN:
1365       fun = "umin";
1366       op[0] = XEXP (x, 0);
1367       op[1] = XEXP (x, 1);
1368       break;
1369     case UMAX:
1370       fun = "umax";
1371       op[0] = XEXP (x, 0);
1372       op[1] = XEXP (x, 1);
1373       break;
1374     case NOT:
1375       st[0] = "~";
1376       op[0] = XEXP (x, 0);
1377       break;
1378     case AND:
1379       op[0] = XEXP (x, 0);
1380       st[1] = "&";
1381       op[1] = XEXP (x, 1);
1382       break;
1383     case IOR:
1384       op[0] = XEXP (x, 0);
1385       st[1] = "|";
1386       op[1] = XEXP (x, 1);
1387       break;
1388     case XOR:
1389       op[0] = XEXP (x, 0);
1390       st[1] = "^";
1391       op[1] = XEXP (x, 1);
1392       break;
1393     case ASHIFT:
1394       op[0] = XEXP (x, 0);
1395       st[1] = "<<";
1396       op[1] = XEXP (x, 1);
1397       break;
1398     case LSHIFTRT:
1399       op[0] = XEXP (x, 0);
1400       st[1] = " 0>>";
1401       op[1] = XEXP (x, 1);
1402       break;
1403     case ASHIFTRT:
1404       op[0] = XEXP (x, 0);
1405       st[1] = ">>";
1406       op[1] = XEXP (x, 1);
1407       break;
1408     case ROTATE:
1409       op[0] = XEXP (x, 0);
1410       st[1] = "<-<";
1411       op[1] = XEXP (x, 1);
1412       break;
1413     case ROTATERT:
1414       op[0] = XEXP (x, 0);
1415       st[1] = ">->";
1416       op[1] = XEXP (x, 1);
1417       break;
1418     case NE:
1419       op[0] = XEXP (x, 0);
1420       st[1] = "!=";
1421       op[1] = XEXP (x, 1);
1422       break;
1423     case EQ:
1424       op[0] = XEXP (x, 0);
1425       st[1] = "==";
1426       op[1] = XEXP (x, 1);
1427       break;
1428     case GE:
1429       op[0] = XEXP (x, 0);
1430       st[1] = ">=";
1431       op[1] = XEXP (x, 1);
1432       break;
1433     case GT:
1434       op[0] = XEXP (x, 0);
1435       st[1] = ">";
1436       op[1] = XEXP (x, 1);
1437       break;
1438     case LE:
1439       op[0] = XEXP (x, 0);
1440       st[1] = "<=";
1441       op[1] = XEXP (x, 1);
1442       break;
1443     case LT:
1444       op[0] = XEXP (x, 0);
1445       st[1] = "<";
1446       op[1] = XEXP (x, 1);
1447       break;
1448     case SIGN_EXTRACT:
1449       fun = (verbose) ? "sign_extract" : "sxt";
1450       op[0] = XEXP (x, 0);
1451       op[1] = XEXP (x, 1);
1452       op[2] = XEXP (x, 2);
1453       break;
1454     case ZERO_EXTRACT:
1455       fun = (verbose) ? "zero_extract" : "zxt";
1456       op[0] = XEXP (x, 0);
1457       op[1] = XEXP (x, 1);
1458       op[2] = XEXP (x, 2);
1459       break;
1460     case SIGN_EXTEND:
1461       fun = (verbose) ? "sign_extend" : "sxn";
1462       op[0] = XEXP (x, 0);
1463       break;
1464     case ZERO_EXTEND:
1465       fun = (verbose) ? "zero_extend" : "zxn";
1466       op[0] = XEXP (x, 0);
1467       break;
1468     case FLOAT_EXTEND:
1469       fun = (verbose) ? "float_extend" : "fxn";
1470       op[0] = XEXP (x, 0);
1471       break;
1472     case TRUNCATE:
1473       fun = (verbose) ? "trunc" : "trn";
1474       op[0] = XEXP (x, 0);
1475       break;
1476     case FLOAT_TRUNCATE:
1477       fun = (verbose) ? "float_trunc" : "ftr";
1478       op[0] = XEXP (x, 0);
1479       break;
1480     case FLOAT:
1481       fun = (verbose) ? "float" : "flt";
1482       op[0] = XEXP (x, 0);
1483       break;
1484     case UNSIGNED_FLOAT:
1485       fun = (verbose) ? "uns_float" : "ufl";
1486       op[0] = XEXP (x, 0);
1487       break;
1488     case FIX:
1489       fun = "fix";
1490       op[0] = XEXP (x, 0);
1491       break;
1492     case UNSIGNED_FIX:
1493       fun = (verbose) ? "uns_fix" : "ufx";
1494       op[0] = XEXP (x, 0);
1495       break;
1496     case PRE_DEC:
1497       st[0] = "--";
1498       op[0] = XEXP (x, 0);
1499       break;
1500     case PRE_INC:
1501       st[0] = "++";
1502       op[0] = XEXP (x, 0);
1503       break;
1504     case POST_DEC:
1505       op[0] = XEXP (x, 0);
1506       st[1] = "--";
1507       break;
1508     case POST_INC:
1509       op[0] = XEXP (x, 0);
1510       st[1] = "++";
1511       break;
1512     case PRE_MODIFY:
1513       st[0] = "pre ";
1514       op[0] = XEXP (XEXP (x, 1), 0);
1515       st[1] = "+=";
1516       op[1] = XEXP (XEXP (x, 1), 1);
1517       break;
1518     case POST_MODIFY:
1519       st[0] = "post ";
1520       op[0] = XEXP (XEXP (x, 1), 0);
1521       st[1] = "+=";
1522       op[1] = XEXP (XEXP (x, 1), 1);
1523       break;
1524     case CALL:
1525       st[0] = "call ";
1526       op[0] = XEXP (x, 0);
1527       if (verbose)
1528         {
1529           st[1] = " argc:";
1530           op[1] = XEXP (x, 1);
1531         }
1532       break;
1533     case IF_THEN_ELSE:
1534       st[0] = "{(";
1535       op[0] = XEXP (x, 0);
1536       st[1] = ")?";
1537       op[1] = XEXP (x, 1);
1538       st[2] = ":";
1539       op[2] = XEXP (x, 2);
1540       st[3] = "}";
1541       break;
1542     case TRAP_IF:
1543       fun = "trap_if";
1544       op[0] = TRAP_CONDITION (x);
1545       break;
1546     case PREFETCH:
1547       fun = "prefetch";
1548       op[0] = XEXP (x, 0);
1549       op[1] = XEXP (x, 1);
1550       op[2] = XEXP (x, 2);
1551       break;
1552     case UNSPEC:
1553     case UNSPEC_VOLATILE:
1554       {
1555         pp_string (pp, "unspec");
1556         if (GET_CODE (x) == UNSPEC_VOLATILE)
1557           pp_string (pp, "/v");
1558         pp_left_bracket (pp);
1559         for (i = 0; i < XVECLEN (x, 0); i++)
1560           {
1561             if (i != 0)
1562               pp_comma (pp);
1563             print_pattern (pp, XVECEXP (x, 0, i), verbose);
1564           }
1565         pp_string (pp, "] ");
1566         pp_decimal_int (pp, XINT (x, 1));
1567       }
1568       break;
1569     default:
1570       {
1571         /* Most unhandled codes can be printed as pseudo-functions.  */
1572         if (GET_RTX_CLASS (GET_CODE (x)) == RTX_UNARY)
1573           {
1574             fun = GET_RTX_NAME (GET_CODE (x));
1575             op[0] = XEXP (x, 0);
1576           }
1577         else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_COMPARE
1578                  || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_COMPARE
1579                  || GET_RTX_CLASS (GET_CODE (x)) == RTX_BIN_ARITH
1580                  || GET_RTX_CLASS (GET_CODE (x)) == RTX_COMM_ARITH)
1581           {
1582             fun = GET_RTX_NAME (GET_CODE (x));
1583             op[0] = XEXP (x, 0);
1584             op[1] = XEXP (x, 1);
1585           }
1586         else if (GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
1587           {
1588             fun = GET_RTX_NAME (GET_CODE (x));
1589             op[0] = XEXP (x, 0);
1590             op[1] = XEXP (x, 1);
1591             op[2] = XEXP (x, 2);
1592           }
1593         else
1594           /* Give up, just print the RTX name.  */
1595           st[0] = GET_RTX_NAME (GET_CODE (x));
1596       }
1597       break;
1598     }
1599
1600   /* Print this as a function?  */
1601   if (fun)
1602     {
1603       pp_string (pp, fun);
1604       pp_left_paren (pp);
1605     }
1606
1607   for (i = 0; i < 4; i++)
1608     {
1609       if (st[i])
1610         pp_string (pp, st[i]);
1611
1612       if (op[i])
1613         {
1614           if (fun && i != 0)
1615             pp_comma (pp);
1616           print_value (pp, op[i], verbose);
1617         }
1618     }
1619
1620   if (fun)
1621     pp_right_paren (pp);
1622 }               /* print_exp */
1623
1624 /* Prints rtxes, I customarily classified as values.  They're constants,
1625    registers, labels, symbols and memory accesses.  */
1626
1627 void
1628 print_value (pretty_printer *pp, const_rtx x, int verbose)
1629 {
1630   char tmp[1024];
1631
1632   if (!x)
1633     {
1634       pp_string (pp, "(nil)");
1635       return;
1636     }
1637   switch (GET_CODE (x))
1638     {
1639     case CONST_INT:
1640       pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1641                  (unsigned HOST_WIDE_INT) INTVAL (x));
1642       break;
1643
1644     case CONST_WIDE_INT:
1645       {
1646         const char *sep = "<";
1647         int i;
1648         for (i = CONST_WIDE_INT_NUNITS (x) - 1; i >= 0; i--)
1649           {
1650             pp_string (pp, sep);
1651             sep = ",";
1652             sprintf (tmp, HOST_WIDE_INT_PRINT_HEX,
1653                      (unsigned HOST_WIDE_INT) CONST_WIDE_INT_ELT (x, i));
1654             pp_string (pp, tmp);
1655           }
1656         pp_greater (pp);
1657       }
1658       break;
1659
1660     case CONST_POLY_INT:
1661       pp_left_bracket (pp);
1662       pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[0], SIGNED);
1663       for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
1664         {
1665           pp_string (pp, ", ");
1666           pp_wide_int (pp, CONST_POLY_INT_COEFFS (x)[i], SIGNED);
1667         }
1668       pp_right_bracket (pp);
1669       break;
1670
1671     case CONST_DOUBLE:
1672       if (FLOAT_MODE_P (GET_MODE (x)))
1673         {
1674           real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x),
1675                            sizeof (tmp), 0, 1);
1676           pp_string (pp, tmp);
1677         }
1678       else
1679         pp_printf (pp, "<%wx,%wx>",
1680                    (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
1681                    (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
1682       break;
1683     case CONST_FIXED:
1684       fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp));
1685       pp_string (pp, tmp);
1686       break;
1687     case CONST_STRING:
1688       pp_printf (pp, "\"%s\"", XSTR (x, 0));
1689       break;
1690     case SYMBOL_REF:
1691       pp_printf (pp, "`%s'", XSTR (x, 0));
1692       break;
1693     case LABEL_REF:
1694       pp_printf (pp, "L%d", INSN_UID (label_ref_label (x)));
1695       break;
1696     case CONST:
1697     case HIGH:
1698     case STRICT_LOW_PART:
1699       pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x)));
1700       print_value (pp, XEXP (x, 0), verbose);
1701       pp_right_paren (pp);
1702       break;
1703     case REG:
1704       if (REGNO (x) < FIRST_PSEUDO_REGISTER)
1705         {
1706           if (ISDIGIT (reg_names[REGNO (x)][0]))
1707             pp_modulo (pp);
1708           pp_string (pp, reg_names[REGNO (x)]);
1709         }
1710       else
1711         pp_printf (pp, "r%d", REGNO (x));
1712       if (verbose)
1713         pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x)));
1714       break;
1715     case SUBREG:
1716       print_value (pp, SUBREG_REG (x), verbose);
1717       pp_printf (pp, "#");
1718       pp_wide_integer (pp, SUBREG_BYTE (x));
1719       break;
1720     case SCRATCH:
1721     case CC0:
1722     case PC:
1723       pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1724       break;
1725     case MEM:
1726       pp_left_bracket (pp);
1727       print_value (pp, XEXP (x, 0), verbose);
1728       pp_right_bracket (pp);
1729       break;
1730     case DEBUG_EXPR:
1731       pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
1732       break;
1733     default:
1734       print_exp (pp, x, verbose);
1735       break;
1736     }
1737 }                               /* print_value */
1738
1739 /* The next step in insn detalization, its pattern recognition.  */
1740
1741 void
1742 print_pattern (pretty_printer *pp, const_rtx x, int verbose)
1743 {
1744   if (! x)
1745     {
1746       pp_string (pp, "(nil)");
1747       return;
1748     }
1749
1750   switch (GET_CODE (x))
1751     {
1752     case SET:
1753       print_value (pp, SET_DEST (x), verbose);
1754       pp_equal (pp);
1755       print_value (pp, SET_SRC (x), verbose);
1756       break;
1757     case RETURN:
1758     case SIMPLE_RETURN:
1759     case EH_RETURN:
1760       pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
1761       break;
1762     case CALL:
1763       print_exp (pp, x, verbose);
1764       break;
1765     case CLOBBER:
1766     case CLOBBER_HIGH:
1767     case USE:
1768       pp_printf (pp, "%s ", GET_RTX_NAME (GET_CODE (x)));
1769       print_value (pp, XEXP (x, 0), verbose);
1770       break;
1771     case VAR_LOCATION:
1772       pp_string (pp, "loc ");
1773       print_value (pp, PAT_VAR_LOCATION_LOC (x), verbose);
1774       break;
1775     case COND_EXEC:
1776       pp_left_paren (pp);
1777       if (GET_CODE (COND_EXEC_TEST (x)) == NE
1778           && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1779         print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1780       else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
1781                && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
1782         {
1783           pp_exclamation (pp);
1784           print_value (pp, XEXP (COND_EXEC_TEST (x), 0), verbose);
1785         }
1786       else
1787         print_value (pp, COND_EXEC_TEST (x), verbose);
1788       pp_string (pp, ") ");
1789       print_pattern (pp, COND_EXEC_CODE (x), verbose);
1790       break;
1791     case PARALLEL:
1792       {
1793         int i;
1794
1795         pp_left_brace (pp);
1796         for (i = 0; i < XVECLEN (x, 0); i++)
1797           {
1798             print_pattern (pp, XVECEXP (x, 0, i), verbose);
1799             pp_semicolon (pp);
1800           }
1801         pp_right_brace (pp);
1802       }
1803       break;
1804     case SEQUENCE:
1805       {
1806         const rtx_sequence *seq = as_a <const rtx_sequence *> (x);
1807         pp_string (pp, "sequence{");
1808         if (INSN_P (seq->element (0)))
1809           {
1810             /* Print the sequence insns indented.  */
1811             const char * save_print_rtx_head = print_rtx_head;
1812             char indented_print_rtx_head[32];
1813
1814             pp_newline (pp);
1815             gcc_assert (strlen (print_rtx_head) < sizeof (indented_print_rtx_head) - 4);
1816             snprintf (indented_print_rtx_head,
1817                       sizeof (indented_print_rtx_head),
1818                       "%s    ", print_rtx_head);
1819             print_rtx_head = indented_print_rtx_head;
1820             for (int i = 0; i < seq->len (); i++)
1821               print_insn_with_notes (pp, seq->insn (i));
1822             pp_printf (pp, "%s      ", save_print_rtx_head);
1823             print_rtx_head = save_print_rtx_head;
1824           }
1825         else
1826           {
1827             for (int i = 0; i < seq->len (); i++)
1828               {
1829                 print_pattern (pp, seq->element (i), verbose);
1830                 pp_semicolon (pp);
1831               }
1832           }
1833         pp_right_brace (pp);
1834       }
1835       break;
1836     case ASM_INPUT:
1837       pp_printf (pp, "asm {%s}", XSTR (x, 0));
1838       break;
1839     case ADDR_VEC:
1840       for (int i = 0; i < XVECLEN (x, 0); i++)
1841         {
1842           print_value (pp, XVECEXP (x, 0, i), verbose);
1843           pp_semicolon (pp);
1844         }
1845       break;
1846     case ADDR_DIFF_VEC:
1847       for (int i = 0; i < XVECLEN (x, 1); i++)
1848         {
1849           print_value (pp, XVECEXP (x, 1, i), verbose);
1850           pp_semicolon (pp);
1851         }
1852       break;
1853     case TRAP_IF:
1854       pp_string (pp, "trap_if ");
1855       print_value (pp, TRAP_CONDITION (x), verbose);
1856       break;
1857     case UNSPEC:
1858     case UNSPEC_VOLATILE:
1859       /* Fallthru -- leave UNSPECs to print_exp.  */
1860     default:
1861       print_value (pp, x, verbose);
1862     }
1863 }                               /* print_pattern */
1864
1865 /* This is the main function in slim rtl visualization mechanism.
1866
1867    X is an insn, to be printed into PP.
1868
1869    This function tries to print it properly in human-readable form,
1870    resembling assembler mnemonics (instead of the older Lisp-style
1871    form).
1872
1873    If VERBOSE is TRUE, insns are printed with more complete (but
1874    longer) pattern names and with extra information, and prefixed
1875    with their INSN_UIDs.  */
1876
1877 void
1878 print_insn (pretty_printer *pp, const rtx_insn *x, int verbose)
1879 {
1880   if (verbose)
1881     {
1882       /* Blech, pretty-print can't print integers with a specified width.  */
1883       char uid_prefix[32];
1884       snprintf (uid_prefix, sizeof uid_prefix, " %4d: ", INSN_UID (x));
1885       pp_string (pp, uid_prefix);
1886     }
1887
1888   switch (GET_CODE (x))
1889     {
1890     case INSN:
1891       print_pattern (pp, PATTERN (x), verbose);
1892       break;
1893
1894     case DEBUG_INSN:
1895       {
1896         if (DEBUG_MARKER_INSN_P (x))
1897           {
1898             switch (INSN_DEBUG_MARKER_KIND (x))
1899               {
1900               case NOTE_INSN_BEGIN_STMT:
1901                 pp_string (pp, "debug begin stmt marker");
1902                 break;
1903
1904               case NOTE_INSN_INLINE_ENTRY:
1905                 pp_string (pp, "debug inline entry marker");
1906                 break;
1907
1908               default:
1909                 gcc_unreachable ();
1910               }
1911             break;
1912           }
1913
1914         const char *name = "?";
1915         char idbuf[32];
1916
1917         if (DECL_P (INSN_VAR_LOCATION_DECL (x)))
1918           {
1919             tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (x));
1920             if (id)
1921               name = IDENTIFIER_POINTER (id);
1922             else if (TREE_CODE (INSN_VAR_LOCATION_DECL (x))
1923                      == DEBUG_EXPR_DECL)
1924               {
1925                 sprintf (idbuf, "D#%i",
1926                          DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (x)));
1927                 name = idbuf;
1928               }
1929             else
1930               {
1931                 sprintf (idbuf, "D.%i",
1932                          DECL_UID (INSN_VAR_LOCATION_DECL (x)));
1933                 name = idbuf;
1934               }
1935           }
1936         pp_printf (pp, "debug %s => ", name);
1937         if (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (x)))
1938           pp_string (pp, "optimized away");
1939         else
1940           print_pattern (pp, INSN_VAR_LOCATION_LOC (x), verbose);
1941       }
1942       break;
1943
1944     case JUMP_INSN:
1945       print_pattern (pp, PATTERN (x), verbose);
1946       break;
1947     case CALL_INSN:
1948       if (GET_CODE (PATTERN (x)) == PARALLEL)
1949         print_pattern (pp, XVECEXP (PATTERN (x), 0, 0), verbose);
1950       else
1951         print_pattern (pp, PATTERN (x), verbose);
1952       break;
1953     case CODE_LABEL:
1954       pp_printf (pp, "L%d:", INSN_UID (x));
1955       break;
1956     case JUMP_TABLE_DATA:
1957       pp_string (pp, "jump_table_data{\n");
1958       print_pattern (pp, PATTERN (x), verbose);
1959       pp_right_brace (pp);
1960       break;
1961     case BARRIER:
1962       pp_string (pp, "barrier");
1963       break;
1964     case NOTE:
1965       {
1966         pp_string (pp, GET_NOTE_INSN_NAME (NOTE_KIND (x)));
1967         switch (NOTE_KIND (x))
1968           {
1969           case NOTE_INSN_EH_REGION_BEG:
1970           case NOTE_INSN_EH_REGION_END:
1971             pp_printf (pp, " %d", NOTE_EH_HANDLER (x));
1972             break;
1973
1974           case NOTE_INSN_BLOCK_BEG:
1975           case NOTE_INSN_BLOCK_END:
1976             pp_printf (pp, " %d", BLOCK_NUMBER (NOTE_BLOCK (x)));
1977             break;
1978
1979           case NOTE_INSN_BASIC_BLOCK:
1980             pp_printf (pp, " %d", NOTE_BASIC_BLOCK (x)->index);
1981             break;
1982
1983           case NOTE_INSN_DELETED_LABEL:
1984           case NOTE_INSN_DELETED_DEBUG_LABEL:
1985             {
1986               const char *label = NOTE_DELETED_LABEL_NAME (x);
1987               if (label == NULL)
1988                 label = "";
1989               pp_printf (pp, " (\"%s\")", label);
1990             }
1991             break;
1992
1993           case NOTE_INSN_VAR_LOCATION:
1994             pp_left_brace (pp);
1995             print_pattern (pp, NOTE_VAR_LOCATION (x), verbose);
1996             pp_right_brace (pp);
1997             break;
1998
1999           default:
2000             break;
2001           }
2002         break;
2003       }
2004     default:
2005       gcc_unreachable ();
2006     }
2007 }                               /* print_insn */
2008
2009 /* Pretty-print a slim dump of X (an insn) to PP, including any register
2010    note attached to the instruction.  */
2011
2012 static void
2013 print_insn_with_notes (pretty_printer *pp, const rtx_insn *x)
2014 {
2015   pp_string (pp, print_rtx_head);
2016   print_insn (pp, x, 1);
2017   pp_newline (pp);
2018   if (INSN_P (x) && REG_NOTES (x))
2019     for (rtx note = REG_NOTES (x); note; note = XEXP (note, 1))
2020       {
2021         pp_printf (pp, "%s      %s ", print_rtx_head,
2022                    GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
2023         if (GET_CODE (note) == INT_LIST)
2024           pp_printf (pp, "%d", XINT (note, 0));
2025         else
2026           print_pattern (pp, XEXP (note, 0), 1);
2027         pp_newline (pp);
2028       }
2029 }
2030
2031 /* Print X, an RTL value node, to file F in slim format.  Include
2032    additional information if VERBOSE is nonzero.
2033
2034    Value nodes are constants, registers, labels, symbols and
2035    memory.  */
2036
2037 void
2038 dump_value_slim (FILE *f, const_rtx x, int verbose)
2039 {
2040   pretty_printer rtl_slim_pp;
2041   rtl_slim_pp.buffer->stream = f;
2042   print_value (&rtl_slim_pp, x, verbose);
2043   pp_flush (&rtl_slim_pp);
2044 }
2045
2046 /* Emit a slim dump of X (an insn) to the file F, including any register
2047    note attached to the instruction.  */
2048 void
2049 dump_insn_slim (FILE *f, const rtx_insn *x)
2050 {
2051   pretty_printer rtl_slim_pp;
2052   rtl_slim_pp.buffer->stream = f;
2053   print_insn_with_notes (&rtl_slim_pp, x);
2054   pp_flush (&rtl_slim_pp);
2055 }
2056
2057 /* Same as above, but stop at LAST or when COUNT == 0.
2058    If COUNT < 0 it will stop only at LAST or NULL rtx.  */
2059
2060 void
2061 dump_rtl_slim (FILE *f, const rtx_insn *first, const rtx_insn *last,
2062                int count, int flags ATTRIBUTE_UNUSED)
2063 {
2064   const rtx_insn *insn, *tail;
2065   pretty_printer rtl_slim_pp;
2066   rtl_slim_pp.buffer->stream = f;
2067
2068   tail = last ? NEXT_INSN (last) : NULL;
2069   for (insn = first;
2070        (insn != NULL) && (insn != tail) && (count != 0);
2071        insn = NEXT_INSN (insn))
2072     {
2073       print_insn_with_notes (&rtl_slim_pp, insn);
2074       if (count > 0)
2075         count--;
2076     }
2077
2078   pp_flush (&rtl_slim_pp);
2079 }
2080
2081 /* Dumps basic block BB to pretty-printer PP in slim form and without and
2082    no indentation, for use as a label of a DOT graph record-node.  */
2083
2084 void
2085 rtl_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
2086 {
2087   rtx_insn *insn;
2088   bool first = true;
2089
2090   /* TODO: inter-bb stuff.  */
2091   FOR_BB_INSNS (bb, insn)
2092     {
2093       if (! first)
2094         {
2095           pp_bar (pp);
2096           pp_write_text_to_stream (pp);
2097         }
2098       first = false;
2099       print_insn_with_notes (pp, insn);
2100       pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
2101     }
2102 }
2103
2104 /* Pretty-print pattern X of some insn in non-verbose mode.
2105    Return a string pointer to the pretty-printer buffer.
2106
2107    This function is only exported exists only to accommodate some older users
2108    of the slim RTL pretty printers.  Please do not use it for new code.  */
2109
2110 const char *
2111 str_pattern_slim (const_rtx x)
2112 {
2113   pretty_printer rtl_slim_pp;
2114   print_pattern (&rtl_slim_pp, x, 0);
2115   return ggc_strdup (pp_formatted_text (&rtl_slim_pp));
2116 }
2117
2118 /* Emit a slim dump of X (an insn) to stderr.  */
2119 extern void debug_insn_slim (const rtx_insn *);
2120 DEBUG_FUNCTION void
2121 debug_insn_slim (const rtx_insn *x)
2122 {
2123   dump_insn_slim (stderr, x);
2124 }
2125
2126 /* Same as above, but using dump_rtl_slim.  */
2127 extern void debug_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
2128                             int, int);
2129 DEBUG_FUNCTION void
2130 debug_rtl_slim (const rtx_insn *first, const rtx_insn *last, int count,
2131                 int flags)
2132 {
2133   dump_rtl_slim (stderr, first, last, count, flags);
2134 }
2135
2136 extern void debug_bb_slim (basic_block);
2137 DEBUG_FUNCTION void
2138 debug_bb_slim (basic_block bb)
2139 {
2140   dump_bb (stderr, bb, 0, TDF_SLIM | TDF_BLOCKS);
2141 }
2142
2143 extern void debug_bb_n_slim (int);
2144 DEBUG_FUNCTION void
2145 debug_bb_n_slim (int n)
2146 {
2147   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, n);
2148   debug_bb_slim (bb);
2149 }
2150
2151 #endif
2152
2153 #if __GNUC__ >= 10
2154 #  pragma GCC diagnostic pop
2155 #endif