OSDN Git Service

* config/rs6000/rs6000.md (andsi3): Add attribute "compare" for
[pf3gnuchains/gcc-fork.git] / gcc / integrate.c
1 /* Procedure integration for GCC.
2    Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4    Contributed by Michael Tiemann (tiemann@cygnus.com)
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27
28 #include "rtl.h"
29 #include "tree.h"
30 #include "tm_p.h"
31 #include "regs.h"
32 #include "flags.h"
33 #include "debug.h"
34 #include "insn-config.h"
35 #include "expr.h"
36 #include "output.h"
37 #include "recog.h"
38 #include "integrate.h"
39 #include "real.h"
40 #include "except.h"
41 #include "function.h"
42 #include "toplev.h"
43 #include "intl.h"
44 #include "params.h"
45 #include "ggc.h"
46 #include "target.h"
47 #include "langhooks.h"
48
49 /* Round to the next highest integer that meets the alignment.  */
50 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
51 \f
52
53 /* Private type used by {get/has}_func_hard_reg_initial_val.  */
54 typedef struct initial_value_pair GTY(()) {
55   rtx hard_reg;
56   rtx pseudo;
57 } initial_value_pair;
58 typedef struct initial_value_struct GTY(()) {
59   int num_entries;
60   int max_entries;
61   initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
62 } initial_value_struct;
63
64 static void set_block_origin_self (tree);
65 static void set_block_abstract_flags (tree, int);
66 \f
67 /* Returns the Ith entry in the label_map contained in MAP.  If the
68    Ith entry has not yet been set, return a fresh label.  This function
69    performs a lazy initialization of label_map, thereby avoiding huge memory
70    explosions when the label_map gets very large.  */
71
72 rtx
73 get_label_from_map (struct inline_remap *map, int i)
74 {
75   rtx x = map->label_map[i];
76
77   if (x == NULL_RTX)
78     x = map->label_map[i] = gen_label_rtx ();
79
80   return x;
81 }
82
83 /* Return false if the function FNDECL cannot be inlined on account of its
84    attributes, true otherwise.  */
85 bool
86 function_attribute_inlinable_p (tree fndecl)
87 {
88   if (targetm.attribute_table)
89     {
90       tree a;
91
92       for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
93         {
94           tree name = TREE_PURPOSE (a);
95           int i;
96
97           for (i = 0; targetm.attribute_table[i].name != NULL; i++)
98             if (is_attribute_p (targetm.attribute_table[i].name, name))
99               return targetm.function_attribute_inlinable_p (fndecl);
100         }
101     }
102
103   return true;
104 }
105 \f
106 /* Copy NODE (which must be a DECL).  The DECL originally was in the FROM_FN,
107    but now it will be in the TO_FN.  */
108
109 tree
110 copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn)
111 {
112   tree copy;
113
114   /* Copy the declaration.  */
115   if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
116     {
117       tree type = TREE_TYPE (decl);
118
119       /* For a parameter or result, we must make an equivalent VAR_DECL, not a
120          new PARM_DECL.  */
121       copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
122       TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
123       TREE_READONLY (copy) = TREE_READONLY (decl);
124       TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
125     }
126   else
127     {
128       copy = copy_node (decl);
129       /* The COPY is not abstract; it will be generated in TO_FN.  */
130       DECL_ABSTRACT (copy) = 0;
131       lang_hooks.dup_lang_specific_decl (copy);
132
133       /* TREE_ADDRESSABLE isn't used to indicate that a label's
134          address has been taken; it's for internal bookkeeping in
135          expand_goto_internal.  */
136       if (TREE_CODE (copy) == LABEL_DECL)
137         {
138           TREE_ADDRESSABLE (copy) = 0;
139         }
140     }
141
142   /* Don't generate debug information for the copy if we wouldn't have
143      generated it for the copy either.  */
144   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl);
145   DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl);
146
147   /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what
148      declaration inspired this copy.  */
149   DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
150
151   /* The new variable/label has no RTL, yet.  */
152   if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
153     SET_DECL_RTL (copy, NULL_RTX);
154
155   /* These args would always appear unused, if not for this.  */
156   TREE_USED (copy) = 1;
157
158   /* Set the context for the new declaration.  */
159   if (!DECL_CONTEXT (decl))
160     /* Globals stay global.  */
161     ;
162   else if (DECL_CONTEXT (decl) != from_fn)
163     /* Things that weren't in the scope of the function we're inlining
164        from aren't in the scope we're inlining to, either.  */
165     ;
166   else if (TREE_STATIC (decl))
167     /* Function-scoped static variables should stay in the original
168        function.  */
169     ;
170   else
171     /* Ordinary automatic local variables are now in the scope of the
172        new function.  */
173     DECL_CONTEXT (copy) = to_fn;
174
175   return copy;
176 }
177 \f
178 /* Unfortunately, we need a global copy of const_equiv map for communication
179    with a function called from note_stores.  Be *very* careful that this
180    is used properly in the presence of recursion.  */
181
182 varray_type global_const_equiv_varray;
183
184 /* Create a new copy of an rtx. Recursively copies the operands of the rtx,
185    except for those few rtx codes that are sharable.
186
187    We always return an rtx that is similar to that incoming rtx, with the
188    exception of possibly changing a REG to a SUBREG or vice versa.  No
189    rtl is ever emitted.
190
191    If FOR_LHS is nonzero, if means we are processing something that will
192    be the LHS of a SET.
193
194    Handle constants that need to be placed in the constant pool by
195    calling `force_const_mem'.  */
196
197 rtx
198 copy_rtx_and_substitute (rtx orig, struct inline_remap *map, int for_lhs)
199 {
200   rtx copy, temp;
201   int i, j;
202   RTX_CODE code;
203   enum machine_mode mode;
204   const char *format_ptr;
205   int regno;
206
207   if (orig == 0)
208     return 0;
209
210   code = GET_CODE (orig);
211   mode = GET_MODE (orig);
212
213   switch (code)
214     {
215     case REG:
216       /* If the stack pointer register shows up, it must be part of
217          stack-adjustments (*not* because we eliminated the frame pointer!).
218          Small hard registers are returned as-is.  Pseudo-registers
219          go through their `reg_map'.  */
220       regno = REGNO (orig);
221       if (regno <= LAST_VIRTUAL_REGISTER)
222         {
223           /* Some hard registers are also mapped,
224              but others are not translated.  */
225           if (map->reg_map[regno] != 0)
226             return map->reg_map[regno];
227
228           /* If this is the virtual frame pointer, make space in current
229              function's stack frame for the stack frame of the inline function.
230
231              Copy the address of this area into a pseudo.  Map
232              virtual_stack_vars_rtx to this pseudo and set up a constant
233              equivalence for it to be the address.  This will substitute the
234              address into insns where it can be substituted and use the new
235              pseudo where it can't.  */
236           else if (regno == VIRTUAL_STACK_VARS_REGNUM)
237             {
238               rtx loc, seq;
239               int size
240                 = get_func_frame_size (DECL_STRUCT_FUNCTION (map->fndecl));
241 #ifdef FRAME_GROWS_DOWNWARD
242               int alignment
243                 = (DECL_STRUCT_FUNCTION (map->fndecl)->stack_alignment_needed
244                    / BITS_PER_UNIT);
245
246               /* In this case, virtual_stack_vars_rtx points to one byte
247                  higher than the top of the frame area.  So make sure we
248                  allocate a big enough chunk to keep the frame pointer
249                  aligned like a real one.  */
250               if (alignment)
251                 size = CEIL_ROUND (size, alignment);
252 #endif
253               start_sequence ();
254               loc = assign_stack_temp (BLKmode, size, 1);
255               loc = XEXP (loc, 0);
256 #ifdef FRAME_GROWS_DOWNWARD
257               /* In this case, virtual_stack_vars_rtx points to one byte
258                  higher than the top of the frame area.  So compute the offset
259                  to one byte higher than our substitute frame.  */
260               loc = plus_constant (loc, size);
261 #endif
262               map->reg_map[regno] = temp
263                 = force_reg (Pmode, force_operand (loc, NULL_RTX));
264
265 #ifdef STACK_BOUNDARY
266               mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
267 #endif
268
269               SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
270
271               seq = get_insns ();
272               end_sequence ();
273               emit_insn_after (seq, map->insns_at_start);
274               return temp;
275             }
276           else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
277             {
278               /* Do the same for a block to contain any arguments referenced
279                  in memory.  */
280               rtx loc, seq;
281               int size = DECL_STRUCT_FUNCTION (map->fndecl)->args_size;
282
283               start_sequence ();
284               loc = assign_stack_temp (BLKmode, size, 1);
285               loc = XEXP (loc, 0);
286               /* When arguments grow downward, the virtual incoming
287                  args pointer points to the top of the argument block,
288                  so the remapped location better do the same.  */
289 #ifdef ARGS_GROW_DOWNWARD
290               loc = plus_constant (loc, size);
291 #endif
292               map->reg_map[regno] = temp
293                 = force_reg (Pmode, force_operand (loc, NULL_RTX));
294
295 #ifdef STACK_BOUNDARY
296               mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
297 #endif
298
299               SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
300
301               seq = get_insns ();
302               end_sequence ();
303               emit_insn_after (seq, map->insns_at_start);
304               return temp;
305             }
306           else
307             return orig;
308
309           abort ();
310         }
311       if (map->reg_map[regno] == NULL)
312         {
313           map->reg_map[regno] = gen_reg_rtx (mode);
314           REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
315           REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
316           /* A reg with REG_FUNCTION_VALUE_P true will never reach here.  */
317
318           if (REG_POINTER (map->x_regno_reg_rtx[regno]))
319             mark_reg_pointer (map->reg_map[regno],
320                               map->regno_pointer_align[regno]);
321         }
322       return map->reg_map[regno];
323
324     case SUBREG:
325       copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
326       return simplify_gen_subreg (GET_MODE (orig), copy,
327                                   GET_MODE (SUBREG_REG (orig)),
328                                   SUBREG_BYTE (orig));
329
330     case USE:
331     case CLOBBER:
332       /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
333          to (use foo) if the original insn didn't have a subreg.
334          Removing the subreg distorts the VAX movmemhi pattern
335          by changing the mode of an operand.  */
336       copy = copy_rtx_and_substitute (XEXP (orig, 0), map, code == CLOBBER);
337       if (GET_CODE (copy) == SUBREG && GET_CODE (XEXP (orig, 0)) != SUBREG)
338         copy = SUBREG_REG (copy);
339       return gen_rtx_fmt_e (code, VOIDmode, copy);
340
341     /* We need to handle "deleted" labels that appear in the DECL_RTL
342        of a LABEL_DECL.  */
343     case NOTE:
344       if (NOTE_LINE_NUMBER (orig) != NOTE_INSN_DELETED_LABEL)
345         break;
346
347       /* Fall through.  */
348     case CODE_LABEL:
349       LABEL_PRESERVE_P (get_label_from_map (map, CODE_LABEL_NUMBER (orig)))
350         = LABEL_PRESERVE_P (orig);
351       return get_label_from_map (map, CODE_LABEL_NUMBER (orig));
352
353     case LABEL_REF:
354       copy
355         = gen_rtx_LABEL_REF
356           (mode,
357            LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
358            : get_label_from_map (map, CODE_LABEL_NUMBER (XEXP (orig, 0))));
359
360       LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
361
362       /* The fact that this label was previously nonlocal does not mean
363          it still is, so we must check if it is within the range of
364          this function's labels.  */
365       LABEL_REF_NONLOCAL_P (copy)
366         = (LABEL_REF_NONLOCAL_P (orig)
367            && ! (CODE_LABEL_NUMBER (XEXP (copy, 0)) >= get_first_label_num ()
368                  && CODE_LABEL_NUMBER (XEXP (copy, 0)) < max_label_num ()));
369
370       return copy;
371
372     case PC:
373     case CC0:
374     case CONST_INT:
375     case CONST_VECTOR:
376       return orig;
377
378     case SYMBOL_REF:
379       /* Symbols which represent the address of a label stored in the constant
380          pool must be modified to point to a constant pool entry for the
381          remapped label.  Otherwise, symbols are returned unchanged.  */
382       if (CONSTANT_POOL_ADDRESS_P (orig))
383         {
384           struct function *f = cfun;
385           rtx constant = get_pool_constant_for_function (f, orig);
386           if (GET_CODE (constant) == LABEL_REF)
387             return XEXP (force_const_mem
388                          (GET_MODE (orig),
389                           copy_rtx_and_substitute (constant, map, for_lhs)),
390                          0);
391         }
392       return orig;
393
394     case CONST_DOUBLE:
395       /* We have to make a new copy of this CONST_DOUBLE because don't want
396          to use the old value of CONST_DOUBLE_MEM.  Also, this may be a
397          duplicate of a CONST_DOUBLE we have already seen.  */
398       if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
399         {
400           REAL_VALUE_TYPE d;
401
402           REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
403           return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (orig));
404         }
405       else
406         return immed_double_const (CONST_DOUBLE_LOW (orig),
407                                    CONST_DOUBLE_HIGH (orig), VOIDmode);
408
409     case CONST:
410       break;
411
412     case ASM_OPERANDS:
413       /* If a single asm insn contains multiple output operands then
414          it contains multiple ASM_OPERANDS rtx's that share the input
415          and constraint vecs.  We must make sure that the copied insn
416          continues to share it.  */
417       if (map->orig_asm_operands_vector == ASM_OPERANDS_INPUT_VEC (orig))
418         {
419           copy = rtx_alloc (ASM_OPERANDS);
420           RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
421           PUT_MODE (copy, GET_MODE (orig));
422           ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
423           ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
424             = ASM_OPERANDS_OUTPUT_CONSTRAINT (orig);
425           ASM_OPERANDS_OUTPUT_IDX (copy) = ASM_OPERANDS_OUTPUT_IDX (orig);
426           ASM_OPERANDS_INPUT_VEC (copy) = map->copy_asm_operands_vector;
427           ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy)
428             = map->copy_asm_constraints_vector;
429 #ifdef USE_MAPPED_LOCATION
430           ASM_OPERANDS_SOURCE_LOCATION (copy)
431             = ASM_OPERANDS_SOURCE_LOCATION (orig);
432 #else
433           ASM_OPERANDS_SOURCE_FILE (copy) = ASM_OPERANDS_SOURCE_FILE (orig);
434           ASM_OPERANDS_SOURCE_LINE (copy) = ASM_OPERANDS_SOURCE_LINE (orig);
435 #endif
436           return copy;
437         }
438       break;
439
440     case CALL:
441       /* This is given special treatment because the first
442          operand of a CALL is a (MEM ...) which may get
443          forced into a register for cse.  This is undesirable
444          if function-address cse isn't wanted or if we won't do cse.  */
445 #ifndef NO_FUNCTION_CSE
446       if (! (optimize && ! flag_no_function_cse))
447 #endif
448         {
449           rtx copy
450             = gen_rtx_MEM (GET_MODE (XEXP (orig, 0)),
451                            copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0),
452                                                     map, 0));
453
454           MEM_COPY_ATTRIBUTES (copy, XEXP (orig, 0));
455
456           return
457             gen_rtx_CALL (GET_MODE (orig), copy,
458                           copy_rtx_and_substitute (XEXP (orig, 1), map, 0));
459         }
460       break;
461
462 #if 0
463     /* Must be ifdefed out for loop unrolling to work.  */
464     /* ??? Is this for the old or the new unroller?  */
465     case RETURN:
466       abort ();
467 #endif
468
469     case SET:
470       /* If this is setting fp or ap, it means that we have a nonlocal goto.
471          Adjust the setting by the offset of the area we made.
472          If the nonlocal goto is into the current function,
473          this will result in unnecessarily bad code, but should work.  */
474       if (SET_DEST (orig) == virtual_stack_vars_rtx
475           || SET_DEST (orig) == virtual_incoming_args_rtx)
476         {
477           /* In case a translation hasn't occurred already, make one now.  */
478           rtx equiv_reg;
479           rtx equiv_loc;
480           HOST_WIDE_INT loc_offset;
481
482           copy_rtx_and_substitute (SET_DEST (orig), map, for_lhs);
483           equiv_reg = map->reg_map[REGNO (SET_DEST (orig))];
484           equiv_loc = VARRAY_CONST_EQUIV (map->const_equiv_varray,
485                                           REGNO (equiv_reg)).rtx;
486           loc_offset
487             = REG_P (equiv_loc) ? 0 : INTVAL (XEXP (equiv_loc, 1));
488
489           return gen_rtx_SET (VOIDmode, SET_DEST (orig),
490                               force_operand
491                               (plus_constant
492                                (copy_rtx_and_substitute (SET_SRC (orig),
493                                                          map, 0),
494                                 - loc_offset),
495                                NULL_RTX));
496         }
497       else
498         return gen_rtx_SET (VOIDmode,
499                             copy_rtx_and_substitute (SET_DEST (orig), map, 1),
500                             copy_rtx_and_substitute (SET_SRC (orig), map, 0));
501       break;
502
503     case MEM:
504       copy = gen_rtx_MEM (mode, copy_rtx_and_substitute (XEXP (orig, 0),
505                                                          map, 0));
506       MEM_COPY_ATTRIBUTES (copy, orig);
507       return copy;
508
509     default:
510       break;
511     }
512
513   copy = rtx_alloc (code);
514   PUT_MODE (copy, mode);
515   RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
516   RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
517   RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
518
519   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
520
521   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
522     {
523       switch (*format_ptr++)
524         {
525         case '0':
526           X0ANY (copy, i) = X0ANY (orig, i);
527           break;
528
529         case 'e':
530           XEXP (copy, i)
531             = copy_rtx_and_substitute (XEXP (orig, i), map, for_lhs);
532           break;
533
534         case 'u':
535           /* Change any references to old-insns to point to the
536              corresponding copied insns.  */
537           XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
538           break;
539
540         case 'E':
541           XVEC (copy, i) = XVEC (orig, i);
542           if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
543             {
544               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
545               for (j = 0; j < XVECLEN (copy, i); j++)
546                 XVECEXP (copy, i, j)
547                   = copy_rtx_and_substitute (XVECEXP (orig, i, j),
548                                              map, for_lhs);
549             }
550           break;
551
552         case 'w':
553           XWINT (copy, i) = XWINT (orig, i);
554           break;
555
556         case 'i':
557           XINT (copy, i) = XINT (orig, i);
558           break;
559
560         case 's':
561           XSTR (copy, i) = XSTR (orig, i);
562           break;
563
564         case 't':
565           XTREE (copy, i) = XTREE (orig, i);
566           break;
567
568         default:
569           abort ();
570         }
571     }
572
573   if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
574     {
575       map->orig_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (orig);
576       map->copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
577       map->copy_asm_constraints_vector
578         = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
579     }
580
581   return copy;
582 }
583 \f
584 /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
585    given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
586    that it points to the node itself, thus indicating that the node is its
587    own (abstract) origin.  Additionally, if the BLOCK_ABSTRACT_ORIGIN for
588    the given node is NULL, recursively descend the decl/block tree which
589    it is the root of, and for each other ..._DECL or BLOCK node contained
590    therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
591    still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
592    values to point to themselves.  */
593
594 static void
595 set_block_origin_self (tree stmt)
596 {
597   if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
598     {
599       BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
600
601       {
602         tree local_decl;
603
604         for (local_decl = BLOCK_VARS (stmt);
605              local_decl != NULL_TREE;
606              local_decl = TREE_CHAIN (local_decl))
607           set_decl_origin_self (local_decl);    /* Potential recursion.  */
608       }
609
610       {
611         tree subblock;
612
613         for (subblock = BLOCK_SUBBLOCKS (stmt);
614              subblock != NULL_TREE;
615              subblock = BLOCK_CHAIN (subblock))
616           set_block_origin_self (subblock);     /* Recurse.  */
617       }
618     }
619 }
620
621 /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
622    the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
623    node to so that it points to the node itself, thus indicating that the
624    node represents its own (abstract) origin.  Additionally, if the
625    DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
626    the decl/block tree of which the given node is the root of, and for
627    each other ..._DECL or BLOCK node contained therein whose
628    DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
629    set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
630    point to themselves.  */
631
632 void
633 set_decl_origin_self (tree decl)
634 {
635   if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
636     {
637       DECL_ABSTRACT_ORIGIN (decl) = decl;
638       if (TREE_CODE (decl) == FUNCTION_DECL)
639         {
640           tree arg;
641
642           for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
643             DECL_ABSTRACT_ORIGIN (arg) = arg;
644           if (DECL_INITIAL (decl) != NULL_TREE
645               && DECL_INITIAL (decl) != error_mark_node)
646             set_block_origin_self (DECL_INITIAL (decl));
647         }
648     }
649 }
650 \f
651 /* Given a pointer to some BLOCK node, and a boolean value to set the
652    "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
653    the given block, and for all local decls and all local sub-blocks
654    (recursively) which are contained therein.  */
655
656 static void
657 set_block_abstract_flags (tree stmt, int setting)
658 {
659   tree local_decl;
660   tree subblock;
661
662   BLOCK_ABSTRACT (stmt) = setting;
663
664   for (local_decl = BLOCK_VARS (stmt);
665        local_decl != NULL_TREE;
666        local_decl = TREE_CHAIN (local_decl))
667     set_decl_abstract_flags (local_decl, setting);
668
669   for (subblock = BLOCK_SUBBLOCKS (stmt);
670        subblock != NULL_TREE;
671        subblock = BLOCK_CHAIN (subblock))
672     set_block_abstract_flags (subblock, setting);
673 }
674
675 /* Given a pointer to some ..._DECL node, and a boolean value to set the
676    "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
677    given decl, and (in the case where the decl is a FUNCTION_DECL) also
678    set the abstract flags for all of the parameters, local vars, local
679    blocks and sub-blocks (recursively) to the same setting.  */
680
681 void
682 set_decl_abstract_flags (tree decl, int setting)
683 {
684   DECL_ABSTRACT (decl) = setting;
685   if (TREE_CODE (decl) == FUNCTION_DECL)
686     {
687       tree arg;
688
689       for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
690         DECL_ABSTRACT (arg) = setting;
691       if (DECL_INITIAL (decl) != NULL_TREE
692           && DECL_INITIAL (decl) != error_mark_node)
693         set_block_abstract_flags (DECL_INITIAL (decl), setting);
694     }
695 }
696 \f
697 /* Functions to keep track of the values hard regs had at the start of
698    the function.  */
699
700 rtx
701 get_hard_reg_initial_reg (struct function *fun, rtx reg)
702 {
703   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
704   int i;
705
706   if (ivs == 0)
707     return NULL_RTX;
708
709   for (i = 0; i < ivs->num_entries; i++)
710     if (rtx_equal_p (ivs->entries[i].pseudo, reg))
711       return ivs->entries[i].hard_reg;
712
713   return NULL_RTX;
714 }
715
716 rtx
717 has_func_hard_reg_initial_val (struct function *fun, rtx reg)
718 {
719   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
720   int i;
721
722   if (ivs == 0)
723     return NULL_RTX;
724
725   for (i = 0; i < ivs->num_entries; i++)
726     if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
727       return ivs->entries[i].pseudo;
728
729   return NULL_RTX;
730 }
731
732 rtx
733 get_func_hard_reg_initial_val (struct function *fun, rtx reg)
734 {
735   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
736   rtx rv = has_func_hard_reg_initial_val (fun, reg);
737
738   if (rv)
739     return rv;
740
741   if (ivs == 0)
742     {
743       fun->hard_reg_initial_vals = ggc_alloc (sizeof (initial_value_struct));
744       ivs = fun->hard_reg_initial_vals;
745       ivs->num_entries = 0;
746       ivs->max_entries = 5;
747       ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
748     }
749
750   if (ivs->num_entries >= ivs->max_entries)
751     {
752       ivs->max_entries += 5;
753       ivs->entries = ggc_realloc (ivs->entries,
754                                   ivs->max_entries
755                                   * sizeof (initial_value_pair));
756     }
757
758   ivs->entries[ivs->num_entries].hard_reg = reg;
759   ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (GET_MODE (reg));
760
761   return ivs->entries[ivs->num_entries++].pseudo;
762 }
763
764 rtx
765 get_hard_reg_initial_val (enum machine_mode mode, int regno)
766 {
767   return get_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
768 }
769
770 rtx
771 has_hard_reg_initial_val (enum machine_mode mode, int regno)
772 {
773   return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
774 }
775
776 void
777 emit_initial_value_sets (void)
778 {
779   struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
780   int i;
781   rtx seq;
782
783   if (ivs == 0)
784     return;
785
786   start_sequence ();
787   for (i = 0; i < ivs->num_entries; i++)
788     emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
789   seq = get_insns ();
790   end_sequence ();
791
792   emit_insn_after (seq, entry_of_function ());
793 }
794
795 /* If the backend knows where to allocate pseudos for hard
796    register initial values, register these allocations now.  */
797 void
798 allocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED)
799 {
800 #ifdef ALLOCATE_INITIAL_VALUE
801   struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
802   int i;
803
804   if (ivs == 0)
805     return;
806
807   for (i = 0; i < ivs->num_entries; i++)
808     {
809       int regno = REGNO (ivs->entries[i].pseudo);
810       rtx x = ALLOCATE_INITIAL_VALUE (ivs->entries[i].hard_reg);
811
812       if (x == NULL_RTX || REG_N_SETS (REGNO (ivs->entries[i].pseudo)) > 1)
813         ; /* Do nothing.  */
814       else if (MEM_P (x))
815         reg_equiv_memory_loc[regno] = x;
816       else if (REG_P (x))
817         {
818           reg_renumber[regno] = REGNO (x);
819           /* Poke the regno right into regno_reg_rtx
820              so that even fixed regs are accepted.  */
821           REGNO (ivs->entries[i].pseudo) = REGNO (x);
822         }
823       else abort ();
824     }
825 #endif
826 }
827
828 #include "gt-integrate.h"