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
00027 #include "config.h"
00028 #include "system.h"
00029
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "tm_p.h"
00033 #include "regs.h"
00034 #include "flags.h"
00035 #include "debug.h"
00036 #include "insn-config.h"
00037 #include "expr.h"
00038 #include "output.h"
00039 #include "recog.h"
00040 #include "integrate.h"
00041 #include "real.h"
00042 #include "except.h"
00043 #include "function.h"
00044 #include "toplev.h"
00045 #include "intl.h"
00046 #include "loop.h"
00047 #include "params.h"
00048 #include "ggc.h"
00049 #include "target.h"
00050 #include "langhooks.h"
00051
00052
00053
00054 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
00055
00056
00057
00058 #ifndef INTEGRATE_THRESHOLD
00059
00060
00061 #define INTEGRATE_THRESHOLD(DECL) \
00062 (optimize_size \
00063 ? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
00064 : (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
00065 #endif
00066
00067
00068
00069 typedef struct initial_value_pair GTY(()) {
00070 rtx hard_reg;
00071 rtx pseudo;
00072 } initial_value_pair;
00073 typedef struct initial_value_struct GTY(()) {
00074 int num_entries;
00075 int max_entries;
00076 initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
00077 } initial_value_struct;
00078
00079 static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
00080
00081 static rtvec initialize_for_inline PARAMS ((tree));
00082 static void note_modified_parmregs PARAMS ((rtx, rtx, void *));
00083 static void integrate_parm_decls PARAMS ((tree, struct inline_remap *,
00084 rtvec));
00085 static tree integrate_decl_tree PARAMS ((tree,
00086 struct inline_remap *));
00087 static void subst_constants PARAMS ((rtx *, rtx,
00088 struct inline_remap *, int));
00089 static void set_block_origin_self PARAMS ((tree));
00090 static void set_block_abstract_flags PARAMS ((tree, int));
00091 static void process_reg_param PARAMS ((struct inline_remap *, rtx,
00092 rtx));
00093 void set_decl_abstract_flags PARAMS ((tree, int));
00094 static void mark_stores PARAMS ((rtx, rtx, void *));
00095 static void save_parm_insns PARAMS ((rtx, rtx));
00096 static void copy_insn_list PARAMS ((rtx, struct inline_remap *,
00097 rtx));
00098 static void copy_insn_notes PARAMS ((rtx, struct inline_remap *,
00099 int));
00100 static int compare_blocks PARAMS ((const PTR, const PTR));
00101 static int find_block PARAMS ((const PTR, const PTR));
00102
00103
00104
00105
00106
00107 static struct function *inlining = 0;
00108
00109
00110
00111
00112
00113
00114 rtx
00115 get_label_from_map (map, i)
00116 struct inline_remap *map;
00117 int i;
00118 {
00119 rtx x = map->label_map[i];
00120
00121 if (x == NULL_RTX)
00122 x = map->label_map[i] = gen_label_rtx ();
00123
00124 return x;
00125 }
00126
00127
00128
00129 bool
00130 function_attribute_inlinable_p (fndecl)
00131 tree fndecl;
00132 {
00133 if (targetm.attribute_table)
00134 {
00135 tree a;
00136
00137 for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
00138 {
00139 tree name = TREE_PURPOSE (a);
00140 int i;
00141
00142 for (i = 0; targetm.attribute_table[i].name != NULL; i++)
00143 if (is_attribute_p (targetm.attribute_table[i].name, name))
00144 return (*targetm.function_attribute_inlinable_p) (fndecl);
00145 }
00146 }
00147
00148 return true;
00149 }
00150
00151
00152
00153
00154
00155
00156 const char *
00157 function_cannot_inline_p (fndecl)
00158 tree fndecl;
00159 {
00160 rtx insn;
00161 tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
00162
00163
00164
00165
00166
00167
00168
00169 int max_insns = (DECL_INLINE (fndecl))
00170 ? (MAX_INLINE_INSNS_RTL
00171 + 8 * list_length (DECL_ARGUMENTS (fndecl)))
00172 : INTEGRATE_THRESHOLD (fndecl);
00173
00174 int ninsns = 0;
00175 tree parms;
00176
00177 if (DECL_UNINLINABLE (fndecl))
00178 return N_("function cannot be inline");
00179
00180
00181 if (last && TREE_VALUE (last) != void_type_node)
00182 return N_("varargs function cannot be inline");
00183
00184 if (current_function_calls_alloca)
00185 return N_("function using alloca cannot be inline");
00186
00187 if (current_function_calls_setjmp)
00188 return N_("function using setjmp cannot be inline");
00189
00190 if (current_function_calls_eh_return)
00191 return N_("function uses __builtin_eh_return");
00192
00193 if (current_function_contains_functions)
00194 return N_("function with nested functions cannot be inline");
00195
00196 if (forced_labels)
00197 return
00198 N_("function with label addresses used in initializers cannot inline");
00199
00200 if (current_function_cannot_inline)
00201 return current_function_cannot_inline;
00202
00203
00204 if (get_max_uid () > 3 * max_insns)
00205 return N_("function too large to be inline");
00206
00207 #if 0
00208
00209
00210 for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
00211 {
00212 if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
00213 TREE_ADDRESSABLE (parms) = 1;
00214 if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
00215 return N_("no prototype, and parameter address used; cannot be inline");
00216 }
00217 #endif
00218
00219
00220
00221 if (current_function_returns_pcc_struct)
00222 return N_("inline functions not supported for this return value type");
00223
00224
00225 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
00226 && int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
00227 return N_("function with varying-size return value cannot be inline");
00228
00229
00230
00231 for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
00232 {
00233 if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
00234 return N_("function with varying-size parameter cannot be inline");
00235 else if (TREE_CODE (TREE_TYPE (parms)) == UNION_TYPE
00236 && TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
00237 return N_("function with transparent unit parameter cannot be inline");
00238 }
00239
00240 if (get_max_uid () > max_insns)
00241 {
00242 for (ninsns = 0, insn = get_first_nonparm_insn ();
00243 insn && ninsns < max_insns;
00244 insn = NEXT_INSN (insn))
00245 if (INSN_P (insn))
00246 ninsns++;
00247
00248 if (ninsns >= max_insns)
00249 return N_("function too large to be inline");
00250 }
00251
00252
00253
00254
00255 if (current_function_has_computed_jump)
00256 return N_("function with computed jump cannot inline");
00257
00258
00259 if (current_function_has_nonlocal_goto)
00260 return N_("function with nonlocal goto cannot be inline");
00261
00262
00263 if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
00264 {
00265 rtx result = DECL_RTL (DECL_RESULT (fndecl));
00266 if (GET_CODE (result) == PARALLEL)
00267 return N_("inline functions not supported for this return value type");
00268 }
00269
00270
00271
00272
00273 if (!function_attribute_inlinable_p (fndecl))
00274 return N_("function with target specific attribute(s) cannot be inlined");
00275
00276 return NULL;
00277 }
00278
00279
00280
00281
00282 static tree *parmdecl_map;
00283
00284
00285 static int in_nonparm_insns;
00286
00287
00288
00289
00290 static rtvec
00291 initialize_for_inline (fndecl)
00292 tree fndecl;
00293 {
00294 int i;
00295 rtvec arg_vector;
00296 tree parms;
00297
00298
00299 memset ((char *) parmdecl_map, 0, max_parm_reg * sizeof (tree));
00300 arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
00301
00302 for (parms = DECL_ARGUMENTS (fndecl), i = 0;
00303 parms;
00304 parms = TREE_CHAIN (parms), i++)
00305 {
00306 rtx p = DECL_RTL (parms);
00307
00308
00309
00310
00311 if (GET_CODE (p) == MEM && GET_CODE (XEXP (p, 0)) == ADDRESSOF
00312 && GET_CODE (XEXP (XEXP (p, 0), 0)) == MEM)
00313 p = XEXP (XEXP (p, 0), 0);
00314
00315 RTVEC_ELT (arg_vector, i) = p;
00316
00317 if (GET_CODE (p) == REG)
00318 parmdecl_map[REGNO (p)] = parms;
00319 else if (GET_CODE (p) == CONCAT)
00320 {
00321 rtx preal = gen_realpart (GET_MODE (XEXP (p, 0)), p);
00322 rtx pimag = gen_imagpart (GET_MODE (preal), p);
00323
00324 if (GET_CODE (preal) == REG)
00325 parmdecl_map[REGNO (preal)] = parms;
00326 if (GET_CODE (pimag) == REG)
00327 parmdecl_map[REGNO (pimag)] = parms;
00328 }
00329
00330
00331
00332 TREE_READONLY (parms) = 1;
00333 }
00334
00335 return arg_vector;
00336 }
00337
00338
00339
00340
00341
00342 tree
00343 copy_decl_for_inlining (decl, from_fn, to_fn)
00344 tree decl;
00345 tree from_fn;
00346 tree to_fn;
00347 {
00348 tree copy;
00349 #ifdef KEY
00350 static unsigned int ret_var_uniquifier = 0;
00351 static char ret_var_uniqified[256];
00352 #endif
00353
00354
00355 if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
00356 {
00357 tree type;
00358 int invisiref = 0;
00359
00360
00361 if (TREE_CODE (decl) == PARM_DECL
00362 && DECL_ARG_TYPE (decl) != TREE_TYPE (decl)
00363 && POINTER_TYPE_P (DECL_ARG_TYPE (decl))
00364 && TREE_TYPE (DECL_ARG_TYPE (decl)) == TREE_TYPE (decl))
00365 {
00366 invisiref = 1;
00367 type = DECL_ARG_TYPE (decl);
00368 }
00369 else
00370 type = TREE_TYPE (decl);
00371
00372
00373
00374 #ifdef KEY
00375 if (TREE_CODE (decl) == RESULT_DECL) {
00376
00377
00378
00379
00380 sprintf (ret_var_uniqified, "__KEY__RV__%d", ret_var_uniquifier++);
00381 copy = build_decl (VAR_DECL, get_identifier(ret_var_uniqified), type);
00382 }
00383 else copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
00384 #else
00385 copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
00386 #endif
00387
00388 if (!invisiref)
00389 {
00390 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
00391 TREE_READONLY (copy) = TREE_READONLY (decl);
00392 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
00393 }
00394 else
00395 {
00396 TREE_ADDRESSABLE (copy) = 0;
00397 TREE_READONLY (copy) = 1;
00398 TREE_THIS_VOLATILE (copy) = 0;
00399 }
00400 }
00401 else
00402 {
00403 copy = copy_node (decl);
00404
00405 DECL_ABSTRACT (copy) = 0;
00406 (*lang_hooks.dup_lang_specific_decl) (copy);
00407
00408
00409
00410
00411 if (TREE_CODE (copy) == LABEL_DECL)
00412 TREE_ADDRESSABLE (copy) = 0;
00413 }
00414
00415
00416
00417 DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
00418
00419
00420 SET_DECL_RTL (copy, NULL_RTX);
00421
00422
00423 TREE_USED (copy) = 1;
00424
00425
00426 if (!DECL_CONTEXT (decl))
00427
00428 ;
00429 else if (DECL_CONTEXT (decl) != from_fn)
00430
00431
00432 ;
00433 else if (TREE_STATIC (decl))
00434
00435
00436 ;
00437 else
00438
00439
00440 DECL_CONTEXT (copy) = to_fn;
00441
00442 return copy;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 void
00465 save_for_inline (fndecl)
00466 tree fndecl;
00467 {
00468 rtx insn;
00469 rtvec argvec;
00470 rtx first_nonparm_insn;
00471
00472
00473
00474
00475
00476
00477 if (! flag_no_inline)
00478 parmdecl_map = (tree *) xmalloc (max_parm_reg * sizeof (tree));
00479
00480
00481
00482 if (return_label == 0)
00483 {
00484 return_label = gen_label_rtx ();
00485 emit_label (return_label);
00486 }
00487
00488 if (! flag_no_inline)
00489 argvec = initialize_for_inline (fndecl);
00490 else
00491 argvec = NULL;
00492
00493
00494
00495
00496 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
00497 if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
00498 delete_related_insns (insn);
00499
00500
00501
00502
00503
00504 insn = get_insns ();
00505 if (GET_CODE (insn) != NOTE)
00506 abort ();
00507
00508 if (! flag_no_inline)
00509 {
00510
00511 first_nonparm_insn = get_first_nonparm_insn ();
00512
00513
00514
00515
00516
00517
00518
00519 in_nonparm_insns = 0;
00520 save_parm_insns (insn, first_nonparm_insn);
00521
00522 cfun->inl_max_label_num = max_label_num ();
00523 cfun->inl_last_parm_insn = cfun->x_last_parm_insn;
00524 cfun->original_arg_vector = argvec;
00525 }
00526 cfun->original_decl_initial = DECL_INITIAL (fndecl);
00527 cfun->no_debugging_symbols = (write_symbols == NO_DEBUG);
00528 DECL_SAVED_INSNS (fndecl) = cfun;
00529
00530
00531 if (! flag_no_inline)
00532 free (parmdecl_map);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541 static void
00542 save_parm_insns (insn, first_nonparm_insn)
00543 rtx insn;
00544 rtx first_nonparm_insn;
00545 {
00546 if (insn == NULL_RTX)
00547 return;
00548
00549 for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
00550 {
00551 if (insn == first_nonparm_insn)
00552 in_nonparm_insns = 1;
00553
00554 if (INSN_P (insn))
00555 {
00556
00557 note_stores (PATTERN (insn), note_modified_parmregs, NULL);
00558
00559
00560
00561
00562 if (GET_CODE (insn) == CALL_INSN
00563 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
00564 {
00565 int i;
00566
00567 for (i = 0; i < 3; i++)
00568 save_parm_insns (XEXP (PATTERN (insn), i),
00569 first_nonparm_insn);
00570 }
00571 }
00572 }
00573 }
00574
00575
00576
00577 static void
00578 note_modified_parmregs (reg, x, data)
00579 rtx reg;
00580 rtx x ATTRIBUTE_UNUSED;
00581 void *data ATTRIBUTE_UNUSED;
00582 {
00583 if (GET_CODE (reg) == REG && in_nonparm_insns
00584 && REGNO (reg) < max_parm_reg
00585 && REGNO (reg) >= FIRST_PSEUDO_REGISTER
00586 && parmdecl_map[REGNO (reg)] != 0)
00587 TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
00588 }
00589
00590
00591
00592
00593
00594 varray_type global_const_equiv_varray;
00595
00596 #define FIXED_BASE_PLUS_P(X) \
00597 (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
00598 && GET_CODE (XEXP (X, 0)) == REG \
00599 && REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
00600 && REGNO (XEXP (X, 0)) <= LAST_VIRTUAL_REGISTER)
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 static void
00612 process_reg_param (map, loc, copy)
00613 struct inline_remap *map;
00614 rtx loc, copy;
00615 {
00616 if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
00617 || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
00618 && ! REG_USERVAR_P (copy))
00619 || (GET_CODE (copy) == REG
00620 && REGNO (copy) < FIRST_PSEUDO_REGISTER))
00621 {
00622 rtx temp = copy_to_mode_reg (GET_MODE (loc), copy);
00623 REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
00624 if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
00625 SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
00626 copy = temp;
00627 }
00628 map->reg_map[REGNO (loc)] = copy;
00629 }
00630
00631
00632
00633
00634
00635 static int
00636 compare_blocks (v1, v2)
00637 const PTR v1;
00638 const PTR v2;
00639 {
00640 tree b1 = *((const tree *) v1);
00641 tree b2 = *((const tree *) v2);
00642 char *p1 = (char *) BLOCK_ABSTRACT_ORIGIN (b1);
00643 char *p2 = (char *) BLOCK_ABSTRACT_ORIGIN (b2);
00644
00645 if (p1 == p2)
00646 return 0;
00647 return p1 < p2 ? -1 : 1;
00648 }
00649
00650
00651
00652
00653 static int
00654 find_block (v1, v2)
00655 const PTR v1;
00656 const PTR v2;
00657 {
00658 const union tree_node *b1 = (const union tree_node *) v1;
00659 tree b2 = *((const tree *) v2);
00660 char *p1 = (char *) b1;
00661 char *p2 = (char *) BLOCK_ABSTRACT_ORIGIN (b2);
00662
00663 if (p1 == p2)
00664 return 0;
00665 return p1 < p2 ? -1 : 1;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 rtx
00682 expand_inline_function (fndecl, parms, target, ignore, type,
00683 structure_value_addr)
00684 tree fndecl, parms;
00685 rtx target;
00686 int ignore;
00687 tree type;
00688 rtx structure_value_addr;
00689 {
00690 struct function *inlining_previous;
00691 struct function *inl_f = DECL_SAVED_INSNS (fndecl);
00692 tree formal, actual, block;
00693 rtx parm_insns = inl_f->emit->x_first_insn;
00694 rtx insns = (inl_f->inl_last_parm_insn
00695 ? NEXT_INSN (inl_f->inl_last_parm_insn)
00696 : parm_insns);
00697 tree *arg_trees;
00698 rtx *arg_vals;
00699 int max_regno;
00700 int i;
00701 int min_labelno = inl_f->emit->x_first_label_num;
00702 int max_labelno = inl_f->inl_max_label_num;
00703 int nargs;
00704 rtx loc;
00705 rtx stack_save = 0;
00706 rtx temp;
00707 struct inline_remap *map = 0;
00708 rtvec arg_vector = inl_f->original_arg_vector;
00709 rtx static_chain_value = 0;
00710 int inl_max_uid;
00711 int eh_region_offset;
00712
00713
00714
00715 rtx *real_label_map = 0;
00716
00717
00718 max_regno = inl_f->emit->x_reg_rtx_no + 3;
00719 if (max_regno < FIRST_PSEUDO_REGISTER)
00720 abort ();
00721
00722
00723
00724 fndecl = inl_f->decl;
00725
00726 nargs = list_length (DECL_ARGUMENTS (fndecl));
00727
00728 if (cfun->preferred_stack_boundary < inl_f->preferred_stack_boundary)
00729 cfun->preferred_stack_boundary = inl_f->preferred_stack_boundary;
00730
00731
00732
00733
00734
00735 for (formal = DECL_ARGUMENTS (fndecl), actual = parms;
00736 formal;
00737 formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual))
00738 {
00739 tree arg;
00740 enum machine_mode mode;
00741
00742 if (actual == 0)
00743 return (rtx) (size_t) -1;
00744
00745 arg = TREE_VALUE (actual);
00746 mode = TYPE_MODE (DECL_ARG_TYPE (formal));
00747
00748 if (arg == error_mark_node
00749 || mode != TYPE_MODE (TREE_TYPE (arg))
00750
00751
00752
00753 || (mode == BLKmode
00754 && (TYPE_MAIN_VARIANT (TREE_TYPE (arg))
00755 != TYPE_MAIN_VARIANT (TREE_TYPE (formal)))))
00756 return (rtx) (size_t) -1;
00757 }
00758
00759
00760
00761 for (; actual; actual = TREE_CHAIN (actual))
00762 expand_expr (TREE_VALUE (actual), const0_rtx,
00763 TYPE_MODE (TREE_TYPE (TREE_VALUE (actual))), 0);
00764
00765
00766
00767
00768 arg_vals = (rtx *) xmalloc (nargs * sizeof (rtx));
00769 arg_trees = (tree *) xmalloc (nargs * sizeof (tree));
00770
00771 for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;
00772 formal;
00773 formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)
00774 {
00775
00776
00777 tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
00778
00779 enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
00780 int invisiref = 0;
00781
00782 arg_trees[i] = arg;
00783 loc = RTVEC_ELT (arg_vector, i);
00784
00785
00786
00787
00788
00789 if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
00790 && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
00791 {
00792 rtx stack_slot = assign_temp (TREE_TYPE (arg), 1, 1, 1);
00793
00794 store_expr (arg, stack_slot, 0);
00795 arg_vals[i] = XEXP (stack_slot, 0);
00796 invisiref = 1;
00797 }
00798 else if (GET_CODE (loc) != MEM)
00799 {
00800 if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))
00801 {
00802 int unsignedp = TREE_UNSIGNED (TREE_TYPE (formal));
00803 enum machine_mode pmode = TYPE_MODE (TREE_TYPE (formal));
00804
00805 pmode = promote_mode (TREE_TYPE (formal), pmode,
00806 &unsignedp, 0);
00807
00808 if (GET_MODE (loc) != pmode)
00809 abort ();
00810
00811
00812
00813 arg_vals[i] = convert_modes (pmode,
00814 TYPE_MODE (TREE_TYPE (arg)),
00815 expand_expr (arg, NULL_RTX, mode,
00816 EXPAND_SUM),
00817 unsignedp);
00818 }
00819 else
00820 arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
00821 }
00822 else
00823 arg_vals[i] = 0;
00824
00825 if (arg_vals[i] != 0
00826 && (! TREE_READONLY (formal)
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 || (target != 0
00837 && ! invisiref
00838 && (GET_CODE (arg_vals[i]) == REG
00839 || GET_CODE (arg_vals[i]) == SUBREG
00840 || GET_CODE (arg_vals[i]) == MEM)
00841 && reg_overlap_mentioned_p (arg_vals[i], target))
00842
00843
00844
00845 || (GET_CODE (arg_vals[i]) == SUBREG)))
00846 arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);
00847
00848 if (arg_vals[i] != 0 && GET_CODE (arg_vals[i]) == REG
00849 && POINTER_TYPE_P (TREE_TYPE (formal)))
00850 mark_reg_pointer (arg_vals[i],
00851 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (formal))));
00852 }
00853
00854
00855
00856 map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
00857 map->fndecl = fndecl;
00858
00859 VARRAY_TREE_INIT (map->block_map, 10, "block_map");
00860 map->reg_map = (rtx *) xcalloc (max_regno, sizeof (rtx));
00861
00862
00863
00864
00865 real_label_map
00866 = (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
00867 map->label_map = real_label_map;
00868 map->local_return_label = NULL_RTX;
00869
00870 inl_max_uid = (inl_f->emit->x_cur_insn_uid + 1);
00871 map->insn_map = (rtx *) xcalloc (inl_max_uid, sizeof (rtx));
00872 map->min_insnno = 0;
00873 map->max_insnno = inl_max_uid;
00874
00875 map->integrating = 1;
00876 map->compare_src = NULL_RTX;
00877 map->compare_mode = VOIDmode;
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
00893 (max_reg_num ()
00894 + (max_regno - FIRST_PSEUDO_REGISTER)
00895 + 15 * nargs
00896 + 10),
00897 "expand_inline_function");
00898 map->const_age = 0;
00899
00900
00901
00902
00903 map->insns_at_start = get_last_insn ();
00904 if (map->insns_at_start == 0)
00905 map->insns_at_start = emit_note (NULL, NOTE_INSN_DELETED);
00906
00907 map->regno_pointer_align = inl_f->emit->regno_pointer_align;
00908 map->x_regno_reg_rtx = inl_f->emit->x_regno_reg_rtx;
00909
00910
00911
00912 if (inl_f->outgoing_args_size > current_function_outgoing_args_size)
00913 current_function_outgoing_args_size = inl_f->outgoing_args_size;
00914
00915
00916
00917 if (inl_f->uses_pic_offset_table)
00918 current_function_uses_pic_offset_table = 1;
00919
00920
00921 if (inl_f->needs_context)
00922 static_chain_value = lookup_static_chain (fndecl);
00923
00924 if (GET_CODE (parm_insns) == NOTE
00925 && NOTE_LINE_NUMBER (parm_insns) > 0)
00926 {
00927 rtx note = emit_note (NOTE_SOURCE_FILE (parm_insns),
00928 NOTE_LINE_NUMBER (parm_insns));
00929 if (note)
00930 RTX_INTEGRATED_P (note) = 1;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 for (i = 0; i < nargs; i++)
00947 {
00948 rtx copy = arg_vals[i];
00949
00950 loc = RTVEC_ELT (arg_vector, i);
00951
00952
00953 if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
00954 && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
00955 {
00956
00957
00958
00959
00960
00961
00962
00963 if (GET_CODE (copy) != REG)
00964 {
00965 temp = copy_addr_to_reg (copy);
00966 if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
00967 SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
00968 copy = temp;
00969 }
00970 map->reg_map[REGNO (XEXP (loc, 0))] = copy;
00971 }
00972 else if (GET_CODE (loc) == MEM)
00973 {
00974
00975
00976
00977
00978
00979
00980
00981
00982 if (DECL_SAVED_INSNS (fndecl)->args_size != 0)
00983 copy_rtx_and_substitute (virtual_incoming_args_rtx, map, 0);
00984 }
00985 else if (GET_CODE (loc) == REG)
00986 process_reg_param (map, loc, copy);
00987 else if (GET_CODE (loc) == CONCAT)
00988 {
00989 rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
00990 rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
00991 rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
00992 rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);
00993
00994 process_reg_param (map, locreal, copyreal);
00995 process_reg_param (map, locimag, copyimag);
00996 }
00997 else
00998 abort ();
00999 }
01000
01001
01002
01003
01004 inlining_previous = inlining;
01005 inlining = inl_f;
01006
01007
01008
01009 for (formal = DECL_ARGUMENTS (fndecl), i = 0;
01010 formal; formal = TREE_CHAIN (formal), i++)
01011 {
01012 loc = RTVEC_ELT (arg_vector, i);
01013
01014 if (GET_CODE (loc) == MEM
01015
01016 && ! (GET_CODE (XEXP (loc, 0)) == REG
01017 && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
01018 {
01019 rtx note = emit_note (DECL_SOURCE_FILE (formal),
01020 DECL_SOURCE_LINE (formal));
01021 if (note)
01022 RTX_INTEGRATED_P (note) = 1;
01023
01024
01025
01026 temp = copy_rtx_and_substitute (loc, map, 1);
01027 subst_constants (&temp, NULL_RTX, map, 1);
01028 apply_change_group ();
01029 if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
01030 temp = change_address (temp, VOIDmode, XEXP (temp, 0));
01031 store_expr (arg_trees[i], temp, 0);
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040
01041 map->inline_target = 0;
01042 loc = (DECL_RTL_SET_P (DECL_RESULT (fndecl))
01043 ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
01044
01045 if (TYPE_MODE (type) == VOIDmode)
01046
01047 ;
01048 else if (GET_CODE (loc) == MEM)
01049 {
01050 if (GET_CODE (XEXP (loc, 0)) == ADDRESSOF)
01051 {
01052 temp = copy_rtx_and_substitute (loc, map, 1);
01053 subst_constants (&temp, NULL_RTX, map, 1);
01054 apply_change_group ();
01055 target = temp;
01056 }
01057 else
01058 {
01059 if (! structure_value_addr
01060 || ! aggregate_value_p (DECL_RESULT (fndecl)))
01061 abort ();
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 if (GET_CODE (XEXP (loc, 0)) == REG)
01074 {
01075 temp = force_operand (structure_value_addr, NULL_RTX);
01076 temp = force_reg (Pmode, temp);
01077
01078
01079
01080
01081
01082
01083 if (REGNO (temp) >= FIRST_VIRTUAL_REGISTER
01084 && REGNO (temp) <= LAST_VIRTUAL_REGISTER)
01085 temp = copy_to_mode_reg (Pmode, temp);
01086 map->reg_map[REGNO (XEXP (loc, 0))] = temp;
01087
01088 if (CONSTANT_P (structure_value_addr)
01089 || GET_CODE (structure_value_addr) == ADDRESSOF
01090 || (GET_CODE (structure_value_addr) == PLUS
01091 && (XEXP (structure_value_addr, 0)
01092 == virtual_stack_vars_rtx)
01093 && (GET_CODE (XEXP (structure_value_addr, 1))
01094 == CONST_INT)))
01095 {
01096 SET_CONST_EQUIV_DATA (map, temp, structure_value_addr,
01097 CONST_AGE_PARM);
01098 }
01099 }
01100 else
01101 {
01102 temp = copy_rtx_and_substitute (loc, map, 1);
01103 subst_constants (&temp, NULL_RTX, map, 0);
01104 apply_change_group ();
01105 emit_move_insn (temp, structure_value_addr);
01106 }
01107 }
01108 }
01109 else if (ignore)
01110
01111
01112
01113 ;
01114 else if (GET_CODE (loc) == REG)
01115 {
01116
01117
01118
01119
01120 enum machine_mode departing_mode = TYPE_MODE (type);
01121
01122
01123
01124
01125 enum machine_mode arriving_mode
01126 = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
01127 rtx reg_to_map;
01128
01129
01130
01131
01132 if (target == 0 || GET_CODE (target) != REG
01133 || GET_MODE (target) != departing_mode)
01134 {
01135
01136
01137
01138 if (departing_mode == BLKmode)
01139 {
01140 if (REG == GET_CODE (DECL_RTL (DECL_RESULT (fndecl))))
01141 {
01142 departing_mode = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
01143 arriving_mode = departing_mode;
01144 }
01145 else
01146 abort ();
01147 }
01148
01149 target = gen_reg_rtx (departing_mode);
01150 }
01151
01152
01153
01154
01155 if (arriving_mode != departing_mode)
01156 {
01157
01158
01159 if (GET_MODE_BITSIZE (arriving_mode) > BITS_PER_WORD)
01160 {
01161 if (!TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (departing_mode),
01162 GET_MODE_BITSIZE (arriving_mode)))
01163
01164 abort ();
01165 reg_to_map = gen_reg_rtx (arriving_mode);
01166 target = gen_lowpart (departing_mode, reg_to_map);
01167 }
01168 else
01169 reg_to_map = gen_rtx_SUBREG (arriving_mode, target, 0);
01170 }
01171 else
01172 reg_to_map = target;
01173
01174
01175
01176 if (REG_FUNCTION_VALUE_P (loc))
01177 map->inline_target = reg_to_map;
01178 else
01179 map->reg_map[REGNO (loc)] = reg_to_map;
01180 }
01181 else if (GET_CODE (loc) == CONCAT)
01182 {
01183 enum machine_mode departing_mode = TYPE_MODE (type);
01184 enum machine_mode arriving_mode
01185 = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
01186
01187 if (departing_mode != arriving_mode)
01188 abort ();
01189 if (GET_CODE (XEXP (loc, 0)) != REG
01190 || GET_CODE (XEXP (loc, 1)) != REG)
01191 abort ();
01192
01193
01194
01195
01196 if (target == 0 || GET_CODE (target) != REG
01197 || GET_MODE (target) != departing_mode)
01198 target = gen_reg_rtx (departing_mode);
01199
01200 if (GET_CODE (target) != CONCAT)
01201 abort ();
01202
01203 map->reg_map[REGNO (XEXP (loc, 0))] = XEXP (target, 0);
01204 map->reg_map[REGNO (XEXP (loc, 1))] = XEXP (target, 1);
01205 }
01206 else
01207 abort ();
01208
01209
01210 temp = get_exception_pointer (inl_f);
01211 if (temp)
01212 map->reg_map[REGNO (temp)] = get_exception_pointer (cfun);
01213
01214
01215
01216 memset ((char *) &map->label_map[min_labelno], 0,
01217 (max_labelno - min_labelno) * sizeof (rtx));
01218
01219
01220
01221
01222
01223 inline_function_decl = fndecl;
01224 integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
01225 block = integrate_decl_tree (inl_f->original_decl_initial, map);
01226 BLOCK_ABSTRACT_ORIGIN (block) = DECL_ORIGIN (fndecl);
01227 inline_function_decl = 0;
01228
01229
01230
01231 expand_start_bindings_and_block (0, block);
01232
01233
01234
01235 qsort (&VARRAY_TREE (map->block_map, 0),
01236 map->block_map->elements_used,
01237 sizeof (tree),
01238 compare_blocks);
01239
01240
01241 emit_queue ();
01242
01243
01244 do_pending_stack_adjust ();
01245
01246
01247
01248 global_const_equiv_varray = map->const_equiv_varray;
01249
01250
01251
01252
01253
01254 if (inl_f->calls_alloca)
01255 emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
01256
01257
01258 setup_initial_hard_reg_value_integration (inl_f, map);
01259
01260
01261 copy_insn_list (insns, map, static_chain_value);
01262
01263
01264
01265
01266
01267 eh_region_offset = duplicate_eh_regions (inl_f, map);
01268
01269
01270 copy_insn_notes (insns, map, eh_region_offset);
01271
01272
01273 if (map->local_return_label)
01274 emit_label (map->local_return_label);
01275
01276
01277 if (inl_f->calls_alloca)
01278 emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX);
01279
01280 if (! cfun->x_whole_function_mode_p)
01281
01282
01283
01284
01285 (*lang_hooks.decls.insert_block) (block);
01286 else
01287 {
01288 BLOCK_CHAIN (block)
01289 = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
01290 BLOCK_CHAIN (DECL_INITIAL (current_function_decl)) = block;
01291 }
01292
01293
01294
01295
01296
01297
01298 expand_end_bindings (NULL_TREE, 1, 1);
01299
01300
01301
01302
01303
01304
01305
01306 if (flag_test_coverage)
01307 emit_note (0, NOTE_INSN_REPEATED_LINE_NUMBER);
01308
01309 emit_line_note (input_filename, lineno);
01310
01311
01312
01313 if (target
01314 && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
01315 && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
01316 target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
01317
01318 if (structure_value_addr)
01319 {
01320 target = gen_rtx_MEM (TYPE_MODE (type),
01321 memory_address (TYPE_MODE (type),
01322 structure_value_addr));
01323 set_mem_attributes (target, type, 1);
01324 }
01325
01326
01327 if (real_label_map)
01328 free (real_label_map);
01329 VARRAY_FREE (map->const_equiv_varray);
01330 free (map->reg_map);
01331 free (map->insn_map);
01332 free (map);
01333 free (arg_vals);
01334 free (arg_trees);
01335
01336 inlining = inlining_previous;
01337
01338 return target;
01339 }
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 static void
01351 copy_insn_list (insns, map, static_chain_value)
01352 rtx insns;
01353 struct inline_remap *map;
01354 rtx static_chain_value;
01355 {
01356 int i;
01357 rtx insn;
01358 rtx temp;
01359 #ifdef HAVE_cc0
01360 rtx cc0_insn = 0;
01361 #endif
01362 rtx static_chain_mem = 0;
01363
01364
01365
01366
01367
01368
01369 for (insn = insns; insn; insn = NEXT_INSN (insn))
01370 {
01371 rtx copy, pattern, set;
01372
01373 map->orig_asm_operands_vector = 0;
01374
01375 switch (GET_CODE (insn))
01376 {
01377 case INSN:
01378 pattern = PATTERN (insn);
01379 set = single_set (insn);
01380 copy = 0;
01381 if (GET_CODE (pattern) == USE
01382 && GET_CODE (XEXP (pattern, 0)) == REG
01383 && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
01384
01385
01386
01387 break;
01388
01389
01390 if (map->inline_target == 0
01391 && set != 0
01392 && GET_CODE (SET_DEST (set)) == REG
01393 && REG_FUNCTION_VALUE_P (SET_DEST (set)))
01394 {
01395 if (volatile_refs_p (SET_SRC (set)))
01396 {
01397 rtx new_set;
01398
01399
01400
01401 copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
01402
01403 new_set = single_set (copy);
01404 if (new_set == 0)
01405 abort ();
01406
01407 SET_DEST (new_set)
01408 = gen_reg_rtx (GET_MODE (SET_DEST (new_set)));
01409 }
01410
01411
01412 else if (rtx_equal_p (SET_DEST (set), SET_SRC (set))
01413 && REG_NOTES (insn) != 0)
01414 copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
01415 else
01416 break;
01417 }
01418
01419
01420 else if (map->inline_target == 0
01421 && GET_CODE (pattern) == CLOBBER
01422 && GET_CODE (XEXP (pattern, 0)) == REG
01423 && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
01424 break;
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442 else if (static_chain_value != 0
01443 && set != 0
01444 && GET_CODE (static_chain_incoming_rtx) == MEM
01445 && GET_CODE (SET_DEST (set)) == REG
01446 && rtx_equal_p (SET_SRC (set),
01447 XEXP (static_chain_incoming_rtx, 0)))
01448 {
01449 static_chain_mem =
01450 gen_rtx_MEM (GET_MODE (static_chain_incoming_rtx),
01451 SET_DEST (set));
01452
01453
01454
01455
01456 copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
01457 }
01458
01459
01460 else if (static_chain_value != 0
01461 && set != 0
01462 && (rtx_equal_p (SET_DEST (set),
01463 static_chain_incoming_rtx)
01464 || (static_chain_mem
01465 && rtx_equal_p (SET_DEST (set), static_chain_mem))))
01466 break;
01467
01468
01469
01470 else if (static_chain_value != 0
01471 && set != 0
01472 && (rtx_equal_p (SET_SRC (set),
01473 static_chain_incoming_rtx)
01474 || (static_chain_mem
01475 && rtx_equal_p (SET_SRC (set), static_chain_mem))))
01476 {
01477 rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map, 1);
01478
01479 copy = emit_move_insn (newdest, static_chain_value);
01480 if (GET_CODE (static_chain_incoming_rtx) != MEM)
01481 static_chain_value = 0;
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491 else if (set != 0
01492 && rtx_equal_p (SET_DEST (set), virtual_stack_vars_rtx))
01493 {
01494 HOST_WIDE_INT offset;
01495 temp = map->reg_map[REGNO (SET_DEST (set))];
01496 temp = VARRAY_CONST_EQUIV (map->const_equiv_varray,
01497 REGNO (temp)).rtx;
01498
01499 if (rtx_equal_p (temp, virtual_stack_vars_rtx))
01500 offset = 0;
01501 else if (GET_CODE (temp) == PLUS
01502 && rtx_equal_p (XEXP (temp, 0), virtual_stack_vars_rtx)
01503 && GET_CODE (XEXP (temp, 1)) == CONST_INT)
01504 offset = INTVAL (XEXP (temp, 1));
01505 else
01506 abort ();
01507
01508 if (rtx_equal_p (SET_SRC (set), stack_pointer_rtx))
01509 temp = SET_SRC (set);
01510 else
01511 temp = force_operand (plus_constant (SET_SRC (set),
01512 - offset),
01513 NULL_RTX);
01514
01515 copy = emit_move_insn (virtual_stack_vars_rtx, temp);
01516 }
01517
01518 else
01519 copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
01520
01521
01522 #ifdef HAVE_cc0
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 if (sets_cc0_p (PATTERN (copy)) != 0)
01537 cc0_insn = copy;
01538 else
01539 {
01540 if (cc0_insn)
01541 try_constants (cc0_insn, map);
01542 cc0_insn = 0;
01543 try_constants (copy, map);
01544 }
01545 #else
01546 try_constants (copy, map);
01547 #endif
01548 INSN_SCOPE (copy) = INSN_SCOPE (insn);
01549 break;
01550
01551 case JUMP_INSN:
01552 if (map->integrating && returnjump_p (insn))
01553 {
01554 if (map->local_return_label == 0)
01555 map->local_return_label = gen_label_rtx ();
01556 pattern = gen_jump (map->local_return_label);
01557 }
01558 else
01559 pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
01560
01561 copy = emit_jump_insn (pattern);
01562
01563 #ifdef HAVE_cc0
01564 if (cc0_insn)
01565 try_constants (cc0_insn, map);
01566 cc0_insn = 0;
01567 #endif
01568 try_constants (copy, map);
01569 INSN_SCOPE (copy) = INSN_SCOPE (insn);
01570
01571
01572
01573 if (any_condjump_p (insn) && onlyjump_p (insn) && map->last_pc_value)
01574 {
01575 #ifdef HAVE_cc0
01576
01577 if (only_sets_cc0_p (PREV_INSN (copy)))
01578 delete_related_insns (PREV_INSN (copy));
01579 #endif
01580
01581
01582 if (map->last_pc_value == pc_rtx)
01583 {
01584 delete_related_insns (copy);
01585 copy = 0;
01586 }
01587 else
01588
01589
01590
01591 emit_barrier ();
01592 }
01593 break;
01594
01595 case CALL_INSN:
01596
01597
01598
01599 if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
01600 {
01601 rtx sequence[3];
01602 rtx tail_label;
01603
01604 for (i = 0; i < 3; i++)
01605 {
01606 rtx seq;
01607
01608 sequence[i] = NULL_RTX;
01609 seq = XEXP (PATTERN (insn), i);
01610 if (seq)
01611 {
01612 start_sequence ();
01613 copy_insn_list (seq, map, static_chain_value);
01614 sequence[i] = get_insns ();
01615 end_sequence ();
01616 }
01617 }
01618
01619
01620
01621 tail_label = copy_rtx_and_substitute (XEXP (PATTERN (insn), 3),
01622 map, 0);
01623
01624 copy = emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode,
01625 sequence[0],
01626 sequence[1],
01627 sequence[2],
01628 tail_label));
01629 break;
01630 }
01631
01632 pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
01633 copy = emit_call_insn (pattern);
01634
01635 SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
01636 CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
01637 INSN_SCOPE (copy) = INSN_SCOPE (insn);
01638
01639
01640
01641
01642 CALL_INSN_FUNCTION_USAGE (copy)
01643 = copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn),
01644 map, 0);
01645
01646 #ifdef HAVE_cc0
01647 if (cc0_insn)
01648 try_constants (cc0_insn, map);
01649 cc0_insn = 0;
01650 #endif
01651 try_constants (copy, map);
01652
01653
01654 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01655 VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
01656 break;
01657
01658 case CODE_LABEL:
01659 copy = emit_label (get_label_from_map (map,
01660 CODE_LABEL_NUMBER (insn)));
01661 LABEL_NAME (copy) = LABEL_NAME (insn);
01662 map->const_age++;
01663 break;
01664
01665 case BARRIER:
01666 copy = emit_barrier ();
01667 break;
01668
01669 case NOTE:
01670 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)
01671 {
01672 copy = emit_label (get_label_from_map (map,
01673 CODE_LABEL_NUMBER (insn)));
01674 LABEL_NAME (copy) = NOTE_SOURCE_FILE (insn);
01675 map->const_age++;
01676 break;
01677 }
01678
01679
01680
01681
01682
01683
01684
01685 if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
01686 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
01687 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
01688 {
01689 copy = emit_note (NOTE_SOURCE_FILE (insn),
01690 NOTE_LINE_NUMBER (insn));
01691 if (copy
01692 && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
01693 || NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
01694 && NOTE_BLOCK (insn))
01695 {
01696 tree *mapped_block_p;
01697
01698 mapped_block_p
01699 = (tree *) bsearch (NOTE_BLOCK (insn),
01700 &VARRAY_TREE (map->block_map, 0),
01701 map->block_map->elements_used,
01702 sizeof (tree),
01703 find_block);
01704
01705 if (!mapped_block_p)
01706 abort ();
01707 else
01708 NOTE_BLOCK (copy) = *mapped_block_p;
01709 }
01710 else if (copy
01711 && NOTE_LINE_NUMBER (copy) == NOTE_INSN_EXPECTED_VALUE)
01712 NOTE_EXPECTED_VALUE (copy)
01713 = copy_rtx_and_substitute (NOTE_EXPECTED_VALUE (insn),
01714 map, 0);
01715 }
01716 else
01717 copy = 0;
01718 break;
01719
01720 default:
01721 abort ();
01722 }
01723
01724 if (copy)
01725 RTX_INTEGRATED_P (copy) = 1;
01726
01727 map->insn_map[INSN_UID (insn)] = copy;
01728 }
01729 }
01730
01731
01732
01733
01734
01735 static void
01736 copy_insn_notes (insns, map, eh_region_offset)
01737 rtx insns;
01738 struct inline_remap *map;
01739 int eh_region_offset;
01740 {
01741 rtx insn, new_insn;
01742
01743 map->const_age++;
01744 for (insn = insns; insn; insn = NEXT_INSN (insn))
01745 {
01746 if (! INSN_P (insn))
01747 continue;
01748
01749 new_insn = map->insn_map[INSN_UID (insn)];
01750 if (! new_insn)
01751 continue;
01752
01753 if (REG_NOTES (insn))
01754 {
01755 rtx next, note = copy_rtx_and_substitute (REG_NOTES (insn), map, 0);
01756
01757
01758
01759 subst_constants (¬e, NULL_RTX, map, 0);
01760 apply_change_group ();
01761 REG_NOTES (new_insn) = note;
01762
01763
01764
01765 for (; note; note = next)
01766 {
01767 next = XEXP (note, 1);
01768 if (REG_NOTE_KIND (note) == REG_LABEL)
01769 remove_note (new_insn, note);
01770 else if (REG_NOTE_KIND (note) == REG_EH_REGION
01771 && INTVAL (XEXP (note, 0)) > 0)
01772 XEXP (note, 0) = GEN_INT (INTVAL (XEXP (note, 0))
01773 + eh_region_offset);
01774 }
01775 }
01776
01777 if (GET_CODE (insn) == CALL_INSN
01778 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
01779 {
01780 int i;
01781 for (i = 0; i < 3; i++)
01782 copy_insn_notes (XEXP (PATTERN (insn), i), map, eh_region_offset);
01783 }
01784
01785 if (GET_CODE (insn) == JUMP_INSN
01786 && GET_CODE (PATTERN (insn)) == RESX)
01787 XINT (PATTERN (new_insn), 0) += eh_region_offset;
01788 }
01789 }
01790
01791
01792
01793
01794 static void
01795 integrate_parm_decls (args, map, arg_vector)
01796 tree args;
01797 struct inline_remap *map;
01798 rtvec arg_vector;
01799 {
01800 tree tail;
01801 int i;
01802
01803 for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
01804 {
01805 tree decl = copy_decl_for_inlining (tail, map->fndecl,
01806 current_function_decl);
01807 rtx new_decl_rtl
01808 = copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map, 1);
01809
01810
01811
01812
01813
01814
01815
01816
01817 subst_constants (&new_decl_rtl, NULL_RTX, map, 1);
01818 apply_change_group ();
01819 SET_DECL_RTL (decl, new_decl_rtl);
01820 }
01821 }
01822
01823
01824
01825
01826
01827
01828
01829
01830 static tree
01831 integrate_decl_tree (let, map)
01832 tree let;
01833 struct inline_remap *map;
01834 {
01835 tree t;
01836 tree new_block;
01837 tree *next;
01838
01839 new_block = make_node (BLOCK);
01840 VARRAY_PUSH_TREE (map->block_map, new_block);
01841 next = &BLOCK_VARS (new_block);
01842
01843 for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
01844 {
01845 tree d;
01846
01847 d = copy_decl_for_inlining (t, map->fndecl, current_function_decl);
01848
01849 if (DECL_RTL_SET_P (t))
01850 {
01851 rtx r;
01852
01853 SET_DECL_RTL (d, copy_rtx_and_substitute (DECL_RTL (t), map, 1));
01854
01855
01856
01857
01858
01859 r = DECL_RTL (d);
01860 subst_constants (&r, NULL_RTX, map, 1);
01861 SET_DECL_RTL (d, r);
01862
01863 if (GET_CODE (r) == REG)
01864 REGNO_DECL (REGNO (r)) = d;
01865 else if (GET_CODE (r) == CONCAT)
01866 {
01867 REGNO_DECL (REGNO (XEXP (r, 0))) = d;
01868 REGNO_DECL (REGNO (XEXP (r, 1))) = d;
01869 }
01870
01871 apply_change_group ();
01872 }
01873
01874
01875
01876 *next = d;
01877 next = &TREE_CHAIN (d);
01878 }
01879
01880 next = &BLOCK_SUBBLOCKS (new_block);
01881 for (t = BLOCK_SUBBLOCKS (let); t; t = BLOCK_CHAIN (t))
01882 {
01883 *next = integrate_decl_tree (t, map);
01884 BLOCK_SUPERCONTEXT (*next) = new_block;
01885 next = &BLOCK_CHAIN (*next);
01886 }
01887
01888 TREE_USED (new_block) = TREE_USED (let);
01889 BLOCK_ABSTRACT_ORIGIN (new_block) = let;
01890
01891 return new_block;
01892 }
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 rtx
01910 copy_rtx_and_substitute (orig, map, for_lhs)
01911 rtx orig;
01912 struct inline_remap *map;
01913 int for_lhs;
01914 {
01915 rtx copy, temp;
01916 int i, j;
01917 RTX_CODE code;
01918 enum machine_mode mode;
01919 const char *format_ptr;
01920 int regno;
01921
01922 if (orig == 0)
01923 return 0;
01924
01925 code = GET_CODE (orig);
01926 mode = GET_MODE (orig);
01927
01928 switch (code)
01929 {
01930 case REG:
01931
01932
01933
01934
01935 regno = REGNO (orig);
01936 if (regno <= LAST_VIRTUAL_REGISTER
01937 || (map->integrating
01938 && DECL_SAVED_INSNS (map->fndecl)->internal_arg_pointer == orig))
01939 {
01940
01941
01942 if (map->reg_map[regno] != 0)
01943 return map->reg_map[regno];
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953 else if (regno == VIRTUAL_STACK_VARS_REGNUM)
01954 {
01955 rtx loc, seq;
01956 int size = get_func_frame_size (DECL_SAVED_INSNS (map->fndecl));
01957 #ifdef FRAME_GROWS_DOWNWARD
01958 int alignment
01959 = (DECL_SAVED_INSNS (map->fndecl)->stack_alignment_needed
01960 / BITS_PER_UNIT);
01961
01962
01963
01964
01965
01966 if (alignment)
01967 size = CEIL_ROUND (size, alignment);
01968 #endif
01969 start_sequence ();
01970 loc = assign_stack_temp (BLKmode, size, 1);
01971 loc = XEXP (loc, 0);
01972 #ifdef FRAME_GROWS_DOWNWARD
01973
01974
01975
01976 loc = plus_constant (loc, size);
01977 #endif
01978 map->reg_map[regno] = temp
01979 = force_reg (Pmode, force_operand (loc, NULL_RTX));
01980
01981 #ifdef STACK_BOUNDARY
01982 mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
01983 #endif
01984
01985 SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
01986
01987 seq = get_insns ();
01988 end_sequence ();
01989 emit_insn_after (seq, map->insns_at_start);
01990 return temp;
01991 }
01992 else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM
01993 || (map->integrating
01994 && (DECL_SAVED_INSNS (map->fndecl)->internal_arg_pointer
01995 == orig)))
01996 {
01997
01998
01999 rtx loc, seq;
02000 int size = DECL_SAVED_INSNS (map->fndecl)->args_size;
02001
02002 start_sequence ();
02003 loc = assign_stack_temp (BLKmode, size, 1);
02004 loc = XEXP (loc, 0);
02005
02006
02007
02008 #ifdef ARGS_GROW_DOWNWARD
02009 loc = plus_constant (loc, size);
02010 #endif
02011 map->reg_map[regno] = temp
02012 = force_reg (Pmode, force_operand (loc, NULL_RTX));
02013
02014 #ifdef STACK_BOUNDARY
02015 mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
02016 #endif
02017
02018 SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
02019
02020 seq = get_insns ();
02021 end_sequence ();
02022 emit_insn_after (seq, map->insns_at_start);
02023 return temp;
02024 }
02025 else if (REG_FUNCTION_VALUE_P (orig))
02026 {
02027
02028
02029
02030 if (map->inline_target == 0)
02031 {
02032 if (rtx_equal_function_value_matters)
02033
02034
02035
02036
02037 return gen_rtx_REG (GET_MODE (orig), regno);
02038 else
02039
02040
02041 return orig;
02042 }
02043 else if (GET_MODE (map->inline_target) != BLKmode
02044 && mode != GET_MODE (map->inline_target))
02045 return gen_lowpart (mode, map->inline_target);
02046 else
02047 return map->inline_target;
02048 }
02049 #if defined (LEAF_REGISTERS) && defined (LEAF_REG_REMAP)
02050
02051
02052
02053
02054
02055
02056
02057 if (map->integrating && regno < FIRST_PSEUDO_REGISTER
02058 && LEAF_REGISTERS[regno] && LEAF_REG_REMAP (regno) != regno)
02059 {
02060 if (!map->leaf_reg_map[regno][mode])
02061 map->leaf_reg_map[regno][mode] = gen_rtx_REG (mode, regno);
02062 return map->leaf_reg_map[regno][mode];
02063 }
02064 #endif
02065 else
02066 return orig;
02067
02068 abort ();
02069 }
02070 if (map->reg_map[regno] == NULL)
02071 {
02072 map->reg_map[regno] = gen_reg_rtx (mode);
02073 REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
02074 REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
02075 RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
02076
02077
02078 if (REG_POINTER (map->x_regno_reg_rtx[regno]))
02079 mark_reg_pointer (map->reg_map[regno],
02080 map->regno_pointer_align[regno]);
02081 }
02082 return map->reg_map[regno];
02083
02084 case SUBREG:
02085 copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
02086 return simplify_gen_subreg (GET_MODE (orig), copy,
02087 GET_MODE (SUBREG_REG (orig)),
02088 SUBREG_BYTE (orig));
02089
02090 case ADDRESSOF:
02091 copy = gen_rtx_ADDRESSOF (mode,
02092 copy_rtx_and_substitute (XEXP (orig, 0),
02093 map, for_lhs),
02094 0, ADDRESSOF_DECL (orig));
02095 regno = ADDRESSOF_REGNO (orig);
02096 if (map->reg_map[regno])
02097 regno = REGNO (map->reg_map[regno]);
02098 else if (regno > LAST_VIRTUAL_REGISTER)
02099 {
02100 temp = XEXP (orig, 0);
02101 map->reg_map[regno] = gen_reg_rtx (GET_MODE (temp));
02102 REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (temp);
02103 REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (temp);
02104 RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116 if (REG_P (map->x_regno_reg_rtx[regno])
02117 && REG_POINTER (map->x_regno_reg_rtx[regno]))
02118 mark_reg_pointer (map->reg_map[regno],
02119 map->regno_pointer_align[regno]);
02120 regno = REGNO (map->reg_map[regno]);
02121 }
02122 ADDRESSOF_REGNO (copy) = regno;
02123 return copy;
02124
02125 case USE:
02126 case CLOBBER:
02127
02128
02129
02130
02131 copy = copy_rtx_and_substitute (XEXP (orig, 0), map, code == CLOBBER);
02132 if (GET_CODE (copy) == SUBREG && GET_CODE (XEXP (orig, 0)) != SUBREG)
02133 copy = SUBREG_REG (copy);
02134 return gen_rtx_fmt_e (code, VOIDmode, copy);
02135
02136
02137
02138 case NOTE:
02139 if (NOTE_LINE_NUMBER (orig) != NOTE_INSN_DELETED_LABEL)
02140 break;
02141
02142
02143 case CODE_LABEL:
02144 LABEL_PRESERVE_P (get_label_from_map (map, CODE_LABEL_NUMBER (orig)))
02145 = LABEL_PRESERVE_P (orig);
02146 return get_label_from_map (map, CODE_LABEL_NUMBER (orig));
02147
02148 case LABEL_REF:
02149 copy
02150 = gen_rtx_LABEL_REF
02151 (mode,
02152 LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
02153 : get_label_from_map (map, CODE_LABEL_NUMBER (XEXP (orig, 0))));
02154
02155 LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
02156
02157
02158
02159
02160 LABEL_REF_NONLOCAL_P (copy)
02161 = (LABEL_REF_NONLOCAL_P (orig)
02162 && ! (CODE_LABEL_NUMBER (XEXP (copy, 0)) >= get_first_label_num ()
02163 && CODE_LABEL_NUMBER (XEXP (copy, 0)) < max_label_num ()));
02164
02165
02166
02167
02168
02169 if (LABEL_REF_NONLOCAL_P (orig) && ! LABEL_REF_NONLOCAL_P (copy))
02170 function_call_count++;
02171
02172 return copy;
02173
02174 case PC:
02175 case CC0:
02176 case CONST_INT:
02177 case CONST_VECTOR:
02178 return orig;
02179
02180 case SYMBOL_REF:
02181
02182
02183
02184 if (CONSTANT_POOL_ADDRESS_P (orig))
02185 {
02186 struct function *f = inlining ? inlining : cfun;
02187 rtx constant = get_pool_constant_for_function (f, orig);
02188 enum machine_mode const_mode = get_pool_mode_for_function (f, orig);
02189 if (inlining)
02190 {
02191 rtx temp = force_const_mem (const_mode,
02192 copy_rtx_and_substitute (constant,
02193 map, 0));
02194
02195 #if 0
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207 if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
02208 temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
02209 #endif
02210
02211 temp = XEXP (temp, 0);
02212
02213 #ifdef POINTERS_EXTEND_UNSIGNED
02214 if (GET_MODE (temp) != GET_MODE (orig))
02215 temp = convert_memory_address (GET_MODE (orig), temp);
02216 #endif
02217 return temp;
02218 }
02219 else if (GET_CODE (constant) == LABEL_REF)
02220 return XEXP (force_const_mem
02221 (GET_MODE (orig),
02222 copy_rtx_and_substitute (constant, map, for_lhs)),
02223 0);
02224 }
02225
02226 return orig;
02227
02228 case CONST_DOUBLE:
02229
02230
02231
02232 if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
02233 {
02234 REAL_VALUE_TYPE d;
02235
02236 REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
02237 return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (orig));
02238 }
02239 else
02240 return immed_double_const (CONST_DOUBLE_LOW (orig),
02241 CONST_DOUBLE_HIGH (orig), VOIDmode);
02242
02243 case CONST:
02244
02245
02246 if (RTX_INTEGRATED_P (orig))
02247 abort ();
02248 break;
02249
02250 case ASM_OPERANDS:
02251
02252
02253
02254
02255 if (map->orig_asm_operands_vector == ASM_OPERANDS_INPUT_VEC (orig))
02256 {
02257 copy = rtx_alloc (ASM_OPERANDS);
02258 RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
02259 PUT_MODE (copy, GET_MODE (orig));
02260 ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
02261 ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
02262 = ASM_OPERANDS_OUTPUT_CONSTRAINT (orig);
02263 ASM_OPERANDS_OUTPUT_IDX (copy) = ASM_OPERANDS_OUTPUT_IDX (orig);
02264 ASM_OPERANDS_INPUT_VEC (copy) = map->copy_asm_operands_vector;
02265 ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy)
02266 = map->copy_asm_constraints_vector;
02267 ASM_OPERANDS_SOURCE_FILE (copy) = ASM_OPERANDS_SOURCE_FILE (orig);
02268 ASM_OPERANDS_SOURCE_LINE (copy) = ASM_OPERANDS_SOURCE_LINE (orig);
02269 return copy;
02270 }
02271 break;
02272
02273 case CALL:
02274
02275
02276
02277
02278 #ifndef NO_FUNCTION_CSE
02279 if (! (optimize && ! flag_no_function_cse))
02280 #endif
02281 {
02282 rtx copy
02283 = gen_rtx_MEM (GET_MODE (XEXP (orig, 0)),
02284 copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0),
02285 map, 0));
02286
02287 MEM_COPY_ATTRIBUTES (copy, XEXP (orig, 0));
02288
02289 return
02290 gen_rtx_CALL (GET_MODE (orig), copy,
02291 copy_rtx_and_substitute (XEXP (orig, 1), map, 0));
02292 }
02293 break;
02294
02295 #if 0
02296
02297 case RETURN:
02298 abort ();
02299 #endif
02300
02301 case SET:
02302
02303
02304
02305
02306 if (SET_DEST (orig) == virtual_stack_vars_rtx
02307 || SET_DEST (orig) == virtual_incoming_args_rtx)
02308 {
02309
02310 rtx equiv_reg;
02311 rtx equiv_loc;
02312 HOST_WIDE_INT loc_offset;
02313
02314 copy_rtx_and_substitute (SET_DEST (orig), map, for_lhs);
02315 equiv_reg = map->reg_map[REGNO (SET_DEST (orig))];
02316 equiv_loc = VARRAY_CONST_EQUIV (map->const_equiv_varray,
02317 REGNO (equiv_reg)).rtx;
02318 loc_offset
02319 = GET_CODE (equiv_loc) == REG ? 0 : INTVAL (XEXP (equiv_loc, 1));
02320
02321 return gen_rtx_SET (VOIDmode, SET_DEST (orig),
02322 force_operand
02323 (plus_constant
02324 (copy_rtx_and_substitute (SET_SRC (orig),
02325 map, 0),
02326 - loc_offset),
02327 NULL_RTX));
02328 }
02329 else
02330 return gen_rtx_SET (VOIDmode,
02331 copy_rtx_and_substitute (SET_DEST (orig), map, 1),
02332 copy_rtx_and_substitute (SET_SRC (orig), map, 0));
02333 break;
02334
02335 case MEM:
02336 if (inlining
02337 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
02338 && CONSTANT_POOL_ADDRESS_P (XEXP (orig, 0)))
02339 {
02340 enum machine_mode const_mode
02341 = get_pool_mode_for_function (inlining, XEXP (orig, 0));
02342 rtx constant
02343 = get_pool_constant_for_function (inlining, XEXP (orig, 0));
02344
02345 constant = copy_rtx_and_substitute (constant, map, 0);
02346
02347
02348
02349
02350
02351
02352
02353 if (! CONSTANT_P (constant))
02354 return constant;
02355
02356 return validize_mem (force_const_mem (const_mode, constant));
02357 }
02358
02359 copy = gen_rtx_MEM (mode, copy_rtx_and_substitute (XEXP (orig, 0),
02360 map, 0));
02361 MEM_COPY_ATTRIBUTES (copy, orig);
02362
02363
02364
02365
02366 if (inlining && !for_lhs)
02367 RTX_UNCHANGING_P (copy) = 0;
02368
02369
02370
02371 if (inlining && MEM_EXPR (copy)
02372 && TREE_CODE (MEM_EXPR (copy)) == INDIRECT_REF
02373 && TREE_CODE (TREE_OPERAND (MEM_EXPR (copy), 0)) == PARM_DECL)
02374 set_mem_expr (copy, NULL_TREE);
02375
02376 return copy;
02377
02378 default:
02379 break;
02380 }
02381
02382 copy = rtx_alloc (code);
02383 PUT_MODE (copy, mode);
02384 RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
02385 RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
02386 RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
02387
02388 format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
02389
02390 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
02391 {
02392 switch (*format_ptr++)
02393 {
02394 case '0':
02395
02396 X0WINT (copy, i) = X0WINT (orig, i);
02397 break;
02398
02399 case 'e':
02400 XEXP (copy, i)
02401 = copy_rtx_and_substitute (XEXP (orig, i), map, for_lhs);
02402 break;
02403
02404 case 'u':
02405
02406
02407 XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
02408 break;
02409
02410 case 'E':
02411 XVEC (copy, i) = XVEC (orig, i);
02412 if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
02413 {
02414 XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
02415 for (j = 0; j < XVECLEN (copy, i); j++)
02416 XVECEXP (copy, i, j)
02417 = copy_rtx_and_substitute (XVECEXP (orig, i, j),
02418 map, for_lhs);
02419 }
02420 break;
02421
02422 case 'w':
02423 XWINT (copy, i) = XWINT (orig, i);
02424 break;
02425
02426 case 'i':
02427 XINT (copy, i) = XINT (orig, i);
02428 break;
02429
02430 case 's':
02431 XSTR (copy, i) = XSTR (orig, i);
02432 break;
02433
02434 case 't':
02435 XTREE (copy, i) = XTREE (orig, i);
02436 break;
02437
02438 default:
02439 abort ();
02440 }
02441 }
02442
02443 if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
02444 {
02445 map->orig_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (orig);
02446 map->copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
02447 map->copy_asm_constraints_vector
02448 = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
02449 }
02450
02451 return copy;
02452 }
02453
02454
02455
02456 void
02457 try_constants (insn, map)
02458 rtx insn;
02459 struct inline_remap *map;
02460 {
02461 int i;
02462
02463 map->num_sets = 0;
02464
02465
02466
02467
02468
02469 subst_constants (&PATTERN (insn), insn, map, 1);
02470 apply_change_group ();
02471 subst_constants (&PATTERN (insn), insn, map, 0);
02472 apply_change_group ();
02473
02474
02475 note_stores (PATTERN (insn), mark_stores, NULL);
02476 map->last_pc_value = 0;
02477 #ifdef HAVE_cc0
02478 map->last_cc0_value = 0;
02479 #endif
02480
02481
02482 for (i = 0; i < map->num_sets; i++)
02483 {
02484 if (GET_CODE (map->equiv_sets[i].dest) == REG)
02485 {
02486 int regno = REGNO (map->equiv_sets[i].dest);
02487
02488 MAYBE_EXTEND_CONST_EQUIV_VARRAY (map, regno);
02489 if (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).rtx == 0
02490
02491
02492 || ! rtx_equal_p (VARRAY_CONST_EQUIV (map->const_equiv_varray,
02493 regno).rtx,
02494 map->equiv_sets[i].equiv))
02495 SET_CONST_EQUIV_DATA (map, map->equiv_sets[i].dest,
02496 map->equiv_sets[i].equiv, map->const_age);
02497 }
02498 else if (map->equiv_sets[i].dest == pc_rtx)
02499 map->last_pc_value = map->equiv_sets[i].equiv;
02500 #ifdef HAVE_cc0
02501 else if (map->equiv_sets[i].dest == cc0_rtx)
02502 map->last_cc0_value = map->equiv_sets[i].equiv;
02503 #endif
02504 }
02505 }
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522 static void
02523 subst_constants (loc, insn, map, memonly)
02524 rtx *loc;
02525 rtx insn;
02526 struct inline_remap *map;
02527 int memonly;
02528 {
02529 rtx x = *loc;
02530 int i, j;
02531 enum rtx_code code;
02532 const char *format_ptr;
02533 int num_changes = num_validated_changes ();
02534 rtx new = 0;
02535 enum machine_mode op0_mode = MAX_MACHINE_MODE;
02536
02537 code = GET_CODE (x);
02538
02539 switch (code)
02540 {
02541 case PC:
02542 case CONST_INT:
02543 case CONST_DOUBLE:
02544 case CONST_VECTOR:
02545 case SYMBOL_REF:
02546 case CONST:
02547 case LABEL_REF:
02548 case ADDRESS:
02549 return;
02550
02551 #ifdef HAVE_cc0
02552 case CC0:
02553 if (! memonly)
02554 validate_change (insn, loc, map->last_cc0_value, 1);
02555 return;
02556 #endif
02557
02558 case USE:
02559 case CLOBBER:
02560
02561
02562 if (GET_CODE (XEXP (x, 0)) == MEM)
02563 subst_constants (&XEXP (XEXP (x, 0), 0), insn, map, 0);
02564 return;
02565
02566 case REG:
02567
02568
02569 if (! memonly)
02570 {
02571 int regno = REGNO (x);
02572 struct const_equiv_data *p;
02573
02574 if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
02575 && (size_t) regno < VARRAY_SIZE (map->const_equiv_varray)
02576 && (p = &VARRAY_CONST_EQUIV (map->const_equiv_varray, regno),
02577 p->rtx != 0)
02578 && p->age >= map->const_age)
02579 validate_change (insn, loc, p->rtx, 1);
02580 }
02581 return;
02582
02583 case SUBREG:
02584
02585
02586
02587
02588
02589 if (! memonly && GET_CODE (SUBREG_REG (x)) == REG)
02590 {
02591 rtx inner = SUBREG_REG (x);
02592 rtx new = 0;
02593
02594
02595
02596
02597
02598
02599 subst_constants (&inner, NULL_RTX, map, 0);
02600 new = simplify_gen_subreg (GET_MODE (x), inner,
02601 GET_MODE (SUBREG_REG (x)),
02602 SUBREG_BYTE (x));
02603
02604 if (new)
02605 validate_change (insn, loc, new, 1);
02606 else
02607 cancel_changes (num_changes);
02608
02609 return;
02610 }
02611 break;
02612
02613 case MEM:
02614 subst_constants (&XEXP (x, 0), insn, map, 0);
02615
02616
02617 if (! memonly && insn != 0 && num_validated_changes () != num_changes
02618 && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
02619 cancel_changes (num_changes);
02620 return;
02621
02622 case SET:
02623 {
02624
02625
02626
02627 rtx *dest_loc = &SET_DEST (x);
02628 rtx dest = *dest_loc;
02629 rtx src, tem;
02630 enum machine_mode compare_mode = VOIDmode;
02631
02632
02633
02634
02635 if (GET_CODE (SET_SRC (x)) == COMPARE)
02636 {
02637 src = SET_SRC (x);
02638 if (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
02639 #ifdef HAVE_cc0
02640 || dest == cc0_rtx
02641 #endif
02642 )
02643 {
02644 compare_mode = GET_MODE (XEXP (src, 0));
02645 if (compare_mode == VOIDmode)
02646 compare_mode = GET_MODE (XEXP (src, 1));
02647 }
02648 }
02649
02650 subst_constants (&SET_SRC (x), insn, map, memonly);
02651 src = SET_SRC (x);
02652
02653 while (GET_CODE (*dest_loc) == ZERO_EXTRACT
02654 || GET_CODE (*dest_loc) == SUBREG
02655 || GET_CODE (*dest_loc) == STRICT_LOW_PART)
02656 {
02657 if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
02658 {
02659 subst_constants (&XEXP (*dest_loc, 1), insn, map, memonly);
02660 subst_constants (&XEXP (*dest_loc, 2), insn, map, memonly);
02661 }
02662 dest_loc = &XEXP (*dest_loc, 0);
02663 }
02664
02665
02666 if (GET_CODE (*dest_loc) == MEM)
02667 subst_constants (&XEXP (*dest_loc, 0), insn, map, 0);
02668
02669
02670
02671
02672
02673 if (GET_CODE (dest) == SUBREG
02674 && GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
02675 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
02676 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
02677 <= GET_MODE_SIZE (GET_MODE (dest)))
02678 && (tem = gen_lowpart_if_possible (GET_MODE (SUBREG_REG (dest)),
02679 src)))
02680 src = tem, dest = SUBREG_REG (dest);
02681
02682
02683 if ((map->num_sets < MAX_RECOG_OPERANDS)
02684 && (CONSTANT_P (src)
02685 || (GET_CODE (src) == REG
02686 && (REGNO (src) == VIRTUAL_INCOMING_ARGS_REGNUM
02687 || REGNO (src) == VIRTUAL_STACK_VARS_REGNUM))
02688 || (GET_CODE (src) == PLUS
02689 && GET_CODE (XEXP (src, 0)) == REG
02690 && (REGNO (XEXP (src, 0)) == VIRTUAL_INCOMING_ARGS_REGNUM
02691 || REGNO (XEXP (src, 0)) == VIRTUAL_STACK_VARS_REGNUM)
02692 && CONSTANT_P (XEXP (src, 1)))
02693 || GET_CODE (src) == COMPARE
02694 #ifdef HAVE_cc0
02695 || dest == cc0_rtx
02696 #endif
02697 || (dest == pc_rtx
02698 && (src == pc_rtx || GET_CODE (src) == RETURN
02699 || GET_CODE (src) == LABEL_REF))))
02700 {
02701
02702
02703
02704 rtx src_copy = copy_rtx (src);
02705 map->equiv_sets[map->num_sets].equiv = src_copy;
02706 map->equiv_sets[map->num_sets++].dest = dest;
02707 if (compare_mode != VOIDmode
02708 && GET_CODE (src) == COMPARE
02709 && (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
02710 #ifdef HAVE_cc0
02711 || dest == cc0_rtx
02712 #endif
02713 )
02714 && GET_MODE (XEXP (src, 0)) == VOIDmode
02715 && GET_MODE (XEXP (src, 1)) == VOIDmode)
02716 {
02717 map->compare_src = src_copy;
02718 map->compare_mode = compare_mode;
02719 }
02720 }
02721 }
02722 return;
02723
02724 default:
02725 break;
02726 }
02727
02728 format_ptr = GET_RTX_FORMAT (code);
02729
02730
02731 if (*format_ptr == 'e')
02732 op0_mode = GET_MODE (XEXP (x, 0));
02733
02734 for (i = 0; i < GET_RTX_LENGTH (code); i++)
02735 {
02736 switch (*format_ptr++)
02737 {
02738 case '0':
02739 break;
02740
02741 case 'e':
02742 if (XEXP (x, i))
02743 subst_constants (&XEXP (x, i), insn, map, memonly);
02744 break;
02745
02746 case 'u':
02747 case 'i':
02748 case 's':
02749 case 'w':
02750 case 'n':
02751 case 't':
02752 case 'B':
02753 break;
02754
02755 case 'E':
02756 if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
02757 for (j = 0; j < XVECLEN (x, i); j++)
02758 subst_constants (&XVECEXP (x, i, j), insn, map, memonly);
02759
02760 break;
02761
02762 default:
02763 abort ();
02764 }
02765 }
02766
02767
02768
02769 if (! memonly
02770 && (GET_RTX_CLASS (code) == 'c' || code == NE || code == EQ)
02771 && CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
02772 {
02773 rtx tem = XEXP (x, 0);
02774 validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
02775 validate_change (insn, &XEXP (x, 1), tem, 1);
02776 }
02777
02778
02779 if (! memonly)
02780 switch (GET_RTX_CLASS (code))
02781 {
02782 case '1':
02783 if (op0_mode == MAX_MACHINE_MODE)
02784 abort ();
02785 new = simplify_unary_operation (code, GET_MODE (x),
02786 XEXP (x, 0), op0_mode);
02787 break;
02788
02789 case '<':
02790 {
02791 enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
02792
02793 if (op_mode == VOIDmode)
02794 op_mode = GET_MODE (XEXP (x, 1));
02795 new = simplify_relational_operation (code, op_mode,
02796 XEXP (x, 0), XEXP (x, 1));
02797 #ifdef FLOAT_STORE_FLAG_VALUE
02798 if (new != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
02799 {
02800 enum machine_mode mode = GET_MODE (x);
02801 if (new == const0_rtx)
02802 new = CONST0_RTX (mode);
02803 else
02804 {
02805 REAL_VALUE_TYPE val;
02806
02807
02808 val = FLOAT_STORE_FLAG_VALUE (mode);
02809 new = CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
02810 }
02811 }
02812 #endif
02813 break;
02814 }
02815
02816 case '2':
02817 case 'c':
02818 new = simplify_binary_operation (code, GET_MODE (x),
02819 XEXP (x, 0), XEXP (x, 1));
02820 break;
02821
02822 case 'b':
02823 case '3':
02824 if (op0_mode == MAX_MACHINE_MODE)
02825 abort ();
02826
02827 if (code == IF_THEN_ELSE)
02828 {
02829 rtx op0 = XEXP (x, 0);
02830
02831 if (GET_RTX_CLASS (GET_CODE (op0)) == '<'
02832 && GET_MODE (op0) == VOIDmode
02833 && ! side_effects_p (op0)
02834 && XEXP (op0, 0) == map->compare_src
02835 && GET_MODE (XEXP (op0, 1)) == VOIDmode)
02836 {
02837
02838
02839 rtx temp =
02840 simplify_relational_operation (GET_CODE (op0),
02841 map->compare_mode,
02842 XEXP (op0, 0),
02843 XEXP (op0, 1));
02844
02845 if (temp == const0_rtx)
02846 new = XEXP (x, 2);
02847 else if (temp == const1_rtx)
02848 new = XEXP (x, 1);
02849 }
02850 }
02851 if (!new)
02852 new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
02853 XEXP (x, 0), XEXP (x, 1),
02854 XEXP (x, 2));
02855 break;
02856 }
02857
02858 if (new)
02859 validate_change (insn, loc, new, 1);
02860 }
02861
02862
02863
02864
02865 static void
02866 mark_stores (dest, x, data)
02867 rtx dest;
02868 rtx x ATTRIBUTE_UNUSED;
02869 void *data ATTRIBUTE_UNUSED;
02870 {
02871 int regno = -1;
02872 enum machine_mode mode = VOIDmode;
02873
02874
02875
02876
02877 if (GET_CODE (dest) == REG)
02878 regno = REGNO (dest), mode = GET_MODE (dest);
02879 else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
02880 {
02881 regno = REGNO (SUBREG_REG (dest));
02882 if (regno < FIRST_PSEUDO_REGISTER)
02883 regno += subreg_regno_offset (REGNO (SUBREG_REG (dest)),
02884 GET_MODE (SUBREG_REG (dest)),
02885 SUBREG_BYTE (dest),
02886 GET_MODE (dest));
02887 mode = GET_MODE (SUBREG_REG (dest));
02888 }
02889
02890 if (regno >= 0)
02891 {
02892 unsigned int uregno = regno;
02893 unsigned int last_reg = (uregno >= FIRST_PSEUDO_REGISTER ? uregno
02894 : uregno + HARD_REGNO_NREGS (uregno, mode) - 1);
02895 unsigned int i;
02896
02897
02898
02899 if (uregno != VIRTUAL_INCOMING_ARGS_REGNUM
02900 && uregno != VIRTUAL_STACK_VARS_REGNUM)
02901 for (i = uregno; i <= last_reg; i++)
02902 if ((size_t) i < VARRAY_SIZE (global_const_equiv_varray))
02903 VARRAY_CONST_EQUIV (global_const_equiv_varray, i).rtx = 0;
02904 }
02905 }
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917 static void
02918 set_block_origin_self (stmt)
02919 tree stmt;
02920 {
02921 if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
02922 {
02923 BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
02924
02925 {
02926 tree local_decl;
02927
02928 for (local_decl = BLOCK_VARS (stmt);
02929 local_decl != NULL_TREE;
02930 local_decl = TREE_CHAIN (local_decl))
02931 set_decl_origin_self (local_decl);
02932 }
02933
02934 {
02935 tree subblock;
02936
02937 for (subblock = BLOCK_SUBBLOCKS (stmt);
02938 subblock != NULL_TREE;
02939 subblock = BLOCK_CHAIN (subblock))
02940 set_block_origin_self (subblock);
02941 }
02942 }
02943 }
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956 void
02957 set_decl_origin_self (decl)
02958 tree decl;
02959 {
02960 if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
02961 {
02962 DECL_ABSTRACT_ORIGIN (decl) = decl;
02963 if (TREE_CODE (decl) == FUNCTION_DECL)
02964 {
02965 tree arg;
02966
02967 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
02968 DECL_ABSTRACT_ORIGIN (arg) = arg;
02969 if (DECL_INITIAL (decl) != NULL_TREE
02970 && DECL_INITIAL (decl) != error_mark_node)
02971 set_block_origin_self (DECL_INITIAL (decl));
02972 }
02973 }
02974 }
02975
02976
02977
02978
02979
02980
02981 static void
02982 set_block_abstract_flags (stmt, setting)
02983 tree stmt;
02984 int setting;
02985 {
02986 tree local_decl;
02987 tree subblock;
02988
02989 BLOCK_ABSTRACT (stmt) = setting;
02990
02991 for (local_decl = BLOCK_VARS (stmt);
02992 local_decl != NULL_TREE;
02993 local_decl = TREE_CHAIN (local_decl))
02994 set_decl_abstract_flags (local_decl, setting);
02995
02996 for (subblock = BLOCK_SUBBLOCKS (stmt);
02997 subblock != NULL_TREE;
02998 subblock = BLOCK_CHAIN (subblock))
02999 set_block_abstract_flags (subblock, setting);
03000 }
03001
03002
03003
03004
03005
03006
03007
03008 void
03009 set_decl_abstract_flags (decl, setting)
03010 tree decl;
03011 int setting;
03012 {
03013 DECL_ABSTRACT (decl) = setting;
03014 if (TREE_CODE (decl) == FUNCTION_DECL)
03015 {
03016 tree arg;
03017
03018 for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
03019 DECL_ABSTRACT (arg) = setting;
03020 if (DECL_INITIAL (decl) != NULL_TREE
03021 && DECL_INITIAL (decl) != error_mark_node)
03022 set_block_abstract_flags (DECL_INITIAL (decl), setting);
03023 }
03024 }
03025
03026
03027
03028
03029
03030 static GTY(()) struct function *old_cfun;
03031
03032 void
03033 output_inline_function (fndecl)
03034 tree fndecl;
03035 {
03036 enum debug_info_type old_write_symbols = write_symbols;
03037 const struct gcc_debug_hooks *const old_debug_hooks = debug_hooks;
03038 struct function *f = DECL_SAVED_INSNS (fndecl);
03039
03040 old_cfun = cfun;
03041 cfun = f;
03042 current_function_decl = fndecl;
03043
03044 set_new_last_label_num (f->inl_max_label_num);
03045
03046
03047 DECL_DEFER_OUTPUT (fndecl) = 0;
03048
03049
03050 if (f->no_debugging_symbols)
03051 {
03052 write_symbols = NO_DEBUG;
03053 debug_hooks = &do_nothing_debug_hooks;
03054 }
03055
03056
03057
03058 input_filename = DECL_SOURCE_FILE (fndecl);
03059 lineno = DECL_SOURCE_LINE (fndecl);
03060
03061
03062
03063
03064 rest_of_compilation (fndecl);
03065 DECL_INLINE (fndecl) = 0;
03066
03067 cfun = old_cfun;
03068 current_function_decl = old_cfun ? old_cfun->decl : 0;
03069 write_symbols = old_write_symbols;
03070 debug_hooks = old_debug_hooks;
03071 }
03072
03073
03074
03075
03076
03077 rtx
03078 get_hard_reg_initial_reg (fun, reg)
03079 struct function *fun;
03080 rtx reg;
03081 {
03082 struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
03083 int i;
03084
03085 if (ivs == 0)
03086 return NULL_RTX;
03087
03088 for (i = 0; i < ivs->num_entries; i++)
03089 if (rtx_equal_p (ivs->entries[i].pseudo, reg))
03090 return ivs->entries[i].hard_reg;
03091
03092 return NULL_RTX;
03093 }
03094
03095 rtx
03096 has_func_hard_reg_initial_val (fun, reg)
03097 struct function *fun;
03098 rtx reg;
03099 {
03100 struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
03101 int i;
03102
03103 if (ivs == 0)
03104 return NULL_RTX;
03105
03106 for (i = 0; i < ivs->num_entries; i++)
03107 if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
03108 return ivs->entries[i].pseudo;
03109
03110 return NULL_RTX;
03111 }
03112
03113 rtx
03114 get_func_hard_reg_initial_val (fun, reg)
03115 struct function *fun;
03116 rtx reg;
03117 {
03118 struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
03119 rtx rv = has_func_hard_reg_initial_val (fun, reg);
03120
03121 if (rv)
03122 return rv;
03123
03124 if (ivs == 0)
03125 {
03126 fun->hard_reg_initial_vals = (void *) ggc_alloc (sizeof (initial_value_struct));
03127 ivs = fun->hard_reg_initial_vals;
03128 ivs->num_entries = 0;
03129 ivs->max_entries = 5;
03130 ivs->entries = (initial_value_pair *) ggc_alloc (5 * sizeof (initial_value_pair));
03131 }
03132
03133 if (ivs->num_entries >= ivs->max_entries)
03134 {
03135 ivs->max_entries += 5;
03136 ivs->entries =
03137 (initial_value_pair *) ggc_realloc (ivs->entries,
03138 ivs->max_entries
03139 * sizeof (initial_value_pair));
03140 }
03141
03142 ivs->entries[ivs->num_entries].hard_reg = reg;
03143 ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (GET_MODE (reg));
03144
03145 return ivs->entries[ivs->num_entries++].pseudo;
03146 }
03147
03148 rtx
03149 get_hard_reg_initial_val (mode, regno)
03150 enum machine_mode mode;
03151 int regno;
03152 {
03153 return get_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
03154 }
03155
03156 rtx
03157 has_hard_reg_initial_val (mode, regno)
03158 enum machine_mode mode;
03159 int regno;
03160 {
03161 return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
03162 }
03163
03164 static void
03165 setup_initial_hard_reg_value_integration (inl_f, remap)
03166 struct function *inl_f;
03167 struct inline_remap *remap;
03168 {
03169 struct initial_value_struct *ivs = inl_f->hard_reg_initial_vals;
03170 int i;
03171
03172 if (ivs == 0)
03173 return;
03174
03175 for (i = 0; i < ivs->num_entries; i ++)
03176 remap->reg_map[REGNO (ivs->entries[i].pseudo)]
03177 = get_func_hard_reg_initial_val (cfun, ivs->entries[i].hard_reg);
03178 }
03179
03180
03181 void
03182 emit_initial_value_sets ()
03183 {
03184 struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
03185 int i;
03186 rtx seq;
03187
03188 if (ivs == 0)
03189 return;
03190
03191 start_sequence ();
03192 for (i = 0; i < ivs->num_entries; i++)
03193 emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
03194 seq = get_insns ();
03195 end_sequence ();
03196
03197 emit_insn_after (seq, get_insns ());
03198 }
03199
03200
03201
03202 void
03203 allocate_initial_values (reg_equiv_memory_loc)
03204 rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED;
03205 {
03206 #ifdef ALLOCATE_INITIAL_VALUE
03207 struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
03208 int i;
03209
03210 if (ivs == 0)
03211 return;
03212
03213 for (i = 0; i < ivs->num_entries; i++)
03214 {
03215 int regno = REGNO (ivs->entries[i].pseudo);
03216 rtx x = ALLOCATE_INITIAL_VALUE (ivs->entries[i].hard_reg);
03217
03218 if (x == NULL_RTX || REG_N_SETS (REGNO (ivs->entries[i].pseudo)) > 1)
03219 ;
03220 else if (GET_CODE (x) == MEM)
03221 reg_equiv_memory_loc[regno] = x;
03222 else if (GET_CODE (x) == REG)
03223 {
03224 reg_renumber[regno] = REGNO (x);
03225
03226
03227 REGNO (ivs->entries[i].pseudo) = REGNO (x);
03228 }
03229 else abort ();
03230 }
03231 #endif
03232 }
03233
03234 #include "gt-integrate.h"