00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "tree.h"
00030 #include "rtl.h"
00031 #include "tm_p.h"
00032 #include "basic-block.h"
00033 #include "function.h"
00034 #include "expr.h"
00035 #include "langhooks.h"
00036 #include "tree-flow.h"
00037 #include "timevar.h"
00038 #include "tree-dump.h"
00039 #include "tree-pass.h"
00040 #include "except.h"
00041 #include "flags.h"
00042 #include "diagnostic.h"
00043 #include "toplev.h"
00044
00045
00046
00047
00048
00049
00050 static void
00051 add_reg_br_prob_note (FILE *dump_file, rtx last, int probability)
00052 {
00053 if (profile_status == PROFILE_ABSENT)
00054 return;
00055 for (last = NEXT_INSN (last); last && NEXT_INSN (last); last = NEXT_INSN (last))
00056 if (GET_CODE (last) == JUMP_INSN)
00057 {
00058
00059
00060 if (!any_condjump_p (last)
00061 || GET_CODE (NEXT_INSN (last)) != JUMP_INSN
00062 || !simplejump_p (NEXT_INSN (last))
00063 || GET_CODE (NEXT_INSN (NEXT_INSN (last))) != BARRIER
00064 || GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last)))) != CODE_LABEL
00065 || NEXT_INSN (NEXT_INSN (NEXT_INSN (NEXT_INSN (last)))))
00066 goto failed;
00067 if (find_reg_note (last, REG_BR_PROB, 0))
00068 abort ();
00069 REG_NOTES (last)
00070 = gen_rtx_EXPR_LIST (REG_BR_PROB,
00071 GEN_INT (REG_BR_PROB_BASE - probability),
00072 REG_NOTES (last));
00073 return;
00074 }
00075 if (!last || GET_CODE (last) != JUMP_INSN || !any_condjump_p (last))
00076 goto failed;
00077 if (find_reg_note (last, REG_BR_PROB, 0))
00078 abort ();
00079 REG_NOTES (last)
00080 = gen_rtx_EXPR_LIST (REG_BR_PROB,
00081 GEN_INT (probability), REG_NOTES (last));
00082 return;
00083 failed:
00084 if (dump_file)
00085 fprintf (dump_file, "Failed to add probability note\n");
00086 }
00087
00088
00089 #ifndef LOCAL_ALIGNMENT
00090 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
00091 #endif
00092
00093 #ifndef STACK_ALIGNMENT_NEEDED
00094 #define STACK_ALIGNMENT_NEEDED 1
00095 #endif
00096
00097 #ifdef FRAME_GROWS_DOWNWARD
00098 # undef FRAME_GROWS_DOWNWARD
00099 # define FRAME_GROWS_DOWNWARD 1
00100 #else
00101 # define FRAME_GROWS_DOWNWARD 0
00102 #endif
00103
00104
00105
00106
00107 struct stack_var
00108 {
00109
00110 tree decl;
00111
00112
00113
00114
00115 HOST_WIDE_INT offset;
00116
00117
00118
00119 HOST_WIDE_INT size;
00120
00121
00122
00123 unsigned int alignb;
00124
00125
00126 size_t representative;
00127
00128
00129 size_t next;
00130 };
00131
00132 #define EOC ((size_t)-1)
00133
00134
00135 static struct stack_var *stack_vars;
00136 static size_t stack_vars_alloc;
00137 static size_t stack_vars_num;
00138
00139
00140
00141 static size_t *stack_vars_sorted;
00142
00143
00144
00145 static bool *stack_vars_conflict;
00146 static size_t stack_vars_conflict_alloc;
00147
00148
00149
00150
00151 static int frame_phase;
00152
00153
00154
00155
00156
00157 static unsigned int
00158 get_decl_align_unit (tree decl)
00159 {
00160 unsigned int align;
00161
00162 align = DECL_ALIGN (decl);
00163 align = LOCAL_ALIGNMENT (TREE_TYPE (decl), align);
00164 if (align > PREFERRED_STACK_BOUNDARY)
00165 align = PREFERRED_STACK_BOUNDARY;
00166 if (cfun->stack_alignment_needed < align)
00167 cfun->stack_alignment_needed = align;
00168
00169 return align / BITS_PER_UNIT;
00170 }
00171
00172
00173
00174
00175 static HOST_WIDE_INT
00176 alloc_stack_frame_space (HOST_WIDE_INT size, HOST_WIDE_INT align)
00177 {
00178 HOST_WIDE_INT offset, new_frame_offset;
00179
00180 new_frame_offset = frame_offset;
00181 if (FRAME_GROWS_DOWNWARD)
00182 {
00183 new_frame_offset -= size + frame_phase;
00184 new_frame_offset &= -align;
00185 new_frame_offset += frame_phase;
00186 offset = new_frame_offset;
00187 }
00188 else
00189 {
00190 new_frame_offset -= frame_phase;
00191 new_frame_offset += align - 1;
00192 new_frame_offset &= -align;
00193 new_frame_offset += frame_phase;
00194 offset = new_frame_offset;
00195 new_frame_offset += size;
00196 }
00197 frame_offset = new_frame_offset;
00198
00199 return offset;
00200 }
00201
00202
00203
00204 static void
00205 add_stack_var (tree decl)
00206 {
00207 if (stack_vars_num >= stack_vars_alloc)
00208 {
00209 if (stack_vars_alloc)
00210 stack_vars_alloc = stack_vars_alloc * 3 / 2;
00211 else
00212 stack_vars_alloc = 32;
00213 stack_vars
00214 = XRESIZEVEC (struct stack_var, stack_vars, stack_vars_alloc);
00215 }
00216 stack_vars[stack_vars_num].decl = decl;
00217 stack_vars[stack_vars_num].offset = 0;
00218 stack_vars[stack_vars_num].size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
00219 stack_vars[stack_vars_num].alignb = get_decl_align_unit (decl);
00220
00221
00222 stack_vars[stack_vars_num].representative = stack_vars_num;
00223 stack_vars[stack_vars_num].next = EOC;
00224
00225
00226 SET_DECL_RTL (decl, pc_rtx);
00227
00228 stack_vars_num++;
00229 }
00230
00231
00232
00233 static size_t
00234 triangular_index (size_t i, size_t j)
00235 {
00236 if (i < j)
00237 {
00238 size_t t;
00239 t = i, i = j, j = t;
00240 }
00241 return (i * (i + 1)) / 2 + j;
00242 }
00243
00244
00245
00246 static void
00247 resize_stack_vars_conflict (size_t n)
00248 {
00249 size_t size = triangular_index (n-1, n-1) + 1;
00250
00251 if (size <= stack_vars_conflict_alloc)
00252 return;
00253
00254 stack_vars_conflict = XRESIZEVEC (bool, stack_vars_conflict, size);
00255 memset (stack_vars_conflict + stack_vars_conflict_alloc, 0,
00256 (size - stack_vars_conflict_alloc) * sizeof (bool));
00257 stack_vars_conflict_alloc = size;
00258 }
00259
00260
00261
00262 static void
00263 add_stack_var_conflict (size_t x, size_t y)
00264 {
00265 size_t index = triangular_index (x, y);
00266 gcc_assert (index < stack_vars_conflict_alloc);
00267 stack_vars_conflict[index] = true;
00268 }
00269
00270
00271
00272 static bool
00273 stack_var_conflict_p (size_t x, size_t y)
00274 {
00275 size_t index = triangular_index (x, y);
00276 gcc_assert (index < stack_vars_conflict_alloc);
00277 return stack_vars_conflict[index];
00278 }
00279
00280
00281
00282
00283
00284
00285 static void
00286 add_alias_set_conflicts (void)
00287 {
00288 size_t i, j, n = stack_vars_num;
00289
00290 for (i = 0; i < n; ++i)
00291 {
00292 bool aggr_i = AGGREGATE_TYPE_P (TREE_TYPE (stack_vars[i].decl));
00293 HOST_WIDE_INT set_i = get_alias_set (stack_vars[i].decl);
00294
00295 for (j = 0; j < i; ++j)
00296 {
00297 bool aggr_j = AGGREGATE_TYPE_P (TREE_TYPE (stack_vars[j].decl));
00298 HOST_WIDE_INT set_j = get_alias_set (stack_vars[j].decl);
00299 if (aggr_i != aggr_j || !alias_sets_conflict_p (set_i, set_j))
00300 add_stack_var_conflict (i, j);
00301 }
00302 }
00303 }
00304
00305
00306
00307
00308 static int
00309 stack_var_size_cmp (const void *a, const void *b)
00310 {
00311 HOST_WIDE_INT sa = stack_vars[*(const size_t *)a].size;
00312 HOST_WIDE_INT sb = stack_vars[*(const size_t *)b].size;
00313
00314 if (sa < sb)
00315 return -1;
00316 if (sa > sb)
00317 return 1;
00318 return 0;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 static void
00330 union_stack_vars (size_t a, size_t b, HOST_WIDE_INT offset)
00331 {
00332 size_t i, last;
00333
00334
00335
00336 for (last = i = b; i != EOC; last = i, i = stack_vars[i].next)
00337 {
00338 stack_vars[i].offset += offset;
00339 stack_vars[i].representative = a;
00340 }
00341 stack_vars[last].next = stack_vars[a].next;
00342 stack_vars[a].next = b;
00343
00344
00345 if (stack_vars[a].alignb < stack_vars[b].alignb)
00346 stack_vars[a].alignb = stack_vars[b].alignb;
00347
00348
00349 for (last = stack_vars_num, i = 0; i < last; ++i)
00350 if (stack_var_conflict_p (b, i))
00351 add_stack_var_conflict (a, i);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 static void
00373 partition_stack_vars (void)
00374 {
00375 size_t si, sj, n = stack_vars_num;
00376
00377 stack_vars_sorted = XNEWVEC (size_t, stack_vars_num);
00378 for (si = 0; si < n; ++si)
00379 stack_vars_sorted[si] = si;
00380
00381 if (n == 1)
00382 return;
00383
00384 qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_size_cmp);
00385
00386
00387
00388
00389
00390
00391 gcc_assert (sizeof(bool) == sizeof(char));
00392 if (memchr (stack_vars_conflict, false, stack_vars_conflict_alloc) == NULL)
00393 return;
00394
00395 for (si = 0; si < n; ++si)
00396 {
00397 size_t i = stack_vars_sorted[si];
00398 HOST_WIDE_INT isize = stack_vars[i].size;
00399 HOST_WIDE_INT offset = 0;
00400
00401 for (sj = si; sj-- > 0; )
00402 {
00403 size_t j = stack_vars_sorted[sj];
00404 HOST_WIDE_INT jsize = stack_vars[j].size;
00405 unsigned int jalign = stack_vars[j].alignb;
00406
00407
00408 if (stack_vars[j].representative != j)
00409 continue;
00410
00411
00412 if (isize < jsize)
00413 continue;
00414
00415
00416 if (stack_var_conflict_p (i, j))
00417 continue;
00418
00419
00420 if (offset & (jalign - 1))
00421 {
00422 HOST_WIDE_INT toff = offset;
00423 toff += jalign - 1;
00424 toff &= -(HOST_WIDE_INT)jalign;
00425 if (isize - (toff - offset) < jsize)
00426 continue;
00427
00428 isize -= toff - offset;
00429 offset = toff;
00430 }
00431
00432
00433 union_stack_vars (i, j, offset);
00434
00435 isize -= jsize;
00436 if (isize == 0)
00437 break;
00438 }
00439 }
00440 }
00441
00442
00443
00444 static void
00445 dump_stack_var_partition (void)
00446 {
00447 size_t si, i, j, n = stack_vars_num;
00448
00449 for (si = 0; si < n; ++si)
00450 {
00451 i = stack_vars_sorted[si];
00452
00453
00454 if (stack_vars[i].representative != i)
00455 continue;
00456
00457 fprintf (dump_file, "Partition %lu: size " HOST_WIDE_INT_PRINT_DEC
00458 " align %u\n", (unsigned long) i, stack_vars[i].size,
00459 stack_vars[i].alignb);
00460
00461 for (j = i; j != EOC; j = stack_vars[j].next)
00462 {
00463 fputc ('\t', dump_file);
00464 print_generic_expr (dump_file, stack_vars[j].decl, dump_flags);
00465 fprintf (dump_file, ", offset " HOST_WIDE_INT_PRINT_DEC "\n",
00466 stack_vars[i].offset);
00467 }
00468 }
00469 }
00470
00471
00472
00473 static void
00474 expand_one_stack_var_at (tree decl, HOST_WIDE_INT offset)
00475 {
00476 HOST_WIDE_INT align;
00477 rtx x;
00478
00479
00480 gcc_assert (offset == trunc_int_for_mode (offset, Pmode));
00481
00482 x = plus_constant (virtual_stack_vars_rtx, offset);
00483 x = gen_rtx_MEM (DECL_MODE (decl), x);
00484
00485
00486 offset -= frame_phase;
00487 align = offset & -offset;
00488 align *= BITS_PER_UNIT;
00489 if (align > STACK_BOUNDARY || align == 0)
00490 align = STACK_BOUNDARY;
00491 DECL_ALIGN (decl) = align;
00492 DECL_USER_ALIGN (decl) = 0;
00493
00494 set_mem_attributes (x, decl, true);
00495 SET_DECL_RTL (decl, x);
00496 }
00497
00498
00499
00500
00501
00502 static void
00503 expand_stack_vars (void)
00504 {
00505 size_t si, i, j, n = stack_vars_num;
00506
00507 for (si = 0; si < n; ++si)
00508 {
00509 HOST_WIDE_INT offset;
00510
00511 i = stack_vars_sorted[si];
00512
00513
00514 if (stack_vars[i].representative != i)
00515 continue;
00516
00517 offset = alloc_stack_frame_space (stack_vars[i].size,
00518 stack_vars[i].alignb);
00519
00520
00521
00522 for (j = i; j != EOC; j = stack_vars[j].next)
00523 expand_one_stack_var_at (stack_vars[j].decl,
00524 stack_vars[j].offset + offset);
00525 }
00526 }
00527
00528
00529
00530
00531 static void
00532 expand_one_stack_var (tree var)
00533 {
00534 HOST_WIDE_INT size, offset, align;
00535
00536 size = tree_low_cst (DECL_SIZE_UNIT (var), 1);
00537 align = get_decl_align_unit (var);
00538 offset = alloc_stack_frame_space (size, align);
00539
00540 expand_one_stack_var_at (var, offset);
00541 }
00542
00543
00544
00545
00546 static void
00547 expand_one_static_var (tree var)
00548 {
00549
00550
00551 var = DECL_ORIGIN (var);
00552
00553
00554 if (TREE_ASM_WRITTEN (var))
00555 return;
00556
00557
00558
00559 if (lang_hooks.expand_decl (var))
00560 return;
00561
00562
00563 rest_of_decl_compilation (var, 0, 0);
00564 }
00565
00566
00567
00568
00569 static void
00570 expand_one_hard_reg_var (tree var)
00571 {
00572 rest_of_decl_compilation (var, 0, 0);
00573 }
00574
00575
00576
00577
00578 static void
00579 expand_one_register_var (tree var)
00580 {
00581 tree type = TREE_TYPE (var);
00582 int unsignedp = TYPE_UNSIGNED (type);
00583 enum machine_mode reg_mode
00584 = promote_mode (type, DECL_MODE (var), &unsignedp, 0);
00585 rtx x = gen_reg_rtx (reg_mode);
00586
00587 SET_DECL_RTL (var, x);
00588
00589
00590 if (!DECL_ARTIFICIAL (var))
00591 {
00592 mark_user_reg (x);
00593
00594
00595
00596
00597
00598
00599
00600 if (POINTER_TYPE_P (type))
00601 mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (var))));
00602 }
00603 }
00604
00605
00606
00607
00608
00609 static void
00610 expand_one_error_var (tree var)
00611 {
00612 enum machine_mode mode = DECL_MODE (var);
00613 rtx x;
00614
00615 if (mode == BLKmode)
00616 x = gen_rtx_MEM (BLKmode, const0_rtx);
00617 else if (mode == VOIDmode)
00618 x = const0_rtx;
00619 else
00620 x = gen_reg_rtx (mode);
00621
00622 SET_DECL_RTL (var, x);
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 static bool
00634 defer_stack_allocation (tree var, bool toplevel)
00635 {
00636
00637
00638
00639
00640 if (toplevel && optimize < 2)
00641 return false;
00642
00643
00644
00645
00646
00647
00648
00649 if (optimize == 0 && tree_low_cst (DECL_SIZE_UNIT (var), 1) < 32)
00650 return false;
00651
00652 return true;
00653 }
00654
00655
00656
00657
00658
00659 static void
00660 expand_one_var (tree var, bool toplevel)
00661 {
00662 if (TREE_CODE (var) != VAR_DECL)
00663 lang_hooks.expand_decl (var);
00664 else if (DECL_EXTERNAL (var))
00665 ;
00666 else if (DECL_VALUE_EXPR (var))
00667 ;
00668 else if (TREE_STATIC (var))
00669 expand_one_static_var (var);
00670 else if (DECL_RTL_SET_P (var))
00671 ;
00672 else if (TREE_TYPE (var) == error_mark_node)
00673 expand_one_error_var (var);
00674 else if (DECL_HARD_REGISTER (var))
00675 expand_one_hard_reg_var (var);
00676 else if (use_register_for_decl (var))
00677 expand_one_register_var (var);
00678 else if (defer_stack_allocation (var, toplevel))
00679 add_stack_var (var);
00680 else
00681 expand_one_stack_var (var);
00682 }
00683
00684
00685
00686
00687
00688
00689
00690 static void
00691 expand_used_vars_for_block (tree block, bool toplevel)
00692 {
00693 size_t i, j, old_sv_num, this_sv_num, new_sv_num;
00694 tree t;
00695
00696 old_sv_num = toplevel ? 0 : stack_vars_num;
00697
00698
00699 for (t = BLOCK_VARS (block); t ; t = TREE_CHAIN (t))
00700 if (TREE_USED (t))
00701 expand_one_var (t, toplevel);
00702
00703 this_sv_num = stack_vars_num;
00704
00705
00706 for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
00707 expand_used_vars_for_block (t, false);
00708
00709
00710
00711
00712
00713
00714 if (old_sv_num < this_sv_num)
00715 {
00716 new_sv_num = stack_vars_num;
00717 resize_stack_vars_conflict (new_sv_num);
00718
00719 for (i = old_sv_num; i < new_sv_num; ++i)
00720 for (j = i < this_sv_num ? i+1 : this_sv_num; j-- > old_sv_num ;)
00721 add_stack_var_conflict (i, j);
00722 }
00723 }
00724
00725
00726
00727
00728 static void
00729 clear_tree_used (tree block)
00730 {
00731 tree t;
00732
00733 for (t = BLOCK_VARS (block); t ; t = TREE_CHAIN (t))
00734
00735 TREE_USED (t) = 0;
00736
00737 for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
00738 clear_tree_used (t);
00739 }
00740
00741
00742
00743 static void
00744 expand_used_vars (void)
00745 {
00746 tree t, outer_block = DECL_INITIAL (current_function_decl);
00747
00748
00749 {
00750 int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00751 int off = STARTING_FRAME_OFFSET % align;
00752 frame_phase = off ? align - off : 0;
00753 }
00754
00755
00756 for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
00757 TREE_USED (TREE_VALUE (t)) = 1;
00758
00759
00760 clear_tree_used (outer_block);
00761
00762
00763
00764 for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
00765 {
00766 tree var = TREE_VALUE (t);
00767 bool expand_now = false;
00768
00769
00770
00771
00772
00773
00774 if (TREE_STATIC (var) || DECL_EXTERNAL (var))
00775 expand_now = true;
00776
00777
00778
00779
00780
00781 else if (is_gimple_reg (var))
00782 expand_now = true;
00783
00784
00785
00786
00787 else if (TREE_USED (var))
00788 expand_now = true;
00789
00790
00791
00792 TREE_USED (var) = 1;
00793
00794 if (expand_now)
00795 expand_one_var (var, true);
00796 }
00797 cfun->unexpanded_var_list = NULL_TREE;
00798
00799
00800
00801 expand_used_vars_for_block (outer_block, true);
00802
00803 if (stack_vars_num > 0)
00804 {
00805
00806
00807
00808 add_alias_set_conflicts ();
00809
00810
00811
00812 partition_stack_vars ();
00813 if (dump_file)
00814 dump_stack_var_partition ();
00815
00816
00817 expand_stack_vars ();
00818
00819
00820 XDELETEVEC (stack_vars);
00821 XDELETEVEC (stack_vars_sorted);
00822 XDELETEVEC (stack_vars_conflict);
00823 stack_vars = NULL;
00824 stack_vars_alloc = stack_vars_num = 0;
00825 stack_vars_conflict = NULL;
00826 stack_vars_conflict_alloc = 0;
00827 }
00828
00829
00830 if (STACK_ALIGNMENT_NEEDED)
00831 {
00832 HOST_WIDE_INT align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00833 if (!FRAME_GROWS_DOWNWARD)
00834 frame_offset += align - 1;
00835 frame_offset &= -align;
00836 }
00837 }
00838
00839
00840
00841
00842
00843
00844 static void
00845 maybe_dump_rtl_for_tree_stmt (tree stmt, rtx since)
00846 {
00847 if (dump_file && (dump_flags & TDF_DETAILS))
00848 {
00849 fprintf (dump_file, "\n;; ");
00850 print_generic_expr (dump_file, stmt, TDF_SLIM);
00851 fprintf (dump_file, "\n");
00852
00853 print_rtl (dump_file, since ? NEXT_INSN (since) : since);
00854 }
00855 }
00856
00857
00858
00859
00860
00861 static basic_block
00862 expand_gimple_cond_expr (basic_block bb, tree stmt)
00863 {
00864 basic_block new_bb, dest;
00865 edge new_edge;
00866 edge true_edge;
00867 edge false_edge;
00868 tree pred = COND_EXPR_COND (stmt);
00869 tree then_exp = COND_EXPR_THEN (stmt);
00870 tree else_exp = COND_EXPR_ELSE (stmt);
00871 rtx last2, last;
00872
00873 last2 = last = get_last_insn ();
00874
00875 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
00876 if (EXPR_LOCUS (stmt))
00877 {
00878 emit_line_note (*(EXPR_LOCUS (stmt)));
00879 record_block_change (TREE_BLOCK (stmt));
00880 }
00881
00882
00883 true_edge->flags &= ~EDGE_TRUE_VALUE;
00884 false_edge->flags &= ~EDGE_FALSE_VALUE;
00885
00886
00887
00888 if (TREE_CODE (then_exp) == GOTO_EXPR && IS_EMPTY_STMT (else_exp))
00889 {
00890 jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
00891 add_reg_br_prob_note (dump_file, last, true_edge->probability);
00892 maybe_dump_rtl_for_tree_stmt (stmt, last);
00893 if (EXPR_LOCUS (then_exp))
00894 emit_line_note (*(EXPR_LOCUS (then_exp)));
00895 return NULL;
00896 }
00897 if (TREE_CODE (else_exp) == GOTO_EXPR && IS_EMPTY_STMT (then_exp))
00898 {
00899 jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp)));
00900 add_reg_br_prob_note (dump_file, last, false_edge->probability);
00901 maybe_dump_rtl_for_tree_stmt (stmt, last);
00902 if (EXPR_LOCUS (else_exp))
00903 emit_line_note (*(EXPR_LOCUS (else_exp)));
00904 return NULL;
00905 }
00906 gcc_assert (TREE_CODE (then_exp) == GOTO_EXPR
00907 && TREE_CODE (else_exp) == GOTO_EXPR);
00908
00909 jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
00910 add_reg_br_prob_note (dump_file, last, true_edge->probability);
00911 last = get_last_insn ();
00912 expand_expr (else_exp, const0_rtx, VOIDmode, 0);
00913
00914 BB_END (bb) = last;
00915 if (BARRIER_P (BB_END (bb)))
00916 BB_END (bb) = PREV_INSN (BB_END (bb));
00917 update_bb_for_insn (bb);
00918
00919 new_bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
00920 dest = false_edge->dest;
00921 redirect_edge_succ (false_edge, new_bb);
00922 false_edge->flags |= EDGE_FALLTHRU;
00923 new_bb->count = false_edge->count;
00924 new_bb->frequency = EDGE_FREQUENCY (false_edge);
00925 new_edge = make_edge (new_bb, dest, 0);
00926 new_edge->probability = REG_BR_PROB_BASE;
00927 new_edge->count = new_bb->count;
00928 if (BARRIER_P (BB_END (new_bb)))
00929 BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
00930 update_bb_for_insn (new_bb);
00931
00932 maybe_dump_rtl_for_tree_stmt (stmt, last2);
00933
00934 if (EXPR_LOCUS (else_exp))
00935 emit_line_note (*(EXPR_LOCUS (else_exp)));
00936
00937 return new_bb;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 static basic_block
00951 expand_gimple_tailcall (basic_block bb, tree stmt, bool *can_fallthru)
00952 {
00953 rtx last2, last;
00954 edge e;
00955 edge_iterator ei;
00956 int probability;
00957 gcov_type count;
00958
00959 last2 = last = get_last_insn ();
00960
00961 expand_expr_stmt (stmt);
00962
00963 for (last = NEXT_INSN (last); last; last = NEXT_INSN (last))
00964 if (CALL_P (last) && SIBLING_CALL_P (last))
00965 goto found;
00966
00967 maybe_dump_rtl_for_tree_stmt (stmt, last2);
00968
00969 *can_fallthru = true;
00970 return NULL;
00971
00972 found:
00973
00974
00975 do_pending_stack_adjust ();
00976
00977
00978
00979
00980
00981
00982
00983
00984 probability = 0;
00985 count = 0;
00986
00987 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00988 {
00989 if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
00990 {
00991 if (e->dest != EXIT_BLOCK_PTR)
00992 {
00993 e->dest->count -= e->count;
00994 e->dest->frequency -= EDGE_FREQUENCY (e);
00995 if (e->dest->count < 0)
00996 e->dest->count = 0;
00997 if (e->dest->frequency < 0)
00998 e->dest->frequency = 0;
00999 }
01000 count += e->count;
01001 probability += e->probability;
01002 remove_edge (e);
01003 }
01004 else
01005 ei_next (&ei);
01006 }
01007
01008
01009
01010
01011 last = NEXT_INSN (last);
01012 gcc_assert (BARRIER_P (last));
01013
01014 *can_fallthru = false;
01015 while (NEXT_INSN (last))
01016 {
01017
01018
01019 if (LABEL_P (NEXT_INSN (last)))
01020 {
01021 *can_fallthru = true;
01022 break;
01023 }
01024 delete_insn (NEXT_INSN (last));
01025 }
01026
01027 e = make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_SIBCALL);
01028 e->probability += probability;
01029 e->count += count;
01030 BB_END (bb) = last;
01031 update_bb_for_insn (bb);
01032
01033 if (NEXT_INSN (last))
01034 {
01035 bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
01036
01037 last = BB_END (bb);
01038 if (BARRIER_P (last))
01039 BB_END (bb) = PREV_INSN (last);
01040 }
01041
01042 maybe_dump_rtl_for_tree_stmt (stmt, last2);
01043
01044 return bb;
01045 }
01046
01047
01048
01049 static basic_block
01050 expand_gimple_basic_block (basic_block bb, FILE * dump_file)
01051 {
01052 block_stmt_iterator bsi = bsi_start (bb);
01053 tree stmt = NULL;
01054 rtx note, last;
01055 edge e;
01056 edge_iterator ei;
01057
01058 if (dump_file)
01059 {
01060 fprintf (dump_file,
01061 "\n;; Generating RTL for tree basic block %d\n",
01062 bb->index);
01063 }
01064
01065 if (!bsi_end_p (bsi))
01066 stmt = bsi_stmt (bsi);
01067
01068 if (stmt && TREE_CODE (stmt) == LABEL_EXPR)
01069 {
01070 last = get_last_insn ();
01071
01072 expand_expr_stmt (stmt);
01073
01074
01075
01076 BB_HEAD (bb) = NEXT_INSN (last);
01077 if (NOTE_P (BB_HEAD (bb)))
01078 BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb));
01079 bsi_next (&bsi);
01080 note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb));
01081
01082 maybe_dump_rtl_for_tree_stmt (stmt, last);
01083 }
01084 else
01085 note = BB_HEAD (bb) = emit_note (NOTE_INSN_BASIC_BLOCK);
01086
01087 NOTE_BASIC_BLOCK (note) = bb;
01088
01089 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
01090 {
01091
01092 e->flags &= ~EDGE_EXECUTABLE;
01093
01094
01095
01096
01097 if (e->flags & EDGE_ABNORMAL)
01098 remove_edge (e);
01099 else
01100 ei_next (&ei);
01101 }
01102
01103 for (; !bsi_end_p (bsi); bsi_next (&bsi))
01104 {
01105 tree stmt = bsi_stmt (bsi);
01106 basic_block new_bb;
01107
01108 if (!stmt)
01109 continue;
01110
01111
01112
01113 if (TREE_CODE (stmt) == COND_EXPR)
01114 {
01115 new_bb = expand_gimple_cond_expr (bb, stmt);
01116 if (new_bb)
01117 return new_bb;
01118 }
01119 else
01120 {
01121 tree call = get_call_expr_in (stmt);
01122 if (call && CALL_EXPR_TAILCALL (call))
01123 {
01124 bool can_fallthru;
01125 new_bb = expand_gimple_tailcall (bb, stmt, &can_fallthru);
01126 if (new_bb)
01127 {
01128 if (can_fallthru)
01129 bb = new_bb;
01130 else
01131 return new_bb;
01132 }
01133 }
01134 else
01135 {
01136 last = get_last_insn ();
01137 expand_expr_stmt (stmt);
01138 maybe_dump_rtl_for_tree_stmt (stmt, last);
01139 }
01140 }
01141 }
01142
01143 do_pending_stack_adjust ();
01144
01145
01146
01147 last = get_last_insn ();
01148 if (BARRIER_P (last))
01149 last = PREV_INSN (last);
01150 if (JUMP_TABLE_DATA_P (last))
01151 last = PREV_INSN (PREV_INSN (last));
01152 BB_END (bb) = last;
01153
01154 update_bb_for_insn (bb);
01155
01156 return bb;
01157 }
01158
01159
01160
01161
01162 static basic_block
01163 construct_init_block (void)
01164 {
01165 basic_block init_block, first_block;
01166 edge e = NULL;
01167 int flags;
01168
01169
01170 gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1);
01171
01172 e = EDGE_SUCC (ENTRY_BLOCK_PTR, 0);
01173
01174
01175
01176 if (e && e->dest != ENTRY_BLOCK_PTR->next_bb)
01177 {
01178 tree label = tree_block_label (e->dest);
01179
01180 emit_jump (label_rtx (label));
01181 flags = 0;
01182 }
01183 else
01184 flags = EDGE_FALLTHRU;
01185
01186 init_block = create_basic_block (NEXT_INSN (get_insns ()),
01187 get_last_insn (),
01188 ENTRY_BLOCK_PTR);
01189 init_block->frequency = ENTRY_BLOCK_PTR->frequency;
01190 init_block->count = ENTRY_BLOCK_PTR->count;
01191 if (e)
01192 {
01193 first_block = e->dest;
01194 redirect_edge_succ (e, init_block);
01195 e = make_edge (init_block, first_block, flags);
01196 }
01197 else
01198 e = make_edge (init_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
01199 e->probability = REG_BR_PROB_BASE;
01200 e->count = ENTRY_BLOCK_PTR->count;
01201
01202 update_bb_for_insn (init_block);
01203 return init_block;
01204 }
01205
01206
01207
01208
01209 static void
01210 construct_exit_block (void)
01211 {
01212 rtx head = get_last_insn ();
01213 rtx end;
01214 basic_block exit_block;
01215 edge e, e2;
01216 unsigned ix;
01217 edge_iterator ei;
01218
01219
01220
01221 #ifdef USE_MAPPED_LOCATION
01222 if (cfun->function_end_locus != UNKNOWN_LOCATION)
01223 #else
01224 if (cfun->function_end_locus.file)
01225 #endif
01226 input_location = cfun->function_end_locus;
01227
01228
01229 record_block_change (DECL_INITIAL (current_function_decl));
01230
01231
01232 expand_function_end ();
01233
01234 end = get_last_insn ();
01235 if (head == end)
01236 return;
01237 while (NEXT_INSN (head) && NOTE_P (NEXT_INSN (head)))
01238 head = NEXT_INSN (head);
01239 exit_block = create_basic_block (NEXT_INSN (head), end,
01240 EXIT_BLOCK_PTR->prev_bb);
01241 exit_block->frequency = EXIT_BLOCK_PTR->frequency;
01242 exit_block->count = EXIT_BLOCK_PTR->count;
01243
01244 ix = 0;
01245 while (ix < EDGE_COUNT (EXIT_BLOCK_PTR->preds))
01246 {
01247 e = EDGE_I (EXIT_BLOCK_PTR->preds, ix);
01248 if (!(e->flags & EDGE_ABNORMAL))
01249 redirect_edge_succ (e, exit_block);
01250 else
01251 ix++;
01252 }
01253
01254 e = make_edge (exit_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
01255 e->probability = REG_BR_PROB_BASE;
01256 e->count = EXIT_BLOCK_PTR->count;
01257 FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR->preds)
01258 if (e2 != e)
01259 {
01260 e->count -= e2->count;
01261 exit_block->count -= e2->count;
01262 exit_block->frequency -= EDGE_FREQUENCY (e2);
01263 }
01264 if (e->count < 0)
01265 e->count = 0;
01266 if (exit_block->count < 0)
01267 exit_block->count = 0;
01268 if (exit_block->frequency < 0)
01269 exit_block->frequency = 0;
01270 update_bb_for_insn (exit_block);
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 static void
01283 tree_expand_cfg (void)
01284 {
01285 basic_block bb, init_block;
01286 sbitmap blocks;
01287
01288
01289 currently_expanding_to_rtl = 1;
01290
01291
01292 reset_block_changes ();
01293
01294
01295 expand_used_vars ();
01296
01297 #ifdef KEY
01298
01299 if (flag_spin_file)
01300 return;
01301 #endif
01302
01303
01304 expand_function_start (current_function_decl);
01305
01306
01307
01308 if (DECL_NAME (current_function_decl)
01309 && MAIN_NAME_P (DECL_NAME (current_function_decl))
01310 && DECL_FILE_SCOPE_P (current_function_decl))
01311 expand_main_function ();
01312
01313
01314 rtl_register_cfg_hooks ();
01315
01316 init_block = construct_init_block ();
01317
01318 FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb)
01319 bb = expand_gimple_basic_block (bb, dump_file);
01320
01321 construct_exit_block ();
01322
01323
01324 currently_expanding_to_rtl = 0;
01325
01326
01327
01328 convert_from_eh_region_ranges ();
01329
01330 rebuild_jump_labels (get_insns ());
01331 find_exception_handler_labels ();
01332
01333 blocks = sbitmap_alloc (last_basic_block);
01334 sbitmap_ones (blocks);
01335 find_many_sub_basic_blocks (blocks);
01336 purge_all_dead_edges (0);
01337 sbitmap_free (blocks);
01338
01339 compact_blocks ();
01340 #ifdef ENABLE_CHECKING
01341 verify_flow_info();
01342 #endif
01343
01344
01345
01346 DECL_DEFER_OUTPUT (current_function_decl) = 0;
01347
01348
01349
01350 generating_concat_p = 0;
01351
01352 finalize_block_changes ();
01353
01354 if (dump_file)
01355 {
01356 fprintf (dump_file,
01357 "\n\n;;\n;; Full RTL generated for this function:\n;;\n");
01358
01359 }
01360 }
01361
01362 struct tree_opt_pass pass_expand =
01363 {
01364 "expand",
01365 NULL,
01366 tree_expand_cfg,
01367 NULL,
01368 NULL,
01369 0,
01370 TV_EXPAND,
01371
01372 PROP_gimple_leh | PROP_cfg,
01373 PROP_rtl,
01374 PROP_gimple_leh,
01375 0,
01376 0,
01377 'r'
01378 };