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