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