Mercurial > hg > CbC > CbC_gcc
comparison gcc/cfgrtl.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
40 #include "config.h" | 40 #include "config.h" |
41 #include "system.h" | 41 #include "system.h" |
42 #include "coretypes.h" | 42 #include "coretypes.h" |
43 #include "tm.h" | 43 #include "tm.h" |
44 #include "tree.h" | 44 #include "tree.h" |
45 #include "rtl.h" | |
46 #include "hard-reg-set.h" | 45 #include "hard-reg-set.h" |
47 #include "basic-block.h" | 46 #include "basic-block.h" |
48 #include "regs.h" | 47 #include "regs.h" |
49 #include "flags.h" | 48 #include "flags.h" |
50 #include "output.h" | 49 #include "output.h" |
51 #include "function.h" | 50 #include "function.h" |
52 #include "except.h" | 51 #include "except.h" |
53 #include "toplev.h" | 52 #include "rtl-error.h" |
54 #include "tm_p.h" | 53 #include "tm_p.h" |
55 #include "obstack.h" | 54 #include "obstack.h" |
56 #include "insn-attr.h" | 55 #include "insn-attr.h" |
57 #include "insn-config.h" | 56 #include "insn-config.h" |
58 #include "cfglayout.h" | 57 #include "cfglayout.h" |
420 { | 419 { |
421 #ifdef DELAY_SLOTS | 420 #ifdef DELAY_SLOTS |
422 /* The resource.c machinery uses DF but the CFG isn't guaranteed to be | 421 /* The resource.c machinery uses DF but the CFG isn't guaranteed to be |
423 valid at that point so it would be too late to call df_analyze. */ | 422 valid at that point so it would be too late to call df_analyze. */ |
424 if (optimize > 0 && flag_delayed_branch) | 423 if (optimize > 0 && flag_delayed_branch) |
425 df_analyze (); | 424 { |
425 df_note_add_problem (); | |
426 df_analyze (); | |
427 } | |
426 #endif | 428 #endif |
427 | 429 |
428 free_bb_for_insn (); | 430 free_bb_for_insn (); |
429 return 0; | 431 return 0; |
430 } | 432 } |
584 rtl_merge_blocks (basic_block a, basic_block b) | 586 rtl_merge_blocks (basic_block a, basic_block b) |
585 { | 587 { |
586 rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a); | 588 rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a); |
587 rtx del_first = NULL_RTX, del_last = NULL_RTX; | 589 rtx del_first = NULL_RTX, del_last = NULL_RTX; |
588 rtx b_debug_start = b_end, b_debug_end = b_end; | 590 rtx b_debug_start = b_end, b_debug_end = b_end; |
591 bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0; | |
589 int b_empty = 0; | 592 int b_empty = 0; |
590 | 593 |
591 if (dump_file) | 594 if (dump_file) |
592 fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index); | 595 fprintf (dump_file, "Merging block %d into block %d...\n", b->index, |
596 a->index); | |
593 | 597 |
594 while (DEBUG_INSN_P (b_end)) | 598 while (DEBUG_INSN_P (b_end)) |
595 b_end = PREV_INSN (b_debug_start = b_end); | 599 b_end = PREV_INSN (b_debug_start = b_end); |
596 | 600 |
597 /* If there was a CODE_LABEL beginning B, delete it. */ | 601 /* If there was a CODE_LABEL beginning B, delete it. */ |
676 a_end = b_debug_end; | 680 a_end = b_debug_end; |
677 } | 681 } |
678 | 682 |
679 df_bb_delete (b->index); | 683 df_bb_delete (b->index); |
680 BB_END (a) = a_end; | 684 BB_END (a) = a_end; |
685 | |
686 /* If B was a forwarder block, propagate the locus on the edge. */ | |
687 if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus) | |
688 EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus; | |
689 | |
690 if (dump_file) | |
691 fprintf (dump_file, "Merged blocks %d and %d.\n", a->index, b->index); | |
681 } | 692 } |
682 | 693 |
683 | 694 |
684 /* Return true when block A and B can be merged. */ | 695 /* Return true when block A and B can be merged. */ |
685 | 696 |
1049 } | 1060 } |
1050 else | 1061 else |
1051 /* When expanding this BB might actually contain multiple | 1062 /* When expanding this BB might actually contain multiple |
1052 jumps (i.e. not yet split by find_many_sub_basic_blocks). | 1063 jumps (i.e. not yet split by find_many_sub_basic_blocks). |
1053 Redirect all of those that match our label. */ | 1064 Redirect all of those that match our label. */ |
1054 for (insn = BB_HEAD (src); insn != NEXT_INSN (BB_END (src)); | 1065 FOR_BB_INSNS (src, insn) |
1055 insn = NEXT_INSN (insn)) | |
1056 if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target)) | 1066 if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target)) |
1057 return NULL; | 1067 return NULL; |
1058 | 1068 |
1059 if (dump_file) | 1069 if (dump_file) |
1060 fprintf (dump_file, "Edge %i->%i redirected to %i\n", | 1070 fprintf (dump_file, "Edge %i->%i redirected to %i\n", |
1366 | 1376 |
1367 /* We are going to place the new block in front of edge destination. | 1377 /* We are going to place the new block in front of edge destination. |
1368 Avoid existence of fallthru predecessors. */ | 1378 Avoid existence of fallthru predecessors. */ |
1369 if ((edge_in->flags & EDGE_FALLTHRU) == 0) | 1379 if ((edge_in->flags & EDGE_FALLTHRU) == 0) |
1370 { | 1380 { |
1371 edge e; | 1381 edge e = find_fallthru_edge (edge_in->dest->preds); |
1372 edge_iterator ei; | |
1373 | |
1374 FOR_EACH_EDGE (e, ei, edge_in->dest->preds) | |
1375 if (e->flags & EDGE_FALLTHRU) | |
1376 break; | |
1377 | 1382 |
1378 if (e) | 1383 if (e) |
1379 force_nonfallthru (e); | 1384 force_nonfallthru (e); |
1380 } | 1385 } |
1381 | 1386 |
2064 bb_info = XCNEWVEC (basic_block, max_uid); | 2069 bb_info = XCNEWVEC (basic_block, max_uid); |
2065 | 2070 |
2066 FOR_EACH_BB_REVERSE (bb) | 2071 FOR_EACH_BB_REVERSE (bb) |
2067 { | 2072 { |
2068 edge e; | 2073 edge e; |
2069 edge_iterator ei; | |
2070 rtx head = BB_HEAD (bb); | 2074 rtx head = BB_HEAD (bb); |
2071 rtx end = BB_END (bb); | 2075 rtx end = BB_END (bb); |
2072 | 2076 |
2073 for (x = last_head; x != NULL_RTX; x = PREV_INSN (x)) | 2077 for (x = last_head; x != NULL_RTX; x = PREV_INSN (x)) |
2074 { | 2078 { |
2118 err = 1; | 2122 err = 1; |
2119 } | 2123 } |
2120 | 2124 |
2121 last_head = PREV_INSN (x); | 2125 last_head = PREV_INSN (x); |
2122 | 2126 |
2123 FOR_EACH_EDGE (e, ei, bb->succs) | 2127 e = find_fallthru_edge (bb->succs); |
2124 if (e->flags & EDGE_FALLTHRU) | |
2125 break; | |
2126 if (!e) | 2128 if (!e) |
2127 { | 2129 { |
2128 rtx insn; | 2130 rtx insn; |
2129 | 2131 |
2130 /* Ensure existence of barrier in BB with no fallthru edges. */ | 2132 /* Ensure existence of barrier in BB with no fallthru edges. */ |
2696 /* Merge block A and B. The blocks must be mergeable. */ | 2698 /* Merge block A and B. The blocks must be mergeable. */ |
2697 | 2699 |
2698 static void | 2700 static void |
2699 cfg_layout_merge_blocks (basic_block a, basic_block b) | 2701 cfg_layout_merge_blocks (basic_block a, basic_block b) |
2700 { | 2702 { |
2701 #ifdef ENABLE_CHECKING | 2703 bool forwarder_p = (b->flags & BB_FORWARDER_BLOCK) != 0; |
2702 gcc_assert (cfg_layout_can_merge_blocks_p (a, b)); | 2704 |
2703 #endif | 2705 gcc_checking_assert (cfg_layout_can_merge_blocks_p (a, b)); |
2704 | 2706 |
2705 if (dump_file) | 2707 if (dump_file) |
2706 fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index); | 2708 fprintf (dump_file, "Merging block %d into block %d...\n", b->index, |
2709 a->index); | |
2707 | 2710 |
2708 /* If there was a CODE_LABEL beginning B, delete it. */ | 2711 /* If there was a CODE_LABEL beginning B, delete it. */ |
2709 if (LABEL_P (BB_HEAD (b))) | 2712 if (LABEL_P (BB_HEAD (b))) |
2710 { | 2713 { |
2711 delete_insn (BB_HEAD (b)); | 2714 delete_insn (BB_HEAD (b)); |
2809 PREV_INSN (b->il.rtl->footer) = last; | 2812 PREV_INSN (b->il.rtl->footer) = last; |
2810 } | 2813 } |
2811 b->il.rtl->footer = NULL; | 2814 b->il.rtl->footer = NULL; |
2812 } | 2815 } |
2813 | 2816 |
2817 /* If B was a forwarder block, propagate the locus on the edge. */ | |
2818 if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus) | |
2819 EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus; | |
2820 | |
2814 if (dump_file) | 2821 if (dump_file) |
2815 fprintf (dump_file, "Merged blocks %d and %d.\n", | 2822 fprintf (dump_file, "Merged blocks %d and %d.\n", a->index, b->index); |
2816 a->index, b->index); | |
2817 } | 2823 } |
2818 | 2824 |
2819 /* Split edge E. */ | 2825 /* Split edge E. */ |
2820 | 2826 |
2821 static basic_block | 2827 static basic_block |
3078 | 3084 |
3079 void | 3085 void |
3080 init_rtl_bb_info (basic_block bb) | 3086 init_rtl_bb_info (basic_block bb) |
3081 { | 3087 { |
3082 gcc_assert (!bb->il.rtl); | 3088 gcc_assert (!bb->il.rtl); |
3083 bb->il.rtl = GGC_CNEW (struct rtl_bb_info); | 3089 bb->il.rtl = ggc_alloc_cleared_rtl_bb_info (); |
3084 } | |
3085 | |
3086 | |
3087 /* Add EXPR to the end of basic block BB. */ | |
3088 | |
3089 rtx | |
3090 insert_insn_end_bb_new (rtx pat, basic_block bb) | |
3091 { | |
3092 rtx insn = BB_END (bb); | |
3093 rtx new_insn; | |
3094 rtx pat_end = pat; | |
3095 | |
3096 while (NEXT_INSN (pat_end) != NULL_RTX) | |
3097 pat_end = NEXT_INSN (pat_end); | |
3098 | |
3099 /* If the last insn is a jump, insert EXPR in front [taking care to | |
3100 handle cc0, etc. properly]. Similarly we need to care trapping | |
3101 instructions in presence of non-call exceptions. */ | |
3102 | |
3103 if (JUMP_P (insn) | |
3104 || (NONJUMP_INSN_P (insn) | |
3105 && (!single_succ_p (bb) | |
3106 || single_succ_edge (bb)->flags & EDGE_ABNORMAL))) | |
3107 { | |
3108 #ifdef HAVE_cc0 | |
3109 rtx note; | |
3110 #endif | |
3111 /* If this is a jump table, then we can't insert stuff here. Since | |
3112 we know the previous real insn must be the tablejump, we insert | |
3113 the new instruction just before the tablejump. */ | |
3114 if (GET_CODE (PATTERN (insn)) == ADDR_VEC | |
3115 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) | |
3116 insn = prev_real_insn (insn); | |
3117 | |
3118 #ifdef HAVE_cc0 | |
3119 /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts | |
3120 if cc0 isn't set. */ | |
3121 note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); | |
3122 if (note) | |
3123 insn = XEXP (note, 0); | |
3124 else | |
3125 { | |
3126 rtx maybe_cc0_setter = prev_nonnote_insn (insn); | |
3127 if (maybe_cc0_setter | |
3128 && INSN_P (maybe_cc0_setter) | |
3129 && sets_cc0_p (PATTERN (maybe_cc0_setter))) | |
3130 insn = maybe_cc0_setter; | |
3131 } | |
3132 #endif | |
3133 /* FIXME: What if something in cc0/jump uses value set in new | |
3134 insn? */ | |
3135 new_insn = emit_insn_before_noloc (pat, insn, bb); | |
3136 } | |
3137 | |
3138 /* Likewise if the last insn is a call, as will happen in the presence | |
3139 of exception handling. */ | |
3140 else if (CALL_P (insn) | |
3141 && (!single_succ_p (bb) | |
3142 || single_succ_edge (bb)->flags & EDGE_ABNORMAL)) | |
3143 { | |
3144 /* Keeping in mind targets with small register classes and parameters | |
3145 in registers, we search backward and place the instructions before | |
3146 the first parameter is loaded. Do this for everyone for consistency | |
3147 and a presumption that we'll get better code elsewhere as well. */ | |
3148 | |
3149 /* Since different machines initialize their parameter registers | |
3150 in different orders, assume nothing. Collect the set of all | |
3151 parameter registers. */ | |
3152 insn = find_first_parameter_load (insn, BB_HEAD (bb)); | |
3153 | |
3154 /* If we found all the parameter loads, then we want to insert | |
3155 before the first parameter load. | |
3156 | |
3157 If we did not find all the parameter loads, then we might have | |
3158 stopped on the head of the block, which could be a CODE_LABEL. | |
3159 If we inserted before the CODE_LABEL, then we would be putting | |
3160 the insn in the wrong basic block. In that case, put the insn | |
3161 after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */ | |
3162 while (LABEL_P (insn) | |
3163 || NOTE_INSN_BASIC_BLOCK_P (insn)) | |
3164 insn = NEXT_INSN (insn); | |
3165 | |
3166 new_insn = emit_insn_before_noloc (pat, insn, bb); | |
3167 } | |
3168 else | |
3169 new_insn = emit_insn_after_noloc (pat, insn, bb); | |
3170 | |
3171 return new_insn; | |
3172 } | 3090 } |
3173 | 3091 |
3174 /* Returns true if it is possible to remove edge E by redirecting | 3092 /* Returns true if it is possible to remove edge E by redirecting |
3175 it to the destination of the other edge from E->src. */ | 3093 it to the destination of the other edge from E->src. */ |
3176 | 3094 |