]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cfghooks.c
re PR target/16532 (Inefficient jump to epilogue)
[thirdparty/gcc.git] / gcc / cfghooks.c
CommitLineData
9ee634e3 1/* Hooks for cfg representation specific functions.
283334f0 2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
9ee634e3
JH
3 Contributed by Sebastian Pop <s.pop@laposte.net>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "tree.h"
27#include "rtl.h"
28#include "basic-block.h"
6de9cd9a 29#include "tree-flow.h"
f470c378
ZD
30#include "timevar.h"
31#include "toplev.h"
9ee634e3
JH
32
33/* A pointer to one of the hooks containers. */
f470c378 34static struct cfg_hooks *cfg_hooks;
9ee634e3
JH
35
36/* Initialization of functions specific to the rtl IR. */
d329e058
AJ
37void
38rtl_register_cfg_hooks (void)
9ee634e3
JH
39{
40 cfg_hooks = &rtl_cfg_hooks;
41}
42
43/* Initialization of functions specific to the rtl IR. */
d329e058
AJ
44void
45cfg_layout_rtl_register_cfg_hooks (void)
9ee634e3
JH
46{
47 cfg_hooks = &cfg_layout_rtl_cfg_hooks;
48}
f470c378 49
6de9cd9a
DN
50/* Initialization of functions specific to the tree IR. */
51
52void
53tree_register_cfg_hooks (void)
54{
55 cfg_hooks = &tree_cfg_hooks;
56}
57
58/* Returns current ir type (rtl = 0, trees = 1). */
59
60int
61ir_type (void)
62{
63 return cfg_hooks == &tree_cfg_hooks ? 1 : 0;
64}
65
f470c378
ZD
66/* Verify the CFG consistency.
67
68 Currently it does following: checks edge and basic block list correctness
69 and calls into IL dependent checking then. */
70
71void
72verify_flow_info (void)
73{
74 size_t *edge_checksum;
75 int num_bb_notes, err = 0;
76 basic_block bb, last_bb_seen;
77 basic_block *last_visited;
78
79 timevar_push (TV_CFG_VERIFY);
80 last_visited = xcalloc (last_basic_block + 2, sizeof (basic_block));
81 edge_checksum = xcalloc (last_basic_block + 2, sizeof (size_t));
82
83 /* Check bb chain & numbers. */
84 last_bb_seen = ENTRY_BLOCK_PTR;
85 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
86 {
87 if (bb != EXIT_BLOCK_PTR
88 && bb != BASIC_BLOCK (bb->index))
89 {
90 error ("bb %d on wrong place", bb->index);
91 err = 1;
92 }
93
94 if (bb->prev_bb != last_bb_seen)
95 {
96 error ("prev_bb of %d should be %d, not %d",
97 bb->index, last_bb_seen->index, bb->prev_bb->index);
98 err = 1;
99 }
100
101 last_bb_seen = bb;
102 }
103
104 /* Now check the basic blocks (boundaries etc.) */
105 FOR_EACH_BB_REVERSE (bb)
106 {
107 int n_fallthru = 0;
108 edge e;
109
110 if (bb->count < 0)
111 {
112 error ("verify_flow_info: Wrong count of block %i %i",
113 bb->index, (int)bb->count);
114 err = 1;
115 }
116 if (bb->frequency < 0)
117 {
118 error ("verify_flow_info: Wrong frequency of block %i %i",
119 bb->index, bb->frequency);
120 err = 1;
121 }
122 for (e = bb->succ; e; e = e->succ_next)
123 {
124 if (last_visited [e->dest->index + 2] == bb)
125 {
126 error ("verify_flow_info: Duplicate edge %i->%i",
127 e->src->index, e->dest->index);
128 err = 1;
129 }
130 if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
131 {
132 error ("verify_flow_info: Wrong probability of edge %i->%i %i",
133 e->src->index, e->dest->index, e->probability);
134 err = 1;
135 }
136 if (e->count < 0)
137 {
138 error ("verify_flow_info: Wrong count of edge %i->%i %i",
139 e->src->index, e->dest->index, (int)e->count);
140 err = 1;
141 }
142
143 last_visited [e->dest->index + 2] = bb;
144
145 if (e->flags & EDGE_FALLTHRU)
146 n_fallthru++;
147
148 if (e->src != bb)
149 {
150 error ("verify_flow_info: Basic block %d succ edge is corrupted",
151 bb->index);
152 fprintf (stderr, "Predecessor: ");
153 dump_edge_info (stderr, e, 0);
154 fprintf (stderr, "\nSuccessor: ");
155 dump_edge_info (stderr, e, 1);
156 fprintf (stderr, "\n");
157 err = 1;
158 }
159
160 edge_checksum[e->dest->index + 2] += (size_t) e;
161 }
162 if (n_fallthru > 1)
163 {
164 error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
165 err = 1;
166 }
167
168 for (e = bb->pred; e; e = e->pred_next)
169 {
170 if (e->dest != bb)
171 {
172 error ("basic block %d pred edge is corrupted", bb->index);
173 fputs ("Predecessor: ", stderr);
174 dump_edge_info (stderr, e, 0);
175 fputs ("\nSuccessor: ", stderr);
176 dump_edge_info (stderr, e, 1);
177 fputc ('\n', stderr);
178 err = 1;
179 }
180 edge_checksum[e->dest->index + 2] -= (size_t) e;
181 }
182 }
183
184 /* Complete edge checksumming for ENTRY and EXIT. */
185 {
186 edge e;
187
188 for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
189 edge_checksum[e->dest->index + 2] += (size_t) e;
190
191 for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
192 edge_checksum[e->dest->index + 2] -= (size_t) e;
193 }
194
195 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
196 if (edge_checksum[bb->index + 2])
197 {
198 error ("basic block %i edge lists are corrupted", bb->index);
199 err = 1;
200 }
201
202 num_bb_notes = 0;
203 last_bb_seen = ENTRY_BLOCK_PTR;
204
205 /* Clean up. */
206 free (last_visited);
207 free (edge_checksum);
208
209 if (cfg_hooks->verify_flow_info)
210 err |= cfg_hooks->verify_flow_info ();
211 if (err)
212 internal_error ("verify_flow_info failed");
213 timevar_pop (TV_CFG_VERIFY);
214}
215
216/* Print out one basic block. This function takes care of the purely
217 graph related information. The cfg hook for the active representation
218 should dump representation-specific information. */
219
220void
221dump_bb (basic_block bb, FILE *outf, int indent)
222{
223 edge e;
224 char *s_indent;
225
400e39e3
KH
226 s_indent = alloca ((size_t) indent + 1);
227 memset (s_indent, ' ', (size_t) indent);
f470c378
ZD
228 s_indent[indent] = '\0';
229
230 fprintf (outf, ";;%s basic block %d, loop depth %d, count ",
231 s_indent, bb->index, bb->loop_depth);
232 fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
233 putc ('\n', outf);
234
235 fprintf (outf, ";;%s prev block ", s_indent);
236 if (bb->prev_bb)
237 fprintf (outf, "%d, ", bb->prev_bb->index);
238 else
239 fprintf (outf, "(nil), ");
240 fprintf (outf, "next block ");
241 if (bb->next_bb)
242 fprintf (outf, "%d", bb->next_bb->index);
243 else
244 fprintf (outf, "(nil)");
245 putc ('\n', outf);
246
247 fprintf (outf, ";;%s pred: ", s_indent);
248 for (e = bb->pred; e; e = e->pred_next)
249 dump_edge_info (outf, e, 0);
250 putc ('\n', outf);
251
252 fprintf (outf, ";;%s succ: ", s_indent);
253 for (e = bb->succ; e; e = e->succ_next)
254 dump_edge_info (outf, e, 1);
255 putc ('\n', outf);
256
257 if (cfg_hooks->dump_bb)
258 cfg_hooks->dump_bb (bb, outf, indent);
259}
260
261/* Redirect edge E to the given basic block DEST and update underlying program
262 representation. Returns edge representing redirected branch (that may not
263 be equivalent to E in the case of duplicate edges being removed) or NULL
264 if edge is not easily redirectable for whatever reason. */
265
6de9cd9a 266edge
f470c378
ZD
267redirect_edge_and_branch (edge e, basic_block dest)
268{
6de9cd9a 269 edge ret;
f470c378
ZD
270
271 if (!cfg_hooks->redirect_edge_and_branch)
272 internal_error ("%s does not support redirect_edge_and_branch.",
273 cfg_hooks->name);
274
275 ret = cfg_hooks->redirect_edge_and_branch (e, dest);
276
277 return ret;
278}
279
280/* Redirect the edge E to basic block DEST even if it requires creating
281 of a new basic block; then it returns the newly created basic block.
282 Aborts when redirection is impossible. */
283
284basic_block
285redirect_edge_and_branch_force (edge e, basic_block dest)
286{
287 basic_block ret;
288
289 if (!cfg_hooks->redirect_edge_and_branch_force)
290 internal_error ("%s does not support redirect_edge_and_branch_force.",
291 cfg_hooks->name);
292
293 ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
294
295 return ret;
296}
297
298/* Splits basic block BB after the specified instruction I (but at least after
299 the labels). If I is NULL, splits just after labels. The newly created edge
300 is returned. The new basic block is created just after the old one. */
301
302edge
303split_block (basic_block bb, void *i)
304{
305 basic_block new_bb;
306
307 if (!cfg_hooks->split_block)
308 internal_error ("%s does not support split_block.", cfg_hooks->name);
309
310 new_bb = cfg_hooks->split_block (bb, i);
311 if (!new_bb)
312 return NULL;
313
314 new_bb->count = bb->count;
315 new_bb->frequency = bb->frequency;
316 new_bb->loop_depth = bb->loop_depth;
317
318 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
319 {
320 redirect_immediate_dominators (CDI_DOMINATORS, bb, new_bb);
321 set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
322 }
323
649b2789 324 return make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
f470c378
ZD
325}
326
327/* Splits block BB just after labels. The newly created edge is returned. */
328
329edge
330split_block_after_labels (basic_block bb)
331{
332 return split_block (bb, NULL);
333}
334
321440fd 335/* Moves block BB immediately after block AFTER. Returns false if the
f470c378
ZD
336 movement was impossible. */
337
338bool
339move_block_after (basic_block bb, basic_block after)
340{
341 bool ret;
342
343 if (!cfg_hooks->move_block_after)
344 internal_error ("%s does not support move_block_after.", cfg_hooks->name);
345
346 ret = cfg_hooks->move_block_after (bb, after);
347
348 return ret;
349}
350
351/* Deletes the basic block BB. */
352
353void
354delete_basic_block (basic_block bb)
355{
356 if (!cfg_hooks->delete_basic_block)
357 internal_error ("%s does not support delete_basic_block.", cfg_hooks->name);
358
359 cfg_hooks->delete_basic_block (bb);
360
361 /* Remove the edges into and out of this block. Note that there may
362 indeed be edges in, if we are removing an unreachable loop. */
363 while (bb->pred != NULL)
364 remove_edge (bb->pred);
365 while (bb->succ != NULL)
366 remove_edge (bb->succ);
367
368 bb->pred = NULL;
369 bb->succ = NULL;
370
371 if (dom_computed[CDI_DOMINATORS])
372 delete_from_dominance_info (CDI_DOMINATORS, bb);
373 if (dom_computed[CDI_POST_DOMINATORS])
374 delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
375
376 /* Remove the basic block from the array. */
377 expunge_block (bb);
378}
379
380/* Splits edge E and returns the newly created basic block. */
381
382basic_block
383split_edge (edge e)
384{
385 basic_block ret;
386 gcov_type count = e->count;
387 int freq = EDGE_FREQUENCY (e);
017b3258 388 edge f;
f470c378
ZD
389
390 if (!cfg_hooks->split_edge)
391 internal_error ("%s does not support split_edge.", cfg_hooks->name);
392
393 ret = cfg_hooks->split_edge (e);
394 ret->count = count;
395 ret->frequency = freq;
396 ret->succ->probability = REG_BR_PROB_BASE;
397 ret->succ->count = count;
398
399 if (dom_computed[CDI_DOMINATORS])
400 set_immediate_dominator (CDI_DOMINATORS, ret, ret->pred->src);
401
402 if (dom_computed[CDI_DOMINATORS] >= DOM_NO_FAST_QUERY)
017b3258
ZD
403 {
404 /* There are two cases:
405
406 If the immediate dominator of e->dest is not e->src, it
407 remains unchanged.
408
409 If immediate dominator of e->dest is e->src, it may become
410 ret, provided that all other predecessors of e->dest are
411 dominated by e->dest. */
412
413 if (get_immediate_dominator (CDI_DOMINATORS, ret->succ->dest)
414 == ret->pred->src)
415 {
416 for (f = ret->succ->dest->pred; f; f = f->pred_next)
417 {
418 if (f == ret->succ)
419 continue;
420
421 if (!dominated_by_p (CDI_DOMINATORS, f->src,
422 ret->succ->dest))
423 break;
424 }
425
426 if (!f)
427 set_immediate_dominator (CDI_DOMINATORS, ret->succ->dest, ret);
428 }
429 };
f470c378
ZD
430
431 return ret;
432}
433
434/* Creates a new basic block just after the basic block AFTER.
435 HEAD and END are the first and the last statement belonging
436 to the block. If both are NULL, an empty block is created. */
437
438basic_block
439create_basic_block (void *head, void *end, basic_block after)
440{
441 basic_block ret;
442
443 if (!cfg_hooks->create_basic_block)
444 internal_error ("%s does not support create_basic_block.", cfg_hooks->name);
445
446 ret = cfg_hooks->create_basic_block (head, end, after);
447
448 if (dom_computed[CDI_DOMINATORS])
449 add_to_dominance_info (CDI_DOMINATORS, ret);
450 if (dom_computed[CDI_POST_DOMINATORS])
451 add_to_dominance_info (CDI_POST_DOMINATORS, ret);
452
453 return ret;
454}
455
456/* Creates an empty basic block just after basic block AFTER. */
457
458basic_block
459create_empty_bb (basic_block after)
460{
461 return create_basic_block (NULL, NULL, after);
462}
463
464/* Checks whether we may merge blocks BB1 and BB2. */
465
466bool
467can_merge_blocks_p (basic_block bb1, basic_block bb2)
468{
469 bool ret;
470
471 if (!cfg_hooks->can_merge_blocks_p)
472 internal_error ("%s does not support can_merge_blocks_p.", cfg_hooks->name);
473
474 ret = cfg_hooks->can_merge_blocks_p (bb1, bb2);
475
476 return ret;
477}
478
6de9cd9a
DN
479void
480predict_edge (edge e, enum br_predictor predictor, int probability)
481{
482 if (!cfg_hooks->predict_edge)
483 internal_error ("%s does not support predict_edge.", cfg_hooks->name);
484
485 cfg_hooks->predict_edge (e, predictor, probability);
486}
487
488bool
489predicted_by_p (basic_block bb, enum br_predictor predictor)
490{
491 if (!cfg_hooks->predict_edge)
492 internal_error ("%s does not support predicted_by_p.", cfg_hooks->name);
493
494 return cfg_hooks->predicted_by_p (bb, predictor);
495}
496
f470c378
ZD
497/* Merges basic block B into basic block A. */
498
499void
500merge_blocks (basic_block a, basic_block b)
501{
502 edge e;
503
504 if (!cfg_hooks->merge_blocks)
505 internal_error ("%s does not support merge_blocks.", cfg_hooks->name);
506
507 cfg_hooks->merge_blocks (a, b);
508
509 /* Normally there should only be one successor of A and that is B, but
510 partway though the merge of blocks for conditional_execution we'll
511 be merging a TEST block with THEN and ELSE successors. Free the
512 whole lot of them and hope the caller knows what they're doing. */
513 while (a->succ)
514 remove_edge (a->succ);
515
516 /* Adjust the edges out of B for the new owner. */
517 for (e = b->succ; e; e = e->succ_next)
518 e->src = a;
519 a->succ = b->succ;
520 a->flags |= b->flags;
521
522 /* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
523 b->pred = b->succ = NULL;
524 a->global_live_at_end = b->global_live_at_end;
525
526 if (dom_computed[CDI_DOMINATORS])
527 redirect_immediate_dominators (CDI_DOMINATORS, b, a);
528
529 if (dom_computed[CDI_DOMINATORS])
530 delete_from_dominance_info (CDI_DOMINATORS, b);
531 if (dom_computed[CDI_POST_DOMINATORS])
532 delete_from_dominance_info (CDI_POST_DOMINATORS, b);
533
534 expunge_block (b);
535}
536
537/* Split BB into entry part and the rest (the rest is the newly created block).
538 Redirect those edges for that REDIRECT_EDGE_P returns true to the entry
539 part. Returns the edge connecting the entry part to the rest. */
540
541edge
542make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
543 void (*new_bb_cbk) (basic_block))
544{
545 edge e, next_e, fallthru;
546 basic_block dummy, jump;
547
548 if (!cfg_hooks->make_forwarder_block)
549 internal_error ("%s does not support make_forwarder_block.",
550 cfg_hooks->name);
551
552 fallthru = split_block_after_labels (bb);
553 dummy = fallthru->src;
554 bb = fallthru->dest;
555
556 /* Redirect back edges we want to keep. */
557 for (e = dummy->pred; e; e = next_e)
558 {
559 next_e = e->pred_next;
560 if (redirect_edge_p (e))
561 continue;
562
563 dummy->frequency -= EDGE_FREQUENCY (e);
564 dummy->count -= e->count;
565 if (dummy->frequency < 0)
566 dummy->frequency = 0;
567 if (dummy->count < 0)
568 dummy->count = 0;
649b2789
PH
569 fallthru->count -= e->count;
570 if (fallthru->count < 0)
571 fallthru->count = 0;
f470c378
ZD
572
573 jump = redirect_edge_and_branch_force (e, bb);
574 if (jump)
575 new_bb_cbk (jump);
576 }
577
578 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
579 {
580 basic_block doms_to_fix[2];
581
582 doms_to_fix[0] = dummy;
583 doms_to_fix[1] = bb;
584 iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, 2);
585 }
586
587 cfg_hooks->make_forwarder_block (fallthru);
588
589 return fallthru;
590}
591
592void
593tidy_fallthru_edge (edge e)
594{
595 if (cfg_hooks->tidy_fallthru_edge)
596 cfg_hooks->tidy_fallthru_edge (e);
597}
598
599/* Fix up edges that now fall through, or rather should now fall through
600 but previously required a jump around now deleted blocks. Simplify
601 the search by only examining blocks numerically adjacent, since this
602 is how find_basic_blocks created them. */
603
604void
605tidy_fallthru_edges (void)
606{
607 basic_block b, c;
608
609 if (!cfg_hooks->tidy_fallthru_edge)
610 return;
611
612 if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
613 return;
614
615 FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, next_bb)
616 {
617 edge s;
618
619 c = b->next_bb;
620
621 /* We care about simple conditional or unconditional jumps with
622 a single successor.
623
624 If we had a conditional branch to the next instruction when
625 find_basic_blocks was called, then there will only be one
626 out edge for the block which ended with the conditional
627 branch (since we do not create duplicate edges).
628
629 Furthermore, the edge will be marked as a fallthru because we
630 merge the flags for the duplicate edges. So we do not want to
631 check that the edge is not a FALLTHRU edge. */
632
633 if ((s = b->succ) != NULL
634 && ! (s->flags & EDGE_COMPLEX)
635 && s->succ_next == NULL
750054a2
CT
636 && s->dest == c
637 && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
f470c378
ZD
638 tidy_fallthru_edge (s);
639 }
640}
6de9cd9a
DN
641
642/* Returns true if we can duplicate basic block BB. */
643
644bool
645can_duplicate_block_p (basic_block bb)
646{
647 edge e;
648
649 if (!cfg_hooks->can_duplicate_block_p)
650 internal_error ("%s does not support can_duplicate_block_p.",
651 cfg_hooks->name);
652
653 if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
654 return false;
655
656 /* Duplicating fallthru block to exit would require adding a jump
657 and splitting the real last BB. */
658 for (e = bb->succ; e; e = e->succ_next)
659 if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_FALLTHRU)
660 return false;
661
662 return cfg_hooks->can_duplicate_block_p (bb);
663}
664
665/* Duplicates basic block BB and redirects edge E to it. Returns the
666 new basic block. */
667
668basic_block
669duplicate_block (basic_block bb, edge e)
670{
671 edge s, n;
672 basic_block new_bb;
673 gcov_type new_count = e ? e->count : 0;
674
675 if (!cfg_hooks->duplicate_block)
676 internal_error ("%s does not support duplicate_block.",
677 cfg_hooks->name);
678
679 if (bb->count < new_count)
680 new_count = bb->count;
341c100f 681 gcc_assert (bb->pred);
6de9cd9a 682#ifdef ENABLE_CHECKING
341c100f 683 gcc_assert (can_duplicate_block_p (bb));
6de9cd9a
DN
684#endif
685
686 new_bb = cfg_hooks->duplicate_block (bb);
687
688 new_bb->loop_depth = bb->loop_depth;
689 new_bb->flags = bb->flags;
690 for (s = bb->succ; s; s = s->succ_next)
691 {
692 /* Since we are creating edges from a new block to successors
693 of another block (which therefore are known to be disjoint), there
694 is no need to actually check for duplicated edges. */
695 n = unchecked_make_edge (new_bb, s->dest, s->flags);
696 n->probability = s->probability;
697 if (e && bb->count)
698 {
699 /* Take care for overflows! */
700 n->count = s->count * (new_count * 10000 / bb->count) / 10000;
701 s->count -= n->count;
702 }
703 else
704 n->count = s->count;
705 n->aux = s->aux;
706 }
707
708 if (e)
709 {
710 new_bb->count = new_count;
711 bb->count -= new_count;
712
713 new_bb->frequency = EDGE_FREQUENCY (e);
714 bb->frequency -= EDGE_FREQUENCY (e);
715
716 redirect_edge_and_branch_force (e, new_bb);
717
718 if (bb->count < 0)
719 bb->count = 0;
720 if (bb->frequency < 0)
721 bb->frequency = 0;
722 }
723 else
724 {
725 new_bb->count = bb->count;
726 new_bb->frequency = bb->frequency;
727 }
728
729 new_bb->rbi->original = bb;
730 bb->rbi->copy = new_bb;
731
732 return new_bb;
733}
734
735/* Return 1 if BB ends with a call, possibly followed by some
736 instructions that must stay with the call, 0 otherwise. */
737
738bool
739block_ends_with_call_p (basic_block bb)
740{
741 if (!cfg_hooks->block_ends_with_call_p)
742 internal_error ("%s does not support block_ends_with_call_p", cfg_hooks->name);
743
744 return (cfg_hooks->block_ends_with_call_p) (bb);
745}
746
747/* Return 1 if BB ends with a conditional branch, 0 otherwise. */
748
749bool
750block_ends_with_condjump_p (basic_block bb)
751{
752 if (!cfg_hooks->block_ends_with_condjump_p)
753 internal_error ("%s does not support block_ends_with_condjump_p",
754 cfg_hooks->name);
755
756 return (cfg_hooks->block_ends_with_condjump_p) (bb);
757}
758
759/* Add fake edges to the function exit for any non constant and non noreturn
760 calls, volatile inline assembly in the bitmap of blocks specified by
761 BLOCKS or to the whole CFG if BLOCKS is zero. Return the number of blocks
762 that were split.
763
764 The goal is to expose cases in which entering a basic block does not imply
765 that all subsequent instructions must be executed. */
766
767int
768flow_call_edges_add (sbitmap blocks)
769{
770 if (!cfg_hooks->flow_call_edges_add)
771 internal_error ("%s does not support flow_call_edges_add",
772 cfg_hooks->name);
773
774 return (cfg_hooks->flow_call_edges_add) (blocks);
775}