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
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "toplev.h"
00031 #include "tree.h"
00032 #include "tree-inline.h"
00033 #include "rtl.h"
00034 #include "expr.h"
00035 #include "flags.h"
00036 #include "params.h"
00037 #include "input.h"
00038 #include "insn-config.h"
00039 #include "integrate.h"
00040 #include "varray.h"
00041 #include "hashtab.h"
00042 #include "pointer-set.h"
00043 #include "splay-tree.h"
00044 #include "langhooks.h"
00045 #include "cgraph.h"
00046 #include "intl.h"
00047 #include "tree-mudflap.h"
00048 #include "tree-flow.h"
00049 #include "function.h"
00050 #include "diagnostic.h"
00051 #include "debug.h"
00052
00053
00054
00055 #include "tree-iterator.h"
00056 #include "tree-gimple.h"
00057
00058
00059
00060
00061
00062
00063 int flag_inline_trees = 0;
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 typedef struct inline_data
00080 {
00081
00082
00083
00084
00085
00086
00087 varray_type fns;
00088
00089
00090 unsigned first_inlined_fn;
00091
00092
00093
00094 tree ret_label;
00095
00096 tree retvar;
00097
00098
00099 splay_tree decl_map;
00100
00101
00102 int in_target_cleanup_p;
00103
00104
00105
00106
00107 bool cloning_p;
00108
00109 bool saving_p;
00110
00111
00112 htab_t tree_pruner;
00113
00114 struct cgraph_node *node;
00115
00116 struct cgraph_node *current_node;
00117
00118
00119
00120 tree_stmt_iterator tsi;
00121 } inline_data;
00122
00123
00124
00125
00126
00127
00128 #define INSNS_PER_STMT (10)
00129
00130 static tree copy_body_r (tree *, int *, void *);
00131 static tree copy_body (inline_data *);
00132 static tree expand_call_inline (tree *, int *, void *);
00133 static void expand_calls_inline (tree *, inline_data *);
00134 static bool inlinable_function_p (tree);
00135 static tree remap_decl (tree, inline_data *);
00136 static tree remap_type (tree, inline_data *);
00137 static tree initialize_inlined_parameters (inline_data *, tree,
00138 tree, tree, tree);
00139 static void remap_block (tree *, inline_data *);
00140 static tree remap_decls (tree, inline_data *);
00141 static void copy_bind_expr (tree *, int *, inline_data *);
00142 static tree mark_local_for_remap_r (tree *, int *, void *);
00143 static void unsave_expr_1 (tree);
00144 static tree unsave_r (tree *, int *, void *);
00145 static void declare_inline_vars (tree bind_expr, tree vars);
00146 static void remap_save_expr (tree *, void *, int *);
00147
00148
00149
00150
00151 static void
00152 insert_decl_map (inline_data *id, tree key, tree value)
00153 {
00154 splay_tree_insert (id->decl_map, (splay_tree_key) key,
00155 (splay_tree_value) value);
00156
00157
00158
00159 if (key != value)
00160 splay_tree_insert (id->decl_map, (splay_tree_key) value,
00161 (splay_tree_value) value);
00162 }
00163
00164
00165
00166
00167 static tree
00168 remap_decl (tree decl, inline_data *id)
00169 {
00170 splay_tree_node n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
00171 tree fn = VARRAY_TOP_TREE (id->fns);
00172
00173
00174
00175 if (!n)
00176 {
00177
00178 tree t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
00179
00180
00181
00182
00183 insert_decl_map (id, decl, t);
00184
00185
00186 TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
00187 if (TREE_CODE (t) == TYPE_DECL)
00188 DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
00189 else if (TREE_CODE (t) == PARM_DECL)
00190 DECL_ARG_TYPE_AS_WRITTEN (t)
00191 = remap_type (DECL_ARG_TYPE_AS_WRITTEN (t), id);
00192
00193
00194 walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
00195 walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
00196
00197
00198 if (TREE_CODE (t) == FIELD_DECL)
00199 {
00200 walk_tree (&DECL_FIELD_OFFSET (t), copy_body_r, id, NULL);
00201 if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE)
00202 walk_tree (&DECL_QUALIFIER (t), copy_body_r, id, NULL);
00203 }
00204
00205 #if 0
00206
00207 if (! DECL_NAME (t) && TREE_TYPE (t)
00208 && lang_hooks.tree_inlining.anon_aggr_type_p (TREE_TYPE (t)))
00209 {
00210
00211
00212 tree members = NULL;
00213 tree src;
00214
00215 for (src = DECL_ANON_UNION_ELEMS (t); src;
00216 src = TREE_CHAIN (src))
00217 {
00218 tree member = remap_decl (TREE_VALUE (src), id);
00219
00220 gcc_assert (!TREE_PURPOSE (src));
00221 members = tree_cons (NULL, member, members);
00222 }
00223 DECL_ANON_UNION_ELEMS (t) = nreverse (members);
00224 }
00225 #endif
00226
00227 return t;
00228 }
00229
00230 return unshare_expr ((tree) n->value);
00231 }
00232
00233 static tree
00234 remap_type (tree type, inline_data *id)
00235 {
00236 splay_tree_node node;
00237 tree new, t;
00238
00239 if (type == NULL)
00240 return type;
00241
00242
00243 node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
00244 if (node)
00245 return (tree) node->value;
00246
00247
00248
00249 if (! variably_modified_type_p (type, VARRAY_TOP_TREE (id->fns)))
00250 {
00251 insert_decl_map (id, type, type);
00252 return type;
00253 }
00254
00255
00256
00257
00258 if (TREE_CODE (type) == POINTER_TYPE)
00259 {
00260 new = build_pointer_type_for_mode (remap_type (TREE_TYPE (type), id),
00261 TYPE_MODE (type),
00262 TYPE_REF_CAN_ALIAS_ALL (type));
00263 insert_decl_map (id, type, new);
00264 return new;
00265 }
00266 else if (TREE_CODE (type) == REFERENCE_TYPE)
00267 {
00268 new = build_reference_type_for_mode (remap_type (TREE_TYPE (type), id),
00269 TYPE_MODE (type),
00270 TYPE_REF_CAN_ALIAS_ALL (type));
00271 insert_decl_map (id, type, new);
00272 return new;
00273 }
00274 else
00275 new = copy_node (type);
00276
00277 insert_decl_map (id, type, new);
00278
00279
00280
00281 t = TYPE_MAIN_VARIANT (type);
00282 if (type != t)
00283 {
00284 t = remap_type (t, id);
00285 TYPE_MAIN_VARIANT (new) = t;
00286 TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t);
00287 TYPE_NEXT_VARIANT (t) = new;
00288 }
00289 else
00290 {
00291 TYPE_MAIN_VARIANT (new) = new;
00292 TYPE_NEXT_VARIANT (new) = NULL;
00293 }
00294
00295 if (TYPE_STUB_DECL (type))
00296 TYPE_STUB_DECL (new) = remap_decl (TYPE_STUB_DECL (type), id);
00297
00298
00299 TYPE_POINTER_TO (new) = NULL;
00300 TYPE_REFERENCE_TO (new) = NULL;
00301
00302 switch (TREE_CODE (new))
00303 {
00304 case INTEGER_TYPE:
00305 case REAL_TYPE:
00306 case ENUMERAL_TYPE:
00307 case BOOLEAN_TYPE:
00308 case CHAR_TYPE:
00309 t = TYPE_MIN_VALUE (new);
00310 if (t && TREE_CODE (t) != INTEGER_CST)
00311 walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL);
00312
00313 t = TYPE_MAX_VALUE (new);
00314 if (t && TREE_CODE (t) != INTEGER_CST)
00315 walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL);
00316 return new;
00317
00318 case FUNCTION_TYPE:
00319 TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
00320 walk_tree (&TYPE_ARG_TYPES (new), copy_body_r, id, NULL);
00321 return new;
00322
00323 case ARRAY_TYPE:
00324 TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
00325 TYPE_DOMAIN (new) = remap_type (TYPE_DOMAIN (new), id);
00326 break;
00327
00328 case RECORD_TYPE:
00329 case UNION_TYPE:
00330 case QUAL_UNION_TYPE:
00331 walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL);
00332 break;
00333
00334 case FILE_TYPE:
00335 case OFFSET_TYPE:
00336 default:
00337
00338 gcc_unreachable ();
00339 }
00340
00341 walk_tree (&TYPE_SIZE (new), copy_body_r, id, NULL);
00342 walk_tree (&TYPE_SIZE_UNIT (new), copy_body_r, id, NULL);
00343
00344 return new;
00345 }
00346
00347 static tree
00348 remap_decls (tree decls, inline_data *id)
00349 {
00350 tree old_var;
00351 tree new_decls = NULL_TREE;
00352
00353
00354 for (old_var = decls; old_var; old_var = TREE_CHAIN (old_var))
00355 {
00356 tree new_var;
00357
00358
00359 new_var = remap_decl (old_var, id);
00360
00361
00362
00363
00364 if (!new_var || new_var == id->retvar)
00365 ;
00366 else
00367 {
00368 gcc_assert (DECL_P (new_var));
00369 TREE_CHAIN (new_var) = new_decls;
00370 new_decls = new_var;
00371 }
00372 }
00373
00374 return nreverse (new_decls);
00375 }
00376
00377
00378
00379
00380 static void
00381 remap_block (tree *block, inline_data *id)
00382 {
00383 tree old_block;
00384 tree new_block;
00385 tree fn;
00386
00387
00388 old_block = *block;
00389 new_block = make_node (BLOCK);
00390 TREE_USED (new_block) = TREE_USED (old_block);
00391 BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
00392 *block = new_block;
00393
00394
00395 BLOCK_VARS (new_block) = remap_decls (BLOCK_VARS (old_block), id);
00396
00397 fn = VARRAY_TREE (id->fns, 0);
00398 #if 1
00399
00400
00401 if (id->cloning_p)
00402
00403
00404
00405 lang_hooks.decls.insert_block (new_block);
00406 else
00407 {
00408
00409
00410
00411 tree *first_block;
00412 if (DECL_INITIAL (fn))
00413 first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
00414 else
00415 first_block = &DECL_INITIAL (fn);
00416 BLOCK_CHAIN (new_block) = *first_block;
00417 *first_block = new_block;
00418 }
00419 #endif
00420
00421 insert_decl_map (id, old_block, new_block);
00422 }
00423
00424 static void
00425 copy_statement_list (tree *tp)
00426 {
00427 tree_stmt_iterator oi, ni;
00428 tree new;
00429
00430 new = alloc_stmt_list ();
00431 ni = tsi_start (new);
00432 oi = tsi_start (*tp);
00433 *tp = new;
00434
00435 for (; !tsi_end_p (oi); tsi_next (&oi))
00436 tsi_link_after (&ni, tsi_stmt (oi), TSI_NEW_STMT);
00437 }
00438
00439 static void
00440 copy_bind_expr (tree *tp, int *walk_subtrees, inline_data *id)
00441 {
00442 tree block = BIND_EXPR_BLOCK (*tp);
00443
00444 copy_tree_r (tp, walk_subtrees, NULL);
00445 if (block)
00446 {
00447 remap_block (&block, id);
00448 BIND_EXPR_BLOCK (*tp) = block;
00449 }
00450
00451 if (BIND_EXPR_VARS (*tp))
00452
00453
00454 BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), id);
00455 }
00456
00457
00458
00459 static tree
00460 copy_body_r (tree *tp, int *walk_subtrees, void *data)
00461 {
00462 inline_data *id = (inline_data *) data;
00463 tree fn = VARRAY_TOP_TREE (id->fns);
00464
00465 #if 0
00466
00467
00468 if ((TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == LABEL_DECL)
00469 && DECL_NAMESPACE_SCOPE_P (*tp))
00470 gcc_assert (DECL_EXTERNAL (*tp) || TREE_STATIC (*tp));
00471 #endif
00472
00473
00474
00475 if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label)
00476 {
00477 tree return_stmt = *tp;
00478 tree goto_stmt;
00479
00480
00481 tree assignment = TREE_OPERAND (return_stmt, 0);
00482 goto_stmt = build1 (GOTO_EXPR, void_type_node, id->ret_label);
00483 TREE_USED (id->ret_label) = 1;
00484
00485
00486
00487
00488 if (assignment)
00489 {
00490
00491 if (TREE_CODE (assignment) == RESULT_DECL)
00492 gimplify_stmt (&assignment);
00493
00494 *tp = build (BIND_EXPR, void_type_node, NULL, NULL, NULL);
00495 append_to_statement_list (assignment, &BIND_EXPR_BODY (*tp));
00496 append_to_statement_list (goto_stmt, &BIND_EXPR_BODY (*tp));
00497 }
00498
00499 else
00500 *tp = goto_stmt;
00501 }
00502
00503
00504
00505
00506 else if (lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
00507 {
00508 tree new_decl;
00509
00510
00511 new_decl = remap_decl (*tp, id);
00512 gcc_assert (new_decl);
00513
00514 STRIP_TYPE_NOPS (new_decl);
00515 *tp = new_decl;
00516 *walk_subtrees = 0;
00517 }
00518 else if (TREE_CODE (*tp) == STATEMENT_LIST)
00519 copy_statement_list (tp);
00520 else if (TREE_CODE (*tp) == SAVE_EXPR)
00521 remap_save_expr (tp, id->decl_map, walk_subtrees);
00522 else if (TREE_CODE (*tp) == BIND_EXPR)
00523 copy_bind_expr (tp, walk_subtrees, id);
00524
00525 else if (TYPE_P (*tp))
00526 *tp = remap_type (*tp, id);
00527
00528
00529
00530 else if (TREE_CODE_CLASS (TREE_CODE (*tp)) == tcc_constant)
00531 {
00532 tree new_type = remap_type (TREE_TYPE (*tp), id);
00533
00534 if (new_type == TREE_TYPE (*tp))
00535 *walk_subtrees = 0;
00536
00537 else if (TREE_CODE (*tp) == INTEGER_CST)
00538 *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp),
00539 TREE_INT_CST_HIGH (*tp));
00540 else
00541 {
00542 *tp = copy_node (*tp);
00543 TREE_TYPE (*tp) = new_type;
00544 }
00545 }
00546
00547
00548
00549 else
00550 {
00551 tree old_node = *tp;
00552
00553 if (TREE_CODE (*tp) == MODIFY_EXPR
00554 && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
00555 && (lang_hooks.tree_inlining.auto_var_in_fn_p
00556 (TREE_OPERAND (*tp, 0), fn)))
00557 {
00558
00559
00560
00561 tree decl = TREE_OPERAND (*tp, 0), value;
00562 splay_tree_node n;
00563
00564 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
00565 if (n)
00566 {
00567 value = (tree) n->value;
00568 STRIP_TYPE_NOPS (value);
00569 if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
00570 {
00571 *tp = build_empty_stmt ();
00572 return copy_body_r (tp, walk_subtrees, data);
00573 }
00574 }
00575 }
00576 else if (TREE_CODE (*tp) == INDIRECT_REF)
00577 {
00578
00579
00580 tree decl = TREE_OPERAND (*tp, 0), value;
00581 splay_tree_node n;
00582
00583 n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
00584 if (n)
00585 {
00586 value = (tree) n->value;
00587 STRIP_NOPS (value);
00588 if (TREE_CODE (value) == ADDR_EXPR
00589 && (lang_hooks.types_compatible_p
00590 (TREE_TYPE (*tp), TREE_TYPE (TREE_OPERAND (value, 0)))))
00591 {
00592 *tp = TREE_OPERAND (value, 0);
00593 return copy_body_r (tp, walk_subtrees, data);
00594 }
00595 }
00596 }
00597
00598 copy_tree_r (tp, walk_subtrees, NULL);
00599
00600 if (TREE_CODE (*tp) == CALL_EXPR && id->node && get_callee_fndecl (*tp))
00601 {
00602 if (id->saving_p)
00603 {
00604 struct cgraph_node *node;
00605 struct cgraph_edge *edge;
00606
00607 for (node = id->node->next_clone; node; node = node->next_clone)
00608 {
00609 edge = cgraph_edge (node, old_node);
00610 gcc_assert (edge);
00611 edge->call_expr = *tp;
00612 }
00613 }
00614 else
00615 {
00616 struct cgraph_edge *edge
00617 = cgraph_edge (id->current_node, old_node);
00618
00619 if (edge)
00620 cgraph_clone_edge (edge, id->node, *tp);
00621 }
00622 }
00623
00624 TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
00625
00626
00627
00628 if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
00629 {
00630 TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3);
00631 TREE_OPERAND (*tp, 3) = NULL_TREE;
00632 }
00633
00634
00635
00636
00637 else if (TREE_CODE (*tp) == ADDR_EXPR)
00638 {
00639 walk_tree (&TREE_OPERAND (*tp, 0), copy_body_r, id, NULL);
00640 recompute_tree_invarant_for_addr_expr (*tp);
00641 *walk_subtrees = 0;
00642 }
00643 }
00644
00645
00646 return NULL_TREE;
00647 }
00648
00649
00650
00651
00652 static tree
00653 copy_body (inline_data *id)
00654 {
00655 tree body;
00656 tree fndecl = VARRAY_TOP_TREE (id->fns);
00657
00658 if (fndecl == current_function_decl
00659 && cfun->saved_tree)
00660 body = cfun->saved_tree;
00661 else
00662 body = DECL_SAVED_TREE (fndecl);
00663 walk_tree (&body, copy_body_r, id, NULL);
00664
00665 return body;
00666 }
00667
00668
00669
00670
00671 static bool
00672 self_inlining_addr_expr (tree value, tree fn)
00673 {
00674 tree var;
00675
00676 if (TREE_CODE (value) != ADDR_EXPR)
00677 return false;
00678
00679 var = get_base_address (TREE_OPERAND (value, 0));
00680
00681 return var && lang_hooks.tree_inlining.auto_var_in_fn_p (var, fn);
00682 }
00683
00684 static void
00685 setup_one_parameter (inline_data *id, tree p, tree value, tree fn,
00686 tree *init_stmts, tree *vars, bool *gimplify_init_stmts_p)
00687 {
00688 tree init_stmt;
00689 tree var;
00690
00691
00692
00693
00694 if (TREE_READONLY (p)
00695 && !TREE_ADDRESSABLE (p)
00696 && value && !TREE_SIDE_EFFECTS (value))
00697 {
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 if (is_gimple_min_invariant (value)
00708 && lang_hooks.types_compatible_p (TREE_TYPE (value), TREE_TYPE (p))
00709
00710
00711
00712
00713
00714 && ! self_inlining_addr_expr (value, fn))
00715 {
00716 insert_decl_map (id, p, value);
00717 return;
00718 }
00719 }
00720
00721
00722
00723
00724 var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
00725
00726
00727
00728
00729 insert_decl_map (id, p, var);
00730
00731
00732 TREE_CHAIN (var) = *vars;
00733 *vars = var;
00734
00735
00736 DECL_SEEN_IN_BIND_EXPR_P (var) = 1;
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
00748 TREE_READONLY (var) = 0;
00749
00750
00751
00752 if (value)
00753 {
00754 tree rhs = fold_convert (TREE_TYPE (var), value);
00755
00756 if (rhs == error_mark_node)
00757 return;
00758
00759
00760
00761 init_stmt = build (MODIFY_EXPR, TREE_TYPE (var), var, rhs);
00762 append_to_statement_list (init_stmt, init_stmts);
00763
00764
00765
00766
00767
00768
00769 if (!is_gimple_val (rhs)
00770 && (!is_gimple_cast (rhs)
00771 || !is_gimple_val (TREE_OPERAND (rhs, 0))))
00772 *gimplify_init_stmts_p = true;
00773 }
00774 }
00775
00776
00777
00778
00779 static tree
00780 initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
00781 tree fn, tree bind_expr)
00782 {
00783 tree init_stmts = NULL_TREE;
00784 tree parms;
00785 tree a;
00786 tree p;
00787 tree vars = NULL_TREE;
00788 bool gimplify_init_stmts_p = false;
00789 int argnum = 0;
00790
00791
00792 parms = DECL_ARGUMENTS (fn);
00793 if (fn == current_function_decl)
00794 parms = cfun->saved_args;
00795
00796
00797
00798 for (p = parms, a = args; p;
00799 a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
00800 {
00801 tree value;
00802
00803 ++argnum;
00804
00805
00806 value = lang_hooks.tree_inlining.convert_parm_for_inlining
00807 (p, a ? TREE_VALUE (a) : NULL_TREE, fn, argnum);
00808
00809 setup_one_parameter (id, p, value, fn, &init_stmts, &vars,
00810 &gimplify_init_stmts_p);
00811 }
00812
00813
00814 for (; a; a = TREE_CHAIN (a))
00815 {
00816 tree value = TREE_VALUE (a);
00817 append_to_statement_list (value, &init_stmts);
00818 }
00819
00820
00821 p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
00822 if (fn == current_function_decl)
00823 p = DECL_STRUCT_FUNCTION (fn)->saved_static_chain_decl;
00824 if (p)
00825 {
00826
00827 gcc_assert (static_chain);
00828
00829 setup_one_parameter (id, p, static_chain, fn, &init_stmts, &vars,
00830 &gimplify_init_stmts_p);
00831 }
00832
00833 if (gimplify_init_stmts_p)
00834 gimplify_body (&init_stmts, current_function_decl, false);
00835
00836 declare_inline_vars (bind_expr, vars);
00837 return init_stmts;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 static tree
00850 declare_return_variable (inline_data *id, tree return_slot_addr,
00851 tree modify_dest, tree *use_p)
00852 {
00853 tree callee = VARRAY_TOP_TREE (id->fns);
00854 tree caller = VARRAY_TREE (id->fns, 0);
00855 tree result = DECL_RESULT (callee);
00856 tree callee_type = TREE_TYPE (result);
00857 tree caller_type = TREE_TYPE (TREE_TYPE (callee));
00858 tree var, use;
00859
00860
00861
00862 if (!result || VOID_TYPE_P (callee_type))
00863 {
00864 *use_p = NULL_TREE;
00865 return NULL_TREE;
00866 }
00867
00868
00869
00870 if (return_slot_addr)
00871 {
00872
00873
00874 gcc_assert (!modify_dest);
00875 if (DECL_BY_REFERENCE (result))
00876 var = return_slot_addr;
00877 else
00878 var = build_fold_indirect_ref (return_slot_addr);
00879 use = NULL;
00880 goto done;
00881 }
00882
00883
00884 gcc_assert (!TREE_ADDRESSABLE (callee_type));
00885
00886
00887 if (modify_dest)
00888 {
00889 bool use_it = false;
00890
00891
00892 if (!lang_hooks.types_compatible_p (caller_type, callee_type))
00893 use_it = false;
00894
00895
00896
00897
00898 else if (TREE_CODE (TYPE_SIZE_UNIT (caller_type)) != INTEGER_CST)
00899 use_it = true;
00900
00901
00902
00903
00904 else if (!TREE_STATIC (modify_dest)
00905 && !TREE_ADDRESSABLE (modify_dest)
00906 && !TREE_ADDRESSABLE (result))
00907 use_it = true;
00908
00909 if (use_it)
00910 {
00911 var = modify_dest;
00912 use = NULL;
00913 goto done;
00914 }
00915 }
00916
00917 gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) == INTEGER_CST);
00918
00919 var = copy_decl_for_inlining (result, callee, caller);
00920 DECL_SEEN_IN_BIND_EXPR_P (var) = 1;
00921 DECL_STRUCT_FUNCTION (caller)->unexpanded_var_list
00922 = tree_cons (NULL_TREE, var,
00923 DECL_STRUCT_FUNCTION (caller)->unexpanded_var_list);
00924
00925
00926
00927 TREE_NO_WARNING (var) = 1;
00928
00929
00930
00931 use = var;
00932 if (!lang_hooks.types_compatible_p (TREE_TYPE (var), caller_type))
00933 use = fold_convert (caller_type, var);
00934
00935 done:
00936
00937
00938
00939 insert_decl_map (id, result, var);
00940
00941
00942 id->retvar = var;
00943
00944 *use_p = use;
00945 return var;
00946 }
00947
00948
00949
00950 bool
00951 tree_inlinable_function_p (tree fn)
00952 {
00953 return inlinable_function_p (fn);
00954 }
00955
00956 static const char *inline_forbidden_reason;
00957
00958 static tree
00959 inline_forbidden_p_1 (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
00960 void *fnp)
00961 {
00962 tree node = *nodep;
00963 tree fn = (tree) fnp;
00964 tree t;
00965
00966 switch (TREE_CODE (node))
00967 {
00968 case CALL_EXPR:
00969
00970
00971
00972
00973
00974 if (alloca_call_p (node)
00975 && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
00976 {
00977 inline_forbidden_reason
00978 = G_("%Jfunction %qF can never be inlined because it uses "
00979 "alloca (override using the always_inline attribute)");
00980 return node;
00981 }
00982 t = get_callee_fndecl (node);
00983 if (! t)
00984 break;
00985
00986
00987 if (setjmp_call_p (t))
00988 {
00989 inline_forbidden_reason
00990 = G_("%Jfunction %qF can never be inlined because it uses setjmp");
00991 return node;
00992 }
00993
00994 if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL)
00995 switch (DECL_FUNCTION_CODE (t))
00996 {
00997
00998
00999 case BUILT_IN_VA_START:
01000 case BUILT_IN_STDARG_START:
01001 case BUILT_IN_NEXT_ARG:
01002 case BUILT_IN_VA_END:
01003 inline_forbidden_reason
01004 = G_("%Jfunction %qF can never be inlined because it "
01005 "uses variable argument lists");
01006 return node;
01007
01008 case BUILT_IN_LONGJMP:
01009
01010
01011
01012
01013
01014 inline_forbidden_reason
01015 = G_("%Jfunction %qF can never be inlined because "
01016 "it uses setjmp-longjmp exception handling");
01017 return node;
01018
01019 case BUILT_IN_NONLOCAL_GOTO:
01020
01021 inline_forbidden_reason
01022 = G_("%Jfunction %qF can never be inlined because "
01023 "it uses non-local goto");
01024 return node;
01025
01026 case BUILT_IN_RETURN:
01027 case BUILT_IN_APPLY_ARGS:
01028
01029
01030
01031
01032 inline_forbidden_reason
01033 = G_("%Jfunction %qF can never be inlined because "
01034 "it uses __builtin_return or __builtin_apply_args");
01035 return node;
01036
01037 default:
01038 break;
01039 }
01040 break;
01041
01042 case GOTO_EXPR:
01043 t = TREE_OPERAND (node, 0);
01044
01045
01046
01047
01048
01049 if (TREE_CODE (t) != LABEL_DECL)
01050 {
01051 inline_forbidden_reason
01052 = G_("%Jfunction %qF can never be inlined "
01053 "because it contains a computed goto");
01054 return node;
01055 }
01056 break;
01057
01058 case LABEL_EXPR:
01059 t = TREE_OPERAND (node, 0);
01060 if (DECL_NONLOCAL (t))
01061 {
01062
01063
01064
01065 inline_forbidden_reason
01066 = G_("%Jfunction %qF can never be inlined "
01067 "because it receives a non-local goto");
01068 return node;
01069 }
01070 break;
01071
01072 case RECORD_TYPE:
01073 case UNION_TYPE:
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t))
01088 if (variably_modified_type_p (TREE_TYPE (t), NULL))
01089 {
01090 inline_forbidden_reason
01091 = G_("%Jfunction %qF can never be inlined "
01092 "because it uses variable sized variables");
01093 return node;
01094 }
01095
01096 default:
01097 break;
01098 }
01099
01100 return NULL_TREE;
01101 }
01102
01103
01104 static tree
01105 inline_forbidden_p (tree fndecl)
01106 {
01107 location_t saved_loc = input_location;
01108 tree ret = walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
01109 inline_forbidden_p_1, fndecl);
01110
01111 input_location = saved_loc;
01112 return ret;
01113 }
01114
01115
01116
01117
01118 static bool
01119 inlinable_function_p (tree fn)
01120 {
01121 bool inlinable = true;
01122
01123
01124
01125 if (DECL_UNINLINABLE (fn))
01126 return false;
01127
01128
01129
01130
01131
01132
01133 inlinable = !lang_hooks.tree_inlining.cannot_inline_tree_fn (&fn);
01134
01135
01136
01137
01138 if (!DECL_SAVED_TREE (fn))
01139 return false;
01140
01141
01142 else if (!flag_inline_trees)
01143 inlinable = false;
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 else if (!DECL_INLINE (fn) && !flag_unit_at_a_time)
01157 inlinable = false;
01158
01159 else if (inline_forbidden_p (fn))
01160 {
01161
01162
01163
01164
01165
01166
01167
01168
01169 bool do_warning = (warn_inline
01170 && DECL_INLINE (fn)
01171 && DECL_DECLARED_INLINE_P (fn)
01172 && !DECL_IN_SYSTEM_HEADER (fn));
01173
01174 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
01175 sorry (inline_forbidden_reason, fn, fn);
01176 else if (do_warning)
01177 warning (inline_forbidden_reason, fn, fn);
01178
01179 inlinable = false;
01180 }
01181
01182
01183 DECL_UNINLINABLE (fn) = !inlinable;
01184
01185 return inlinable;
01186 }
01187
01188
01189
01190
01191 int
01192 estimate_move_cost (tree type)
01193 {
01194 HOST_WIDE_INT size;
01195
01196 size = int_size_in_bytes (type);
01197
01198 if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
01199
01200 return 4;
01201 else
01202 return ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
01203 }
01204
01205
01206
01207
01208 static tree
01209 estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
01210 {
01211 int *count = data;
01212 tree x = *tp;
01213
01214 if (IS_TYPE_OR_DECL_P (x))
01215 {
01216 *walk_subtrees = 0;
01217 return NULL;
01218 }
01219
01220
01221
01222 else if (CONSTANT_CLASS_P (x) || REFERENCE_CLASS_P (x))
01223 return NULL;
01224
01225 switch (TREE_CODE (x))
01226 {
01227
01228 case TREE_LIST:
01229 case TREE_VEC:
01230 case BLOCK:
01231 case COMPONENT_REF:
01232 case BIT_FIELD_REF:
01233 case INDIRECT_REF:
01234 case ALIGN_INDIRECT_REF:
01235 case MISALIGNED_INDIRECT_REF:
01236 case ARRAY_REF:
01237 case ARRAY_RANGE_REF:
01238 case OBJ_TYPE_REF:
01239 case EXC_PTR_EXPR:
01240 case FILTER_EXPR:
01241 case COMPOUND_EXPR:
01242 case BIND_EXPR:
01243 case WITH_CLEANUP_EXPR:
01244 case NOP_EXPR:
01245 case VIEW_CONVERT_EXPR:
01246 case SAVE_EXPR:
01247 case ADDR_EXPR:
01248 case COMPLEX_EXPR:
01249 case RANGE_EXPR:
01250 case CASE_LABEL_EXPR:
01251 case SSA_NAME:
01252 case CATCH_EXPR:
01253 case EH_FILTER_EXPR:
01254 case STATEMENT_LIST:
01255 case ERROR_MARK:
01256 case NON_LVALUE_EXPR:
01257 case FDESC_EXPR:
01258 case VA_ARG_EXPR:
01259 case TRY_CATCH_EXPR:
01260 case TRY_FINALLY_EXPR:
01261 case LABEL_EXPR:
01262 case GOTO_EXPR:
01263 case RETURN_EXPR:
01264 case EXIT_EXPR:
01265 case LOOP_EXPR:
01266 case PHI_NODE:
01267 case WITH_SIZE_EXPR:
01268 break;
01269
01270
01271
01272
01273
01274 case IDENTIFIER_NODE:
01275 case INTEGER_CST:
01276 case REAL_CST:
01277 case COMPLEX_CST:
01278 case VECTOR_CST:
01279 case STRING_CST:
01280 *walk_subtrees = 0;
01281 return NULL;
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 case INIT_EXPR:
01308 case MODIFY_EXPR:
01309
01310 if (TREE_CODE (TREE_OPERAND (x, 1)) == TARGET_EXPR)
01311 break;
01312
01313
01314 case TARGET_EXPR:
01315 x = TREE_OPERAND (x, 0);
01316
01317 if (is_gimple_reg (x))
01318 break;
01319
01320
01321 case CONSTRUCTOR:
01322 *count += estimate_move_cost (TREE_TYPE (x));
01323 break;
01324
01325
01326
01327 case COND_EXPR:
01328
01329 case PLUS_EXPR:
01330 case MINUS_EXPR:
01331 case MULT_EXPR:
01332
01333 case FIX_TRUNC_EXPR:
01334 case FIX_CEIL_EXPR:
01335 case FIX_FLOOR_EXPR:
01336 case FIX_ROUND_EXPR:
01337
01338 case NEGATE_EXPR:
01339 case FLOAT_EXPR:
01340 case MIN_EXPR:
01341 case MAX_EXPR:
01342 case ABS_EXPR:
01343
01344 case LSHIFT_EXPR:
01345 case RSHIFT_EXPR:
01346 case LROTATE_EXPR:
01347 case RROTATE_EXPR:
01348
01349 case BIT_IOR_EXPR:
01350 case BIT_XOR_EXPR:
01351 case BIT_AND_EXPR:
01352 case BIT_NOT_EXPR:
01353
01354 case TRUTH_ANDIF_EXPR:
01355 case TRUTH_ORIF_EXPR:
01356 case TRUTH_AND_EXPR:
01357 case TRUTH_OR_EXPR:
01358 case TRUTH_XOR_EXPR:
01359 case TRUTH_NOT_EXPR:
01360
01361 case LT_EXPR:
01362 case LE_EXPR:
01363 case GT_EXPR:
01364 case GE_EXPR:
01365 case EQ_EXPR:
01366 case NE_EXPR:
01367 case ORDERED_EXPR:
01368 case UNORDERED_EXPR:
01369
01370 case UNLT_EXPR:
01371 case UNLE_EXPR:
01372 case UNGT_EXPR:
01373 case UNGE_EXPR:
01374 case UNEQ_EXPR:
01375 case LTGT_EXPR:
01376
01377 case CONVERT_EXPR:
01378
01379 case CONJ_EXPR:
01380
01381 case PREDECREMENT_EXPR:
01382 case PREINCREMENT_EXPR:
01383 case POSTDECREMENT_EXPR:
01384 case POSTINCREMENT_EXPR:
01385
01386 case SWITCH_EXPR:
01387
01388 case ASM_EXPR:
01389
01390 case REALIGN_LOAD_EXPR:
01391
01392 case RESX_EXPR:
01393 *count += 1;
01394 break;
01395
01396
01397
01398 case TRUNC_DIV_EXPR:
01399 case CEIL_DIV_EXPR:
01400 case FLOOR_DIV_EXPR:
01401 case ROUND_DIV_EXPR:
01402 case EXACT_DIV_EXPR:
01403 case TRUNC_MOD_EXPR:
01404 case CEIL_MOD_EXPR:
01405 case FLOOR_MOD_EXPR:
01406 case ROUND_MOD_EXPR:
01407 case RDIV_EXPR:
01408 *count += 10;
01409 break;
01410 case CALL_EXPR:
01411 {
01412 tree decl = get_callee_fndecl (x);
01413 tree arg;
01414
01415 if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
01416 switch (DECL_FUNCTION_CODE (decl))
01417 {
01418 case BUILT_IN_CONSTANT_P:
01419 *walk_subtrees = 0;
01420 return NULL_TREE;
01421 case BUILT_IN_EXPECT:
01422 return NULL_TREE;
01423 default:
01424 break;
01425 }
01426
01427
01428
01429 if (!decl)
01430 {
01431 for (arg = TREE_OPERAND (x, 1); arg; arg = TREE_CHAIN (arg))
01432 *count += estimate_move_cost (TREE_TYPE (TREE_VALUE (arg)));
01433 }
01434 else
01435 {
01436 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
01437 *count += estimate_move_cost (TREE_TYPE (arg));
01438 }
01439
01440 *count += PARAM_VALUE (PARAM_INLINE_CALL_COST);
01441 break;
01442 }
01443 default:
01444 #ifdef KEY
01445
01446
01447
01448 if (flag_spin_file) {
01449 *count += 1;
01450 break;
01451 }
01452 #endif
01453
01454 gcc_unreachable ();
01455 }
01456 return NULL;
01457 }
01458
01459
01460
01461 int
01462 estimate_num_insns (tree expr)
01463 {
01464 int num = 0;
01465 walk_tree_without_duplicates (&expr, estimate_num_insns_1, &num);
01466 return num;
01467 }
01468
01469
01470
01471 static tree
01472 expand_call_inline (tree *tp, int *walk_subtrees, void *data)
01473 {
01474 inline_data *id;
01475 tree t;
01476 tree expr;
01477 tree stmt;
01478 tree use_retvar;
01479 tree decl;
01480 tree fn;
01481 tree arg_inits;
01482 tree *inlined_body;
01483 splay_tree st;
01484 tree args;
01485 tree return_slot_addr;
01486 tree modify_dest;
01487 location_t saved_location;
01488 struct cgraph_edge *edge;
01489 const char *reason;
01490
01491
01492 id = (inline_data *) data;
01493 t = *tp;
01494
01495
01496
01497 saved_location = input_location;
01498 if (EXPR_HAS_LOCATION (t))
01499 input_location = EXPR_LOCATION (t);
01500
01501
01502
01503 if (TREE_CODE (*tp) == TARGET_EXPR)
01504 {
01505 #if 0
01506 int i, len = TREE_CODE_LENGTH (TARGET_EXPR);
01507
01508
01509 *walk_subtrees = 0;
01510
01511
01512
01513
01514 for (i = 0; i < len; ++i)
01515 {
01516 if (i == 2)
01517 ++id->in_target_cleanup_p;
01518 walk_tree (&TREE_OPERAND (*tp, i), expand_call_inline, data,
01519 id->tree_pruner);
01520 if (i == 2)
01521 --id->in_target_cleanup_p;
01522 }
01523
01524 goto egress;
01525 #endif
01526 }
01527
01528 if (TYPE_P (t))
01529
01530
01531
01532 *walk_subtrees = 0;
01533
01534
01535 if (TREE_CODE (t) != CALL_EXPR)
01536 goto egress;
01537
01538
01539
01540 fn = get_callee_fndecl (t);
01541 if (!fn)
01542 goto egress;
01543
01544
01545 fn = cgraph_node (fn)->decl;
01546
01547
01548
01549
01550
01551
01552
01553
01554 if (! DECL_INITIAL (fn)
01555 && DECL_ABSTRACT_ORIGIN (fn)
01556 && DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn)))
01557 fn = DECL_ABSTRACT_ORIGIN (fn);
01558
01559
01560
01561 if (!id->current_node->analyzed)
01562 goto egress;
01563
01564 edge = cgraph_edge (id->current_node, t);
01565
01566
01567
01568 if (!edge)
01569 {
01570 struct cgraph_node *dest = cgraph_node (fn);
01571
01572
01573
01574
01575
01576 gcc_assert (dest->needed || !flag_unit_at_a_time);
01577 cgraph_create_edge (id->node, dest, t)->inline_failed
01578 = N_("originally indirect function call not considered for inlining");
01579 goto egress;
01580 }
01581
01582
01583
01584 if (!cgraph_inline_p (edge, &reason))
01585 {
01586 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
01587 {
01588 sorry ("%Jinlining failed in call to %qF: %s", fn, fn, reason);
01589 sorry ("called from here");
01590 }
01591 else if (warn_inline && DECL_DECLARED_INLINE_P (fn)
01592 && !DECL_IN_SYSTEM_HEADER (fn)
01593 && strlen (reason)
01594 && !lookup_attribute ("noinline", DECL_ATTRIBUTES (fn)))
01595 {
01596 warning ("%Jinlining failed in call to %qF: %s", fn, fn, reason);
01597 warning ("called from here");
01598 }
01599 goto egress;
01600 }
01601
01602 #ifdef ENABLE_CHECKING
01603 if (edge->callee->decl != id->node->decl)
01604 verify_cgraph_node (edge->callee);
01605 #endif
01606
01607 if (! lang_hooks.tree_inlining.start_inlining (fn))
01608 goto egress;
01609
01610
01611
01612
01613
01614 stmt = NULL;
01615 expr = build (BIND_EXPR, void_type_node, NULL_TREE,
01616 stmt, make_node (BLOCK));
01617 BLOCK_ABSTRACT_ORIGIN (BIND_EXPR_BLOCK (expr)) = fn;
01618
01619
01620
01621 st = id->decl_map;
01622 id->decl_map = splay_tree_new (splay_tree_compare_pointers,
01623 NULL, NULL);
01624
01625
01626 args = TREE_OPERAND (t, 1);
01627 return_slot_addr = NULL_TREE;
01628 if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (t))
01629 {
01630 return_slot_addr = TREE_VALUE (args);
01631 args = TREE_CHAIN (args);
01632 TREE_TYPE (expr) = void_type_node;
01633 }
01634
01635 arg_inits = initialize_inlined_parameters (id, args, TREE_OPERAND (t, 2),
01636 fn, expr);
01637 if (arg_inits)
01638 {
01639
01640
01641
01642
01643
01644
01645
01646 tree_stmt_iterator save_tsi;
01647
01648 save_tsi = id->tsi;
01649 expand_calls_inline (&arg_inits, id);
01650 id->tsi = save_tsi;
01651
01652
01653 append_to_statement_list (arg_inits, &BIND_EXPR_BODY (expr));
01654 }
01655
01656
01657
01658 VARRAY_PUSH_TREE (id->fns, fn);
01659
01660
01661
01662 id->ret_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
01663 DECL_ARTIFICIAL (id->ret_label) = 1;
01664 DECL_IGNORED_P (id->ret_label) = 1;
01665 DECL_CONTEXT (id->ret_label) = VARRAY_TREE (id->fns, 0);
01666 insert_decl_map (id, id->ret_label, id->ret_label);
01667
01668 gcc_assert (DECL_INITIAL (fn));
01669 gcc_assert (TREE_CODE (DECL_INITIAL (fn)) == BLOCK);
01670
01671
01672 modify_dest = tsi_stmt (id->tsi);
01673 if (TREE_CODE (modify_dest) == MODIFY_EXPR)
01674 {
01675 modify_dest = TREE_OPERAND (modify_dest, 0);
01676
01677
01678
01679
01680
01681
01682
01683 if (DECL_P (modify_dest))
01684 TREE_NO_WARNING (modify_dest) = 1;
01685 }
01686 else
01687 modify_dest = NULL;
01688
01689
01690 decl = declare_return_variable (id, return_slot_addr,
01691 modify_dest, &use_retvar);
01692
01693
01694
01695 {
01696 struct cgraph_node *old_node = id->current_node;
01697 tree copy;
01698
01699 id->current_node = edge->callee;
01700 copy = copy_body (id);
01701
01702
01703
01704
01705 if (warn_return_type
01706 && !TREE_NO_WARNING (fn)
01707 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
01708 && return_slot_addr == NULL_TREE
01709 && block_may_fallthru (copy)
01710 && !DECL_IN_SYSTEM_HEADER (fn))
01711 {
01712 warning ("control may reach end of non-void function %qD being inlined",
01713 fn);
01714 TREE_NO_WARNING (fn) = 1;
01715 }
01716
01717 append_to_statement_list (copy, &BIND_EXPR_BODY (expr));
01718 id->current_node = old_node;
01719 }
01720 inlined_body = &BIND_EXPR_BODY (expr);
01721
01722
01723
01724
01725 if (TREE_USED (id->ret_label))
01726 {
01727 tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label);
01728 append_to_statement_list (label, &BIND_EXPR_BODY (expr));
01729 }
01730
01731
01732 splay_tree_delete (id->decl_map);
01733 id->decl_map = st;
01734
01735
01736
01737
01738
01739 TREE_SIDE_EFFECTS (expr) = 1;
01740
01741 tsi_link_before (&id->tsi, expr, TSI_SAME_STMT);
01742
01743
01744
01745
01746
01747 if (!use_retvar || !modify_dest)
01748 *tsi_stmt_ptr (id->tsi) = build_empty_stmt ();
01749 else
01750 *tp = use_retvar;
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 recalculate_side_effects (expr);
01764
01765
01766
01767
01768
01769 (*debug_hooks->outlining_inline_function) (edge->callee->decl);
01770
01771
01772 cgraph_remove_node (edge->callee);
01773
01774
01775 expand_calls_inline (inlined_body, id);
01776 VARRAY_POP (id->fns);
01777
01778
01779 *walk_subtrees = 0;
01780
01781 lang_hooks.tree_inlining.end_inlining (fn);
01782
01783
01784 egress:
01785 input_location = saved_location;
01786 return NULL_TREE;
01787 }
01788
01789 static void
01790 expand_calls_inline (tree *stmt_p, inline_data *id)
01791 {
01792 tree stmt = *stmt_p;
01793 enum tree_code code = TREE_CODE (stmt);
01794 int dummy;
01795
01796 switch (code)
01797 {
01798 case STATEMENT_LIST:
01799 {
01800 tree_stmt_iterator i;
01801 tree new;
01802
01803 for (i = tsi_start (stmt); !tsi_end_p (i); )
01804 {
01805 id->tsi = i;
01806 expand_calls_inline (tsi_stmt_ptr (i), id);
01807
01808 new = tsi_stmt (i);
01809 if (TREE_CODE (new) == STATEMENT_LIST)
01810 {
01811 tsi_link_before (&i, new, TSI_SAME_STMT);
01812 tsi_delink (&i);
01813 }
01814 else
01815 tsi_next (&i);
01816 }
01817 }
01818 break;
01819
01820 case COND_EXPR:
01821 expand_calls_inline (&COND_EXPR_THEN (stmt), id);
01822 expand_calls_inline (&COND_EXPR_ELSE (stmt), id);
01823 break;
01824
01825 case CATCH_EXPR:
01826 expand_calls_inline (&CATCH_BODY (stmt), id);
01827 break;
01828
01829 case EH_FILTER_EXPR:
01830 expand_calls_inline (&EH_FILTER_FAILURE (stmt), id);
01831 break;
01832
01833 case TRY_CATCH_EXPR:
01834 case TRY_FINALLY_EXPR:
01835 expand_calls_inline (&TREE_OPERAND (stmt, 0), id);
01836 expand_calls_inline (&TREE_OPERAND (stmt, 1), id);
01837 break;
01838
01839 case BIND_EXPR:
01840 expand_calls_inline (&BIND_EXPR_BODY (stmt), id);
01841 break;
01842
01843 case COMPOUND_EXPR:
01844
01845 gcc_unreachable ();
01846
01847 case RETURN_EXPR:
01848 stmt_p = &TREE_OPERAND (stmt, 0);
01849 stmt = *stmt_p;
01850 if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
01851 break;
01852
01853
01854
01855 case MODIFY_EXPR:
01856 stmt_p = &TREE_OPERAND (stmt, 1);
01857 stmt = *stmt_p;
01858 if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
01859 {
01860 stmt_p = &TREE_OPERAND (stmt, 0);
01861 stmt = *stmt_p;
01862 }
01863 if (TREE_CODE (stmt) != CALL_EXPR)
01864 break;
01865
01866
01867
01868 case CALL_EXPR:
01869 expand_call_inline (stmt_p, &dummy, id);
01870 break;
01871
01872 default:
01873 break;
01874 }
01875 }
01876
01877
01878
01879 void
01880 optimize_inline_calls (tree fn)
01881 {
01882 inline_data id;
01883 tree prev_fn;
01884
01885
01886
01887
01888 if (errorcount || sorrycount)
01889 return;
01890
01891
01892 memset (&id, 0, sizeof (id));
01893
01894 id.current_node = id.node = cgraph_node (fn);
01895
01896 VARRAY_TREE_INIT (id.fns, 32, "fns");
01897 VARRAY_PUSH_TREE (id.fns, fn);
01898
01899 prev_fn = NULL_TREE;
01900 if (current_function_decl)
01901 {
01902 VARRAY_PUSH_TREE (id.fns, current_function_decl);
01903 prev_fn = current_function_decl;
01904 }
01905
01906 prev_fn = lang_hooks.tree_inlining.add_pending_fn_decls (&id.fns, prev_fn);
01907
01908
01909
01910 id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns);
01911
01912
01913
01914 id.tree_pruner = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
01915 expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
01916
01917
01918 htab_delete (id.tree_pruner);
01919
01920 #ifdef ENABLE_CHECKING
01921 {
01922 struct cgraph_edge *e;
01923
01924 verify_cgraph_node (id.node);
01925
01926
01927 for (e = id.node->callees; e; e = e->next_callee)
01928 gcc_assert (e->inline_failed);
01929 }
01930 #endif
01931 }
01932
01933
01934
01935
01936
01937 void
01938 clone_body (tree clone, tree fn, void *arg_map)
01939 {
01940 inline_data id;
01941
01942
01943
01944
01945 memset (&id, 0, sizeof (id));
01946 VARRAY_TREE_INIT (id.fns, 2, "fns");
01947 VARRAY_PUSH_TREE (id.fns, clone);
01948 VARRAY_PUSH_TREE (id.fns, fn);
01949 id.decl_map = (splay_tree)arg_map;
01950
01951
01952
01953 id.cloning_p = true;
01954
01955
01956 append_to_statement_list_force (copy_body (&id), &DECL_SAVED_TREE (clone));
01957 }
01958
01959
01960
01961
01962 tree
01963 save_body (tree fn, tree *arg_copy, tree *sc_copy)
01964 {
01965 inline_data id;
01966 tree body, *parg;
01967
01968 memset (&id, 0, sizeof (id));
01969 VARRAY_TREE_INIT (id.fns, 1, "fns");
01970 VARRAY_PUSH_TREE (id.fns, fn);
01971 id.node = cgraph_node (fn);
01972 id.saving_p = true;
01973 id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
01974 *arg_copy = DECL_ARGUMENTS (fn);
01975
01976 for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
01977 {
01978 tree new = copy_node (*parg);
01979
01980 lang_hooks.dup_lang_specific_decl (new);
01981 DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*parg);
01982 insert_decl_map (&id, *parg, new);
01983 TREE_CHAIN (new) = TREE_CHAIN (*parg);
01984 *parg = new;
01985 }
01986
01987 *sc_copy = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
01988 if (*sc_copy)
01989 {
01990 tree new = copy_node (*sc_copy);
01991
01992 lang_hooks.dup_lang_specific_decl (new);
01993 DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*sc_copy);
01994 insert_decl_map (&id, *sc_copy, new);
01995 TREE_CHAIN (new) = TREE_CHAIN (*sc_copy);
01996 *sc_copy = new;
01997 }
01998
01999 insert_decl_map (&id, DECL_RESULT (fn), DECL_RESULT (fn));
02000
02001
02002 body = copy_body (&id);
02003
02004
02005 splay_tree_delete (id.decl_map);
02006 return body;
02007 }
02008
02009 #define WALK_SUBTREE(NODE) \
02010 do \
02011 { \
02012 result = walk_tree (&(NODE), func, data, pset); \
02013 if (result) \
02014 return result; \
02015 } \
02016 while (0)
02017
02018
02019
02020
02021
02022 static tree
02023 walk_type_fields (tree type, walk_tree_fn func, void *data,
02024 struct pointer_set_t *pset)
02025 {
02026 tree result = NULL_TREE;
02027
02028 switch (TREE_CODE (type))
02029 {
02030 case POINTER_TYPE:
02031 case REFERENCE_TYPE:
02032
02033
02034
02035
02036
02037
02038
02039 if (POINTER_TYPE_P (TREE_TYPE (type))
02040 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (type)))
02041 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (TREE_TYPE (type))))
02042 && !pset)
02043 {
02044 result = walk_tree_without_duplicates (&TREE_TYPE (type),
02045 func, data);
02046 if (result)
02047 return result;
02048
02049 break;
02050 }
02051
02052
02053
02054 case COMPLEX_TYPE:
02055 WALK_SUBTREE (TREE_TYPE (type));
02056 break;
02057
02058 case METHOD_TYPE:
02059 WALK_SUBTREE (TYPE_METHOD_BASETYPE (type));
02060
02061
02062
02063 case FUNCTION_TYPE:
02064 WALK_SUBTREE (TREE_TYPE (type));
02065 {
02066 tree arg;
02067
02068
02069 for (arg = TYPE_ARG_TYPES (type); arg; arg = TREE_CHAIN (arg))
02070 WALK_SUBTREE (TREE_VALUE (arg));
02071 }
02072 break;
02073
02074 case ARRAY_TYPE:
02075
02076
02077 if (!POINTER_TYPE_P (TREE_TYPE (type))
02078 && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE)
02079 WALK_SUBTREE (TREE_TYPE (type));
02080 WALK_SUBTREE (TYPE_DOMAIN (type));
02081 break;
02082
02083 case BOOLEAN_TYPE:
02084 case ENUMERAL_TYPE:
02085 case INTEGER_TYPE:
02086 case CHAR_TYPE:
02087 case REAL_TYPE:
02088 WALK_SUBTREE (TYPE_MIN_VALUE (type));
02089 WALK_SUBTREE (TYPE_MAX_VALUE (type));
02090 break;
02091
02092 case OFFSET_TYPE:
02093 WALK_SUBTREE (TREE_TYPE (type));
02094 WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type));
02095 break;
02096
02097 default:
02098 break;
02099 }
02100
02101 return NULL_TREE;
02102 }
02103
02104
02105
02106
02107
02108
02109
02110 tree
02111 walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
02112 {
02113 enum tree_code code;
02114 int walk_subtrees;
02115 tree result;
02116
02117 #define WALK_SUBTREE_TAIL(NODE) \
02118 do \
02119 { \
02120 tp = & (NODE); \
02121 goto tail_recurse; \
02122 } \
02123 while (0)
02124
02125 tail_recurse:
02126
02127 if (!*tp)
02128 return NULL_TREE;
02129
02130
02131
02132 if (pset && pointer_set_insert (pset, *tp))
02133 return NULL_TREE;
02134
02135
02136 walk_subtrees = 1;
02137 result = (*func) (tp, &walk_subtrees, data);
02138
02139
02140 if (result)
02141 return result;
02142
02143 code = TREE_CODE (*tp);
02144
02145
02146
02147 if (!walk_subtrees)
02148 {
02149 if (code == TREE_LIST)
02150
02151 WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
02152 else
02153 return NULL_TREE;
02154 }
02155
02156 result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func,
02157 data, pset);
02158 if (result || ! walk_subtrees)
02159 return result;
02160
02161
02162
02163
02164
02165
02166
02167
02168 if (code == DECL_EXPR
02169 && TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL
02170 && TREE_CODE (TREE_TYPE (DECL_EXPR_DECL (*tp))) != ERROR_MARK)
02171 {
02172 tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
02173
02174
02175
02176
02177 result = (*func) (type_p, &walk_subtrees, data);
02178 if (result || !walk_subtrees)
02179 return NULL_TREE;
02180
02181 result = walk_type_fields (*type_p, func, data, pset);
02182 if (result)
02183 return result;
02184
02185 WALK_SUBTREE (TYPE_SIZE (*type_p));
02186 WALK_SUBTREE (TYPE_SIZE_UNIT (*type_p));
02187
02188
02189 if (TREE_CODE (*type_p) == RECORD_TYPE
02190 || TREE_CODE (*type_p) == UNION_TYPE
02191 || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
02192 {
02193 tree field;
02194
02195 for (field = TYPE_FIELDS (*type_p); field;
02196 field = TREE_CHAIN (field))
02197 {
02198
02199
02200
02201 if (TREE_CODE (field) != FIELD_DECL)
02202 continue;
02203
02204 WALK_SUBTREE (DECL_FIELD_OFFSET (field));
02205 WALK_SUBTREE (DECL_SIZE (field));
02206 WALK_SUBTREE (DECL_SIZE_UNIT (field));
02207 if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
02208 WALK_SUBTREE (DECL_QUALIFIER (field));
02209 }
02210 }
02211 }
02212
02213 else if (code != SAVE_EXPR
02214 && code != BIND_EXPR
02215 && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
02216 {
02217 int i, len;
02218
02219
02220 len = TREE_CODE_LENGTH (code);
02221
02222
02223 if (code == TARGET_EXPR
02224 && TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1))
02225 --len;
02226
02227
02228
02229 #ifdef DEBUG_WALK_TREE
02230 for (i = 0; i < len; ++i)
02231 WALK_SUBTREE (TREE_OPERAND (*tp, i));
02232 #else
02233 for (i = 0; i < len - 1; ++i)
02234 WALK_SUBTREE (TREE_OPERAND (*tp, i));
02235
02236 if (len)
02237 {
02238
02239 if (code != BIND_EXPR
02240 && !TREE_CHAIN (*tp))
02241 WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
02242 else
02243 WALK_SUBTREE (TREE_OPERAND (*tp, len - 1));
02244 }
02245 #endif
02246 }
02247
02248
02249 else if (TYPE_P (*tp))
02250 {
02251 result = walk_type_fields (*tp, func, data, pset);
02252 if (result)
02253 return result;
02254 }
02255 else
02256 {
02257
02258
02259 switch (code)
02260 {
02261 case ERROR_MARK:
02262 case IDENTIFIER_NODE:
02263 case INTEGER_CST:
02264 case REAL_CST:
02265 case VECTOR_CST:
02266 case STRING_CST:
02267 case BLOCK:
02268 case PLACEHOLDER_EXPR:
02269 case SSA_NAME:
02270 case FIELD_DECL:
02271 case RESULT_DECL:
02272
02273
02274 break;
02275
02276 case TREE_LIST:
02277 WALK_SUBTREE (TREE_VALUE (*tp));
02278 WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
02279 break;
02280
02281 case TREE_VEC:
02282 {
02283 int len = TREE_VEC_LENGTH (*tp);
02284
02285 if (len == 0)
02286 break;
02287
02288
02289 while (--len)
02290 WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
02291
02292
02293 WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
02294 }
02295
02296 case COMPLEX_CST:
02297 WALK_SUBTREE (TREE_REALPART (*tp));
02298 WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
02299
02300 case CONSTRUCTOR:
02301 WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
02302
02303 case SAVE_EXPR:
02304 WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
02305
02306 case BIND_EXPR:
02307 {
02308 tree decl;
02309 for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
02310 {
02311
02312
02313
02314
02315
02316 WALK_SUBTREE (DECL_INITIAL (decl));
02317 WALK_SUBTREE (DECL_SIZE (decl));
02318 WALK_SUBTREE (DECL_SIZE_UNIT (decl));
02319 }
02320 WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
02321 }
02322
02323 case STATEMENT_LIST:
02324 {
02325 tree_stmt_iterator i;
02326 for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
02327 WALK_SUBTREE (*tsi_stmt_ptr (i));
02328 }
02329 break;
02330
02331 default:
02332
02333
02334 break;
02335 }
02336 }
02337
02338
02339 return NULL_TREE;
02340
02341 #undef WALK_SUBTREE
02342 #undef WALK_SUBTREE_TAIL
02343 }
02344
02345
02346
02347 tree
02348 walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data)
02349 {
02350 tree result;
02351 struct pointer_set_t *pset;
02352
02353 pset = pointer_set_create ();
02354 result = walk_tree (tp, func, data, pset);
02355 pointer_set_destroy (pset);
02356 return result;
02357 }
02358
02359
02360
02361 tree
02362 copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
02363 {
02364 enum tree_code code = TREE_CODE (*tp);
02365
02366
02367 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
02368 || code == TREE_LIST
02369 || code == TREE_VEC
02370 || code == TYPE_DECL)
02371 {
02372
02373
02374 tree chain = TREE_CHAIN (*tp);
02375 tree new;
02376
02377
02378 new = copy_node (*tp);
02379
02380
02381 if (flag_mudflap && mf_marked_p (*tp))
02382 mf_mark (new);
02383
02384 *tp = new;
02385
02386
02387
02388 if (code == PARM_DECL || code == TREE_LIST)
02389 TREE_CHAIN (*tp) = chain;
02390
02391
02392
02393 if (TREE_CODE (*tp) == BIND_EXPR)
02394 BIND_EXPR_BLOCK (*tp) = NULL_TREE;
02395 }
02396
02397 else if (TREE_CODE_CLASS (code) == tcc_type)
02398 *walk_subtrees = 0;
02399 else if (TREE_CODE_CLASS (code) == tcc_declaration)
02400 *walk_subtrees = 0;
02401 else if (TREE_CODE_CLASS (code) == tcc_constant)
02402 *walk_subtrees = 0;
02403 else
02404 gcc_assert (code != STATEMENT_LIST);
02405 return NULL_TREE;
02406 }
02407
02408
02409
02410
02411
02412 static void
02413 remap_save_expr (tree *tp, void *st_, int *walk_subtrees)
02414 {
02415 splay_tree st = (splay_tree) st_;
02416 splay_tree_node n;
02417 tree t;
02418
02419
02420 n = splay_tree_lookup (st, (splay_tree_key) *tp);
02421
02422
02423 if (!n)
02424 {
02425 t = copy_node (*tp);
02426
02427
02428 splay_tree_insert (st, (splay_tree_key) *tp, (splay_tree_value) t);
02429
02430 splay_tree_insert (st, (splay_tree_key) t, (splay_tree_value) t);
02431 }
02432 else
02433 {
02434
02435 *walk_subtrees = 0;
02436 t = (tree) n->value;
02437 }
02438
02439
02440 *tp = t;
02441 }
02442
02443
02444
02445
02446
02447 static tree
02448 mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
02449 void *data)
02450 {
02451 inline_data *id = (inline_data *) data;
02452
02453
02454 if (TYPE_P (*tp))
02455 *walk_subtrees = 0;
02456
02457 else if (TREE_CODE (*tp) == LABEL_EXPR)
02458 {
02459 tree decl = TREE_OPERAND (*tp, 0);
02460
02461
02462 insert_decl_map (id, decl,
02463 copy_decl_for_inlining (decl, DECL_CONTEXT (decl),
02464 DECL_CONTEXT (decl)));
02465 }
02466
02467 return NULL_TREE;
02468 }
02469
02470
02471
02472
02473 static void
02474 unsave_expr_1 (tree expr)
02475 {
02476 switch (TREE_CODE (expr))
02477 {
02478 case TARGET_EXPR:
02479
02480
02481
02482
02483 if (TREE_OPERAND (expr, 1))
02484 break;
02485
02486 TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3);
02487 TREE_OPERAND (expr, 3) = NULL_TREE;
02488 break;
02489
02490 default:
02491 break;
02492 }
02493 }
02494
02495
02496
02497
02498
02499 static tree
02500 unsave_r (tree *tp, int *walk_subtrees, void *data)
02501 {
02502 inline_data *id = (inline_data *) data;
02503 splay_tree st = id->decl_map;
02504 splay_tree_node n;
02505
02506
02507 if ((TREE_CODE (*tp) == VAR_DECL && !TREE_STATIC (*tp))
02508 || TREE_CODE (*tp) == LABEL_DECL)
02509 {
02510
02511 n = splay_tree_lookup (st, (splay_tree_key) *tp);
02512
02513
02514 if (n)
02515 *tp = (tree) n->value;
02516 }
02517
02518 else if (TREE_CODE (*tp) == STATEMENT_LIST)
02519 copy_statement_list (tp);
02520 else if (TREE_CODE (*tp) == BIND_EXPR)
02521 copy_bind_expr (tp, walk_subtrees, id);
02522 else if (TREE_CODE (*tp) == SAVE_EXPR)
02523 remap_save_expr (tp, st, walk_subtrees);
02524 else
02525 {
02526 copy_tree_r (tp, walk_subtrees, NULL);
02527
02528
02529 unsave_expr_1 (*tp);
02530 }
02531
02532
02533 return NULL_TREE;
02534 }
02535
02536
02537
02538
02539 tree
02540 unsave_expr_now (tree expr)
02541 {
02542 inline_data id;
02543
02544
02545 if (expr == 0)
02546 return expr;
02547
02548
02549 memset (&id, 0, sizeof (id));
02550 VARRAY_TREE_INIT (id.fns, 1, "fns");
02551 VARRAY_PUSH_TREE (id.fns, current_function_decl);
02552 id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
02553
02554
02555 walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id);
02556
02557
02558 walk_tree (&expr, unsave_r, &id, NULL);
02559
02560
02561 splay_tree_delete (id.decl_map);
02562
02563 return expr;
02564 }
02565
02566
02567
02568 static tree
02569 debug_find_tree_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
02570 {
02571 if (*tp == data)
02572 return (tree) data;
02573 else
02574 return NULL;
02575 }
02576
02577 bool
02578 debug_find_tree (tree top, tree search)
02579 {
02580 return walk_tree_without_duplicates (&top, debug_find_tree_1, search) != 0;
02581 }
02582
02583
02584
02585
02586 static void
02587 declare_inline_vars (tree bind_expr, tree vars)
02588 {
02589 tree t;
02590 for (t = vars; t; t = TREE_CHAIN (t))
02591 DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
02592
02593 add_var_to_bind_expr (bind_expr, vars);
02594 }