00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "tm_p.h"
00028 #include "hard-reg-set.h"
00029 #include "basic-block.h"
00030 #include "function.h"
00031 #include "tree-flow.h"
00032 #include "tree-dump.h"
00033 #include "diagnostic.h"
00034 #include "except.h"
00035 #include "tree-pass.h"
00036 #include "flags.h"
00037 #include "langhooks.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 struct tailcall
00102 {
00103
00104 basic_block call_block;
00105
00106
00107 block_stmt_iterator call_bsi;
00108
00109
00110 bool tail_recursion;
00111
00112
00113
00114 tree mult, add;
00115
00116
00117 struct tailcall *next;
00118 };
00119
00120
00121
00122 static tree m_acc, a_acc;
00123
00124 static bool suitable_for_tail_opt_p (void);
00125 static bool optimize_tail_call (struct tailcall *, bool);
00126 static void eliminate_tail_call (struct tailcall *);
00127 static void find_tail_calls (basic_block, struct tailcall **);
00128
00129
00130
00131
00132 static bool
00133 suitable_for_tail_opt_p (void)
00134 {
00135 referenced_var_iterator rvi;
00136 tree var;
00137
00138 if (current_function_stdarg)
00139 return false;
00140
00141
00142
00143
00144 FOR_EACH_REFERENCED_VAR (var, rvi)
00145 {
00146
00147 if (!is_global_var (var)
00148 && (!MTAG_P (var) || TREE_CODE (var) == STRUCT_FIELD_TAG)
00149 && is_call_clobbered (var))
00150 return false;
00151 }
00152
00153 return true;
00154 }
00155
00156
00157
00158
00159
00160 static bool
00161 suitable_for_tail_call_opt_p (void)
00162 {
00163 tree param;
00164
00165
00166
00167 if (current_function_calls_alloca)
00168 return false;
00169
00170
00171
00172
00173 if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers ())
00174 return false;
00175
00176
00177
00178
00179 if (current_function_calls_setjmp)
00180 return false;
00181
00182
00183
00184 for (param = DECL_ARGUMENTS (current_function_decl);
00185 param;
00186 param = TREE_CHAIN (param))
00187 if (TREE_ADDRESSABLE (param))
00188 return false;
00189
00190 return true;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 static tree
00200 independent_of_stmt_p (tree expr, tree at, block_stmt_iterator bsi)
00201 {
00202 basic_block bb, call_bb, at_bb;
00203 edge e;
00204 edge_iterator ei;
00205
00206 if (is_gimple_min_invariant (expr))
00207 return expr;
00208
00209 if (TREE_CODE (expr) != SSA_NAME)
00210 return NULL_TREE;
00211
00212
00213 at_bb = bb_for_stmt (at);
00214 call_bb = bb_for_stmt (bsi_stmt (bsi));
00215 for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
00216 bb->aux = &bb->aux;
00217 bb->aux = &bb->aux;
00218
00219 while (1)
00220 {
00221 at = SSA_NAME_DEF_STMT (expr);
00222 bb = bb_for_stmt (at);
00223
00224
00225 if (!bb || !bb->aux)
00226 break;
00227
00228 if (bb == call_bb)
00229 {
00230 for (; !bsi_end_p (bsi); bsi_next (&bsi))
00231 if (bsi_stmt (bsi) == at)
00232 break;
00233
00234 if (!bsi_end_p (bsi))
00235 expr = NULL_TREE;
00236 break;
00237 }
00238
00239 if (TREE_CODE (at) != PHI_NODE)
00240 {
00241 expr = NULL_TREE;
00242 break;
00243 }
00244
00245 FOR_EACH_EDGE (e, ei, bb->preds)
00246 if (e->src->aux)
00247 break;
00248 gcc_assert (e);
00249
00250 expr = PHI_ARG_DEF_FROM_EDGE (at, e);
00251 if (TREE_CODE (expr) != SSA_NAME)
00252 {
00253
00254 break;
00255 }
00256 }
00257
00258
00259 for (bb = call_bb; bb != at_bb; bb = single_succ (bb))
00260 bb->aux = NULL;
00261 bb->aux = NULL;
00262
00263 return expr;
00264 }
00265
00266
00267
00268
00269
00270 static bool
00271 process_assignment (tree ass, tree stmt, block_stmt_iterator call, tree *m,
00272 tree *a, tree *ass_var)
00273 {
00274 tree op0, op1, non_ass_var;
00275 tree dest = TREE_OPERAND (ass, 0);
00276 tree src = TREE_OPERAND (ass, 1);
00277 enum tree_code code = TREE_CODE (src);
00278 tree src_var = src;
00279
00280
00281
00282
00283
00284 STRIP_NOPS (src_var);
00285 if (TREE_CODE (src_var) == SSA_NAME)
00286 {
00287 if (src_var != *ass_var)
00288 return false;
00289
00290 *ass_var = dest;
00291 return true;
00292 }
00293
00294 if (TREE_CODE_CLASS (code) != tcc_binary)
00295 return false;
00296
00297
00298
00299
00300 if (!flag_unsafe_math_optimizations)
00301 if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
00302 return false;
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 op0 = TREE_OPERAND (src, 0);
00315 op1 = TREE_OPERAND (src, 1);
00316
00317 if (op0 == *ass_var
00318 && (non_ass_var = independent_of_stmt_p (op1, stmt, call)))
00319 ;
00320 else if (op1 == *ass_var
00321 && (non_ass_var = independent_of_stmt_p (op0, stmt, call)))
00322 ;
00323 else
00324 return false;
00325
00326 switch (code)
00327 {
00328 case PLUS_EXPR:
00329
00330
00331
00332
00333 if (*a)
00334 return false;
00335 *a = non_ass_var;
00336 *ass_var = dest;
00337 return true;
00338
00339 case MULT_EXPR:
00340
00341
00342
00343 if (*a || *m)
00344 return false;
00345 *m = non_ass_var;
00346 *ass_var = dest;
00347 return true;
00348
00349
00350
00351 default:
00352 return false;
00353 }
00354 }
00355
00356
00357
00358 static tree
00359 propagate_through_phis (tree var, edge e)
00360 {
00361 basic_block dest = e->dest;
00362 tree phi;
00363
00364 for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00365 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var)
00366 return PHI_RESULT (phi);
00367
00368 return var;
00369 }
00370
00371
00372
00373
00374 static void
00375 find_tail_calls (basic_block bb, struct tailcall **ret)
00376 {
00377 tree ass_var, ret_var, stmt, func, param, args, call = NULL_TREE;
00378 block_stmt_iterator bsi, absi;
00379 bool tail_recursion;
00380 struct tailcall *nw;
00381 edge e;
00382 tree m, a;
00383 basic_block abb;
00384 stmt_ann_t ann;
00385
00386 if (!single_succ_p (bb))
00387 return;
00388
00389 for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
00390 {
00391 stmt = bsi_stmt (bsi);
00392
00393
00394 if (TREE_CODE (stmt) == LABEL_EXPR)
00395 continue;
00396
00397
00398 if (TREE_CODE (stmt) == MODIFY_EXPR)
00399 {
00400 ass_var = TREE_OPERAND (stmt, 0);
00401 call = TREE_OPERAND (stmt, 1);
00402 if (TREE_CODE (call) == WITH_SIZE_EXPR)
00403 call = TREE_OPERAND (call, 0);
00404 }
00405 else
00406 {
00407 ass_var = NULL_TREE;
00408 call = stmt;
00409 }
00410
00411 if (TREE_CODE (call) == CALL_EXPR)
00412 break;
00413
00414
00415 ann = stmt_ann (stmt);
00416 if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
00417 || ann->has_volatile_ops)
00418 return;
00419 }
00420
00421 if (bsi_end_p (bsi))
00422 {
00423 edge_iterator ei;
00424
00425 FOR_EACH_EDGE (e, ei, bb->preds)
00426 find_tail_calls (e->src, ret);
00427
00428 return;
00429 }
00430
00431
00432 tail_recursion = false;
00433 func = get_callee_fndecl (call);
00434 if (func == current_function_decl)
00435 {
00436 for (param = DECL_ARGUMENTS (func), args = TREE_OPERAND (call, 1);
00437 param && args;
00438 param = TREE_CHAIN (param), args = TREE_CHAIN (args))
00439 {
00440 tree arg = TREE_VALUE (args);
00441 if (param != arg)
00442 {
00443
00444
00445
00446
00447 if (!is_gimple_reg_type (TREE_TYPE (param))
00448 || !lang_hooks.types_compatible_p (TREE_TYPE (param),
00449 TREE_TYPE (arg)))
00450 break;
00451
00452
00453
00454
00455
00456
00457
00458
00459 if (!is_gimple_reg (param))
00460 break;
00461 }
00462 }
00463 if (!args && !param)
00464 tail_recursion = true;
00465 }
00466
00467
00468
00469
00470
00471 m = NULL_TREE;
00472 a = NULL_TREE;
00473
00474 abb = bb;
00475 absi = bsi;
00476 while (1)
00477 {
00478 bsi_next (&absi);
00479
00480 while (bsi_end_p (absi))
00481 {
00482 ass_var = propagate_through_phis (ass_var, single_succ_edge (abb));
00483 abb = single_succ (abb);
00484 absi = bsi_start (abb);
00485 }
00486
00487 stmt = bsi_stmt (absi);
00488
00489 if (TREE_CODE (stmt) == LABEL_EXPR)
00490 continue;
00491
00492 if (TREE_CODE (stmt) == RETURN_EXPR)
00493 break;
00494
00495 if (TREE_CODE (stmt) != MODIFY_EXPR)
00496 return;
00497
00498 if (!process_assignment (stmt, stmt, bsi, &m, &a, &ass_var))
00499 return;
00500 }
00501
00502
00503 ret_var = TREE_OPERAND (stmt, 0);
00504 if (ret_var
00505 && TREE_CODE (ret_var) == MODIFY_EXPR)
00506 {
00507 tree ret_op = TREE_OPERAND (ret_var, 1);
00508 STRIP_NOPS (ret_op);
00509 if (!tail_recursion
00510 && TREE_CODE (ret_op) != SSA_NAME)
00511 return;
00512
00513 if (!process_assignment (ret_var, stmt, bsi, &m, &a, &ass_var))
00514 return;
00515 ret_var = TREE_OPERAND (ret_var, 0);
00516 }
00517
00518
00519
00520 if (ret_var
00521 && (ret_var != ass_var))
00522 return;
00523
00524
00525
00526 if (!tail_recursion && (m || a))
00527 return;
00528
00529 nw = XNEW (struct tailcall);
00530
00531 nw->call_block = bb;
00532 nw->call_bsi = bsi;
00533
00534 nw->tail_recursion = tail_recursion;
00535
00536 nw->mult = m;
00537 nw->add = a;
00538
00539 nw->next = *ret;
00540 *ret = nw;
00541 }
00542
00543
00544
00545
00546 static void
00547 adjust_accumulator_values (block_stmt_iterator bsi, tree m, tree a, edge back)
00548 {
00549 tree stmt, var, phi, tmp;
00550 tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
00551 tree a_acc_arg = a_acc, m_acc_arg = m_acc;
00552
00553 if (a)
00554 {
00555 if (m_acc)
00556 {
00557 if (integer_onep (a))
00558 var = m_acc;
00559 else
00560 {
00561 stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
00562 build2 (MULT_EXPR, ret_type, m_acc, a));
00563
00564 tmp = create_tmp_var (ret_type, "acc_tmp");
00565 add_referenced_var (tmp);
00566
00567 var = make_ssa_name (tmp, stmt);
00568 TREE_OPERAND (stmt, 0) = var;
00569 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
00570 }
00571 }
00572 else
00573 var = a;
00574
00575 stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
00576 build2 (PLUS_EXPR, ret_type, a_acc, var));
00577 var = make_ssa_name (SSA_NAME_VAR (a_acc), stmt);
00578 TREE_OPERAND (stmt, 0) = var;
00579 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
00580 a_acc_arg = var;
00581 }
00582
00583 if (m)
00584 {
00585 stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
00586 build2 (MULT_EXPR, ret_type, m_acc, m));
00587 var = make_ssa_name (SSA_NAME_VAR (m_acc), stmt);
00588 TREE_OPERAND (stmt, 0) = var;
00589 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
00590 m_acc_arg = var;
00591 }
00592
00593 if (a_acc)
00594 {
00595 for (phi = phi_nodes (back->dest); phi; phi = PHI_CHAIN (phi))
00596 if (PHI_RESULT (phi) == a_acc)
00597 break;
00598
00599 add_phi_arg (phi, a_acc_arg, back);
00600 }
00601
00602 if (m_acc)
00603 {
00604 for (phi = phi_nodes (back->dest); phi; phi = PHI_CHAIN (phi))
00605 if (PHI_RESULT (phi) == m_acc)
00606 break;
00607
00608 add_phi_arg (phi, m_acc_arg, back);
00609 }
00610 }
00611
00612
00613
00614
00615 static void
00616 adjust_return_value (basic_block bb, tree m, tree a)
00617 {
00618 tree ret_stmt = last_stmt (bb), ret_var, var, stmt, tmp;
00619 tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
00620 block_stmt_iterator bsi = bsi_last (bb);
00621
00622 gcc_assert (TREE_CODE (ret_stmt) == RETURN_EXPR);
00623
00624 ret_var = TREE_OPERAND (ret_stmt, 0);
00625 if (!ret_var)
00626 return;
00627
00628 if (TREE_CODE (ret_var) == MODIFY_EXPR)
00629 {
00630 ret_var->common.ann = (tree_ann_t) stmt_ann (ret_stmt);
00631 bsi_replace (&bsi, ret_var, true);
00632 SSA_NAME_DEF_STMT (TREE_OPERAND (ret_var, 0)) = ret_var;
00633 ret_var = TREE_OPERAND (ret_var, 0);
00634 ret_stmt = build1 (RETURN_EXPR, TREE_TYPE (ret_stmt), ret_var);
00635 bsi_insert_after (&bsi, ret_stmt, BSI_NEW_STMT);
00636 }
00637
00638 if (m)
00639 {
00640 stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
00641 build2 (MULT_EXPR, ret_type, m_acc, ret_var));
00642
00643 tmp = create_tmp_var (ret_type, "acc_tmp");
00644 add_referenced_var (tmp);
00645
00646 var = make_ssa_name (tmp, stmt);
00647 TREE_OPERAND (stmt, 0) = var;
00648 bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
00649 }
00650 else
00651 var = ret_var;
00652
00653 if (a)
00654 {
00655 stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
00656 build2 (PLUS_EXPR, ret_type, a_acc, var));
00657
00658 tmp = create_tmp_var (ret_type, "acc_tmp");
00659 add_referenced_var (tmp);
00660
00661 var = make_ssa_name (tmp, stmt);
00662 TREE_OPERAND (stmt, 0) = var;
00663 bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
00664 }
00665
00666 TREE_OPERAND (ret_stmt, 0) = var;
00667 update_stmt (ret_stmt);
00668 }
00669
00670
00671
00672 static void
00673 decrease_profile (basic_block bb, gcov_type count, int frequency)
00674 {
00675 edge e;
00676 bb->count -= count;
00677 if (bb->count < 0)
00678 bb->count = 0;
00679 bb->frequency -= frequency;
00680 if (bb->frequency < 0)
00681 bb->frequency = 0;
00682 if (!single_succ_p (bb))
00683 {
00684 gcc_assert (!EDGE_COUNT (bb->succs));
00685 return;
00686 }
00687 e = single_succ_edge (bb);
00688 e->count -= count;
00689 if (e->count < 0)
00690 e->count = 0;
00691 }
00692
00693
00694
00695
00696 static bool
00697 arg_needs_copy_p (tree param)
00698 {
00699 tree def;
00700
00701 if (!is_gimple_reg (param) || !var_ann (param))
00702 return false;
00703
00704
00705 def = default_def (param);
00706 if (!def)
00707 return false;
00708
00709 return true;
00710 }
00711
00712
00713
00714
00715 static void
00716 eliminate_tail_call (struct tailcall *t)
00717 {
00718 tree param, stmt, args, rslt, call;
00719 basic_block bb, first;
00720 edge e;
00721 tree phi;
00722 block_stmt_iterator bsi;
00723 tree orig_stmt;
00724
00725 stmt = orig_stmt = bsi_stmt (t->call_bsi);
00726 bb = t->call_block;
00727
00728 if (dump_file && (dump_flags & TDF_DETAILS))
00729 {
00730 fprintf (dump_file, "Eliminated tail recursion in bb %d : ",
00731 bb->index);
00732 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00733 fprintf (dump_file, "\n");
00734 }
00735
00736 if (TREE_CODE (stmt) == MODIFY_EXPR)
00737 stmt = TREE_OPERAND (stmt, 1);
00738
00739 first = single_succ (ENTRY_BLOCK_PTR);
00740
00741
00742
00743
00744 bsi = t->call_bsi;
00745 bsi_next (&bsi);
00746 while (!bsi_end_p (bsi))
00747 {
00748 tree t = bsi_stmt (bsi);
00749
00750
00751 if (TREE_CODE (t) == RETURN_EXPR)
00752 break;
00753
00754 bsi_remove (&bsi, true);
00755 release_defs (t);
00756 }
00757
00758
00759 e = single_succ_edge (t->call_block);
00760 decrease_profile (EXIT_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
00761 decrease_profile (ENTRY_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
00762 if (e->dest != EXIT_BLOCK_PTR)
00763 decrease_profile (e->dest, e->count, EDGE_FREQUENCY (e));
00764
00765
00766 e = redirect_edge_and_branch (single_succ_edge (t->call_block), first);
00767 gcc_assert (e);
00768 PENDING_STMT (e) = NULL_TREE;
00769
00770
00771
00772 for (param = DECL_ARGUMENTS (current_function_decl),
00773 args = TREE_OPERAND (stmt, 1),
00774 phi = phi_nodes (first);
00775 param;
00776 param = TREE_CHAIN (param),
00777 args = TREE_CHAIN (args))
00778 {
00779 if (!arg_needs_copy_p (param))
00780 continue;
00781 gcc_assert (param == SSA_NAME_VAR (PHI_RESULT (phi)));
00782
00783 add_phi_arg (phi, TREE_VALUE (args), e);
00784 phi = PHI_CHAIN (phi);
00785 }
00786
00787
00788 adjust_accumulator_values (t->call_bsi, t->mult, t->add, e);
00789
00790 call = bsi_stmt (t->call_bsi);
00791 if (TREE_CODE (call) == MODIFY_EXPR)
00792 {
00793 rslt = TREE_OPERAND (call, 0);
00794
00795
00796
00797 SSA_NAME_DEF_STMT (rslt) = build_empty_stmt ();
00798 }
00799
00800 bsi_remove (&t->call_bsi, true);
00801 release_defs (call);
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 static void
00815 add_virtual_phis (void)
00816 {
00817 referenced_var_iterator rvi;
00818 tree var;
00819
00820
00821
00822
00823
00824
00825
00826
00827 FOR_EACH_REFERENCED_VAR (var, rvi)
00828 {
00829 if (!is_gimple_reg (var) && default_def (var) != NULL_TREE)
00830 mark_sym_for_renaming (var);
00831 }
00832
00833 update_ssa (TODO_update_ssa_only_virtuals);
00834 }
00835
00836
00837
00838
00839 static bool
00840 optimize_tail_call (struct tailcall *t, bool opt_tailcalls)
00841 {
00842 if (t->tail_recursion)
00843 {
00844 eliminate_tail_call (t);
00845 return true;
00846 }
00847
00848 if (opt_tailcalls)
00849 {
00850 tree stmt = bsi_stmt (t->call_bsi);
00851
00852 stmt = get_call_expr_in (stmt);
00853 CALL_EXPR_TAILCALL (stmt) = 1;
00854 if (dump_file && (dump_flags & TDF_DETAILS))
00855 {
00856 fprintf (dump_file, "Found tail call ");
00857 print_generic_expr (dump_file, stmt, dump_flags);
00858 fprintf (dump_file, " in bb %i\n", t->call_block->index);
00859 }
00860 }
00861
00862 return false;
00863 }
00864
00865
00866
00867
00868 static void
00869 tree_optimize_tail_calls_1 (bool opt_tailcalls)
00870 {
00871 edge e;
00872 bool phis_constructed = false;
00873 struct tailcall *tailcalls = NULL, *act, *next;
00874 bool changed = false;
00875 basic_block first = single_succ (ENTRY_BLOCK_PTR);
00876 tree stmt, param, ret_type, tmp, phi;
00877 edge_iterator ei;
00878
00879 if (!suitable_for_tail_opt_p ())
00880 return;
00881 if (opt_tailcalls)
00882 opt_tailcalls = suitable_for_tail_call_opt_p ();
00883
00884 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
00885 {
00886
00887
00888 stmt = last_stmt (e->src);
00889
00890 if (stmt
00891 && TREE_CODE (stmt) == RETURN_EXPR)
00892 find_tail_calls (e->src, &tailcalls);
00893 }
00894
00895
00896 a_acc = m_acc = NULL_TREE;
00897 for (act = tailcalls; act; act = act->next)
00898 {
00899 if (!act->tail_recursion)
00900 continue;
00901
00902 if (!phis_constructed)
00903 {
00904
00905 if (!single_pred_p (first))
00906 first = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
00907
00908
00909 for (param = DECL_ARGUMENTS (current_function_decl);
00910 param;
00911 param = TREE_CHAIN (param))
00912 if (arg_needs_copy_p (param))
00913 {
00914 tree name = default_def (param);
00915 tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
00916 tree phi;
00917
00918 set_default_def (param, new_name);
00919 phi = create_phi_node (name, first);
00920 SSA_NAME_DEF_STMT (name) = phi;
00921 add_phi_arg (phi, new_name, single_pred_edge (first));
00922 }
00923 phis_constructed = true;
00924 }
00925
00926 if (act->add && !a_acc)
00927 {
00928 ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
00929
00930 tmp = create_tmp_var (ret_type, "add_acc");
00931 add_referenced_var (tmp);
00932
00933 phi = create_phi_node (tmp, first);
00934 add_phi_arg (phi,
00935
00936
00937 fold_convert (ret_type, integer_zero_node),
00938 single_pred_edge (first));
00939 a_acc = PHI_RESULT (phi);
00940 }
00941
00942 if (act->mult && !m_acc)
00943 {
00944 ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
00945
00946 tmp = create_tmp_var (ret_type, "mult_acc");
00947 add_referenced_var (tmp);
00948
00949 phi = create_phi_node (tmp, first);
00950 add_phi_arg (phi,
00951
00952
00953 fold_convert (ret_type, integer_one_node),
00954 single_pred_edge (first));
00955 m_acc = PHI_RESULT (phi);
00956 }
00957 }
00958
00959
00960 if (phis_constructed)
00961 {
00962
00963
00964 set_phi_nodes (first, phi_reverse (phi_nodes (first)));
00965 }
00966
00967 for (; tailcalls; tailcalls = next)
00968 {
00969 next = tailcalls->next;
00970 changed |= optimize_tail_call (tailcalls, opt_tailcalls);
00971 free (tailcalls);
00972 }
00973
00974 if (a_acc || m_acc)
00975 {
00976
00977 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
00978 {
00979 stmt = last_stmt (e->src);
00980
00981 if (stmt
00982 && TREE_CODE (stmt) == RETURN_EXPR)
00983 adjust_return_value (e->src, m_acc, a_acc);
00984 }
00985 }
00986
00987 if (changed)
00988 {
00989 free_dominance_info (CDI_DOMINATORS);
00990 cleanup_tree_cfg ();
00991 }
00992
00993 if (phis_constructed)
00994 add_virtual_phis ();
00995 }
00996
00997 static unsigned int
00998 execute_tail_recursion (void)
00999 {
01000 tree_optimize_tail_calls_1 (false);
01001 return 0;
01002 }
01003
01004 static bool
01005 gate_tail_calls (void)
01006 {
01007 return flag_optimize_sibling_calls != 0;
01008 }
01009
01010 static unsigned int
01011 execute_tail_calls (void)
01012 {
01013 tree_optimize_tail_calls_1 (true);
01014 return 0;
01015 }
01016
01017 struct tree_opt_pass pass_tail_recursion =
01018 {
01019 "tailr",
01020 gate_tail_calls,
01021 execute_tail_recursion,
01022 NULL,
01023 NULL,
01024 0,
01025 0,
01026 PROP_cfg | PROP_ssa | PROP_alias,
01027 0,
01028 0,
01029 0,
01030 TODO_dump_func | TODO_verify_ssa,
01031 0
01032 };
01033
01034 struct tree_opt_pass pass_tail_calls =
01035 {
01036 "tailc",
01037 gate_tail_calls,
01038 execute_tail_calls,
01039 NULL,
01040 NULL,
01041 0,
01042 0,
01043 PROP_cfg | PROP_ssa | PROP_alias,
01044 0,
01045 0,
01046 0,
01047 TODO_dump_func | TODO_verify_ssa,
01048 0
01049 };