OSDN Git Service

dbgcnt name matching bug fix
[pf3gnuchains/gcc-fork.git] / gcc / var-tracking.c
1 /* Variable tracking routines for the GNU compiler.
2    Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING3.  If not see
19    <http://www.gnu.org/licenses/>.  */
20
21 /* This file contains the variable tracking pass.  It computes where
22    variables are located (which registers or where in memory) at each position
23    in instruction stream and emits notes describing the locations.
24    Debug information (DWARF2 location lists) is finally generated from
25    these notes.
26    With this debug information, it is possible to show variables
27    even when debugging optimized code.
28
29    How does the variable tracking pass work?
30
31    First, it scans RTL code for uses, stores and clobbers (register/memory
32    references in instructions), for call insns and for stack adjustments
33    separately for each basic block and saves them to an array of micro
34    operations.
35    The micro operations of one instruction are ordered so that
36    pre-modifying stack adjustment < use < use with no var < call insn <
37      < set < clobber < post-modifying stack adjustment
38
39    Then, a forward dataflow analysis is performed to find out how locations
40    of variables change through code and to propagate the variable locations
41    along control flow graph.
42    The IN set for basic block BB is computed as a union of OUT sets of BB's
43    predecessors, the OUT set for BB is copied from the IN set for BB and
44    is changed according to micro operations in BB.
45
46    The IN and OUT sets for basic blocks consist of a current stack adjustment
47    (used for adjusting offset of variables addressed using stack pointer),
48    the table of structures describing the locations of parts of a variable
49    and for each physical register a linked list for each physical register.
50    The linked list is a list of variable parts stored in the register,
51    i.e. it is a list of triplets (reg, decl, offset) where decl is
52    REG_EXPR (reg) and offset is REG_OFFSET (reg).  The linked list is used for
53    effective deleting appropriate variable parts when we set or clobber the
54    register.
55
56    There may be more than one variable part in a register.  The linked lists
57    should be pretty short so it is a good data structure here.
58    For example in the following code, register allocator may assign same
59    register to variables A and B, and both of them are stored in the same
60    register in CODE:
61
62      if (cond)
63        set A;
64      else
65        set B;
66      CODE;
67      if (cond)
68        use A;
69      else
70        use B;
71
72    Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
73    are emitted to appropriate positions in RTL code.  Each such a note describes
74    the location of one variable at the point in instruction stream where the
75    note is.  There is no need to emit a note for each variable before each
76    instruction, we only emit these notes where the location of variable changes
77    (this means that we also emit notes for changes between the OUT set of the
78    previous block and the IN set of the current block).
79
80    The notes consist of two parts:
81    1. the declaration (from REG_EXPR or MEM_EXPR)
82    2. the location of a variable - it is either a simple register/memory
83       reference (for simple variables, for example int),
84       or a parallel of register/memory references (for a large variables
85       which consist of several parts, for example long long).
86
87 */
88
89 #include "config.h"
90 #include "system.h"
91 #include "coretypes.h"
92 #include "tm.h"
93 #include "rtl.h"
94 #include "tree.h"
95 #include "hard-reg-set.h"
96 #include "basic-block.h"
97 #include "flags.h"
98 #include "output.h"
99 #include "insn-config.h"
100 #include "reload.h"
101 #include "sbitmap.h"
102 #include "alloc-pool.h"
103 #include "fibheap.h"
104 #include "hashtab.h"
105 #include "regs.h"
106 #include "expr.h"
107 #include "timevar.h"
108 #include "tree-pass.h"
109
110 /* Type of micro operation.  */
111 enum micro_operation_type
112 {
113   MO_USE,       /* Use location (REG or MEM).  */
114   MO_USE_NO_VAR,/* Use location which is not associated with a variable
115                    or the variable is not trackable.  */
116   MO_SET,       /* Set location.  */
117   MO_COPY,      /* Copy the same portion of a variable from one
118                    location to another.  */
119   MO_CLOBBER,   /* Clobber location.  */
120   MO_CALL,      /* Call insn.  */
121   MO_ADJUST     /* Adjust stack pointer.  */
122 };
123
124 /* Where shall the note be emitted?  BEFORE or AFTER the instruction.  */
125 enum emit_note_where
126 {
127   EMIT_NOTE_BEFORE_INSN,
128   EMIT_NOTE_AFTER_INSN
129 };
130
131 /* Structure holding information about micro operation.  */
132 typedef struct micro_operation_def
133 {
134   /* Type of micro operation.  */
135   enum micro_operation_type type;
136
137   union {
138     /* Location.  For MO_SET and MO_COPY, this is the SET that performs
139        the assignment, if known, otherwise it is the target of the
140        assignment.  */
141     rtx loc;
142
143     /* Stack adjustment.  */
144     HOST_WIDE_INT adjust;
145   } u;
146
147   /* The instruction which the micro operation is in, for MO_USE,
148      MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
149      instruction or note in the original flow (before any var-tracking
150      notes are inserted, to simplify emission of notes), for MO_SET
151      and MO_CLOBBER.  */
152   rtx insn;
153 } micro_operation;
154
155 /* Structure for passing some other parameters to function
156    emit_note_insn_var_location.  */
157 typedef struct emit_note_data_def
158 {
159   /* The instruction which the note will be emitted before/after.  */
160   rtx insn;
161
162   /* Where the note will be emitted (before/after insn)?  */
163   enum emit_note_where where;
164 } emit_note_data;
165
166 /* Description of location of a part of a variable.  The content of a physical
167    register is described by a chain of these structures.
168    The chains are pretty short (usually 1 or 2 elements) and thus
169    chain is the best data structure.  */
170 typedef struct attrs_def
171 {
172   /* Pointer to next member of the list.  */
173   struct attrs_def *next;
174
175   /* The rtx of register.  */
176   rtx loc;
177
178   /* The declaration corresponding to LOC.  */
179   tree decl;
180
181   /* Offset from start of DECL.  */
182   HOST_WIDE_INT offset;
183 } *attrs;
184
185 /* Structure holding a refcounted hash table.  If refcount > 1,
186    it must be first unshared before modified.  */
187 typedef struct shared_hash_def
188 {
189   /* Reference count.  */
190   int refcount;
191
192   /* Actual hash table.  */
193   htab_t htab;
194 } *shared_hash;
195
196 /* Structure holding the IN or OUT set for a basic block.  */
197 typedef struct dataflow_set_def
198 {
199   /* Adjustment of stack offset.  */
200   HOST_WIDE_INT stack_adjust;
201
202   /* Attributes for registers (lists of attrs).  */
203   attrs regs[FIRST_PSEUDO_REGISTER];
204
205   /* Variable locations.  */
206   shared_hash vars;
207 } dataflow_set;
208
209 /* The structure (one for each basic block) containing the information
210    needed for variable tracking.  */
211 typedef struct variable_tracking_info_def
212 {
213   /* Number of micro operations stored in the MOS array.  */
214   int n_mos;
215
216   /* The array of micro operations.  */
217   micro_operation *mos;
218
219   /* The IN and OUT set for dataflow analysis.  */
220   dataflow_set in;
221   dataflow_set out;
222
223   /* Has the block been visited in DFS?  */
224   bool visited;
225 } *variable_tracking_info;
226
227 /* Structure for chaining the locations.  */
228 typedef struct location_chain_def
229 {
230   /* Next element in the chain.  */
231   struct location_chain_def *next;
232
233   /* The location (REG or MEM).  */
234   rtx loc;
235
236   /* The "value" stored in this location.  */
237   rtx set_src;
238
239   /* Initialized? */
240   enum var_init_status init;
241 } *location_chain;
242
243 /* Structure describing one part of variable.  */
244 typedef struct variable_part_def
245 {
246   /* Chain of locations of the part.  */
247   location_chain loc_chain;
248
249   /* Location which was last emitted to location list.  */
250   rtx cur_loc;
251
252   /* The offset in the variable.  */
253   HOST_WIDE_INT offset;
254 } variable_part;
255
256 /* Maximum number of location parts.  */
257 #define MAX_VAR_PARTS 16
258
259 /* Structure describing where the variable is located.  */
260 typedef struct variable_def
261 {
262   /* The declaration of the variable.  */
263   tree decl;
264
265   /* Reference count.  */
266   int refcount;
267
268   /* Number of variable parts.  */
269   int n_var_parts;
270
271   /* The variable parts.  */
272   variable_part var_part[MAX_VAR_PARTS];
273 } *variable;
274 typedef const struct variable_def *const_variable;
275
276 /* Hash function for DECL for VARIABLE_HTAB.  */
277 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
278
279 /* Pointer to the BB's information specific to variable tracking pass.  */
280 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
281
282 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
283 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
284
285 /* Alloc pool for struct attrs_def.  */
286 static alloc_pool attrs_pool;
287
288 /* Alloc pool for struct variable_def.  */
289 static alloc_pool var_pool;
290
291 /* Alloc pool for struct location_chain_def.  */
292 static alloc_pool loc_chain_pool;
293
294 /* Alloc pool for struct shared_hash_def.  */
295 static alloc_pool shared_hash_pool;
296
297 /* Changed variables, notes will be emitted for them.  */
298 static htab_t changed_variables;
299
300 /* Shall notes be emitted?  */
301 static bool emit_notes;
302
303 /* Empty shared hashtable.  */
304 static shared_hash empty_shared_hash;
305
306 /* Local function prototypes.  */
307 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
308                                           HOST_WIDE_INT *);
309 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
310                                                HOST_WIDE_INT *);
311 static void bb_stack_adjust_offset (basic_block);
312 static bool vt_stack_adjustments (void);
313 static rtx adjust_stack_reference (rtx, HOST_WIDE_INT);
314 static hashval_t variable_htab_hash (const void *);
315 static int variable_htab_eq (const void *, const void *);
316 static void variable_htab_free (void *);
317
318 static void init_attrs_list_set (attrs *);
319 static void attrs_list_clear (attrs *);
320 static attrs attrs_list_member (attrs, tree, HOST_WIDE_INT);
321 static void attrs_list_insert (attrs *, tree, HOST_WIDE_INT, rtx);
322 static void attrs_list_copy (attrs *, attrs);
323 static void attrs_list_union (attrs *, attrs);
324
325 static variable unshare_variable (dataflow_set *set, variable var, 
326                                   enum var_init_status);
327 static int vars_copy_1 (void **, void *);
328 static void vars_copy (htab_t, htab_t);
329 static tree var_debug_decl (tree);
330 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
331 static void var_reg_delete_and_set (dataflow_set *, rtx, bool, 
332                                     enum var_init_status, rtx);
333 static void var_reg_delete (dataflow_set *, rtx, bool);
334 static void var_regno_delete (dataflow_set *, int);
335 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
336 static void var_mem_delete_and_set (dataflow_set *, rtx, bool, 
337                                     enum var_init_status, rtx);
338 static void var_mem_delete (dataflow_set *, rtx, bool);
339
340 static void dataflow_set_init (dataflow_set *);
341 static void dataflow_set_clear (dataflow_set *);
342 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
343 static int variable_union_info_cmp_pos (const void *, const void *);
344 static int variable_union (void **, void *);
345 static int variable_canonicalize (void **, void *);
346 static void dataflow_set_union (dataflow_set *, dataflow_set *);
347 static bool variable_part_different_p (variable_part *, variable_part *);
348 static bool variable_different_p (variable, variable, bool);
349 static int dataflow_set_different_1 (void **, void *);
350 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
351 static void dataflow_set_destroy (dataflow_set *);
352
353 static bool contains_symbol_ref (rtx);
354 static bool track_expr_p (tree);
355 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
356 static int count_uses (rtx *, void *);
357 static void count_uses_1 (rtx *, void *);
358 static void count_stores (rtx, const_rtx, void *);
359 static int add_uses (rtx *, void *);
360 static void add_uses_1 (rtx *, void *);
361 static void add_stores (rtx, const_rtx, void *);
362 static bool compute_bb_dataflow (basic_block);
363 static void vt_find_locations (void);
364
365 static void dump_attrs_list (attrs);
366 static int dump_variable (void **, void *);
367 static void dump_vars (htab_t);
368 static void dump_dataflow_set (dataflow_set *);
369 static void dump_dataflow_sets (void);
370
371 static void variable_was_changed (variable, dataflow_set *);
372 static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, 
373                                enum var_init_status, rtx);
374 static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, 
375                                    rtx);
376 static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
377 static int emit_note_insn_var_location (void **, void *);
378 static void emit_notes_for_changes (rtx, enum emit_note_where);
379 static int emit_notes_for_differences_1 (void **, void *);
380 static int emit_notes_for_differences_2 (void **, void *);
381 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
382 static void emit_notes_in_bb (basic_block);
383 static void vt_emit_notes (void);
384
385 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
386 static void vt_add_function_parameters (void);
387 static void vt_initialize (void);
388 static void vt_finalize (void);
389
390 /* Given a SET, calculate the amount of stack adjustment it contains
391    PRE- and POST-modifying stack pointer.
392    This function is similar to stack_adjust_offset.  */
393
394 static void
395 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
396                               HOST_WIDE_INT *post)
397 {
398   rtx src = SET_SRC (pattern);
399   rtx dest = SET_DEST (pattern);
400   enum rtx_code code;
401
402   if (dest == stack_pointer_rtx)
403     {
404       /* (set (reg sp) (plus (reg sp) (const_int))) */
405       code = GET_CODE (src);
406       if (! (code == PLUS || code == MINUS)
407           || XEXP (src, 0) != stack_pointer_rtx
408           || !CONST_INT_P (XEXP (src, 1)))
409         return;
410
411       if (code == MINUS)
412         *post += INTVAL (XEXP (src, 1));
413       else
414         *post -= INTVAL (XEXP (src, 1));
415     }
416   else if (MEM_P (dest))
417     {
418       /* (set (mem (pre_dec (reg sp))) (foo)) */
419       src = XEXP (dest, 0);
420       code = GET_CODE (src);
421
422       switch (code)
423         {
424         case PRE_MODIFY:
425         case POST_MODIFY:
426           if (XEXP (src, 0) == stack_pointer_rtx)
427             {
428               rtx val = XEXP (XEXP (src, 1), 1);
429               /* We handle only adjustments by constant amount.  */
430               gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
431                           CONST_INT_P (val));
432               
433               if (code == PRE_MODIFY)
434                 *pre -= INTVAL (val);
435               else
436                 *post -= INTVAL (val);
437               break;
438             }
439           return;
440
441         case PRE_DEC:
442           if (XEXP (src, 0) == stack_pointer_rtx)
443             {
444               *pre += GET_MODE_SIZE (GET_MODE (dest));
445               break;
446             }
447           return;
448
449         case POST_DEC:
450           if (XEXP (src, 0) == stack_pointer_rtx)
451             {
452               *post += GET_MODE_SIZE (GET_MODE (dest));
453               break;
454             }
455           return;
456
457         case PRE_INC:
458           if (XEXP (src, 0) == stack_pointer_rtx)
459             {
460               *pre -= GET_MODE_SIZE (GET_MODE (dest));
461               break;
462             }
463           return;
464
465         case POST_INC:
466           if (XEXP (src, 0) == stack_pointer_rtx)
467             {
468               *post -= GET_MODE_SIZE (GET_MODE (dest));
469               break;
470             }
471           return;
472
473         default:
474           return;
475         }
476     }
477 }
478
479 /* Given an INSN, calculate the amount of stack adjustment it contains
480    PRE- and POST-modifying stack pointer.  */
481
482 static void
483 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
484                                    HOST_WIDE_INT *post)
485 {
486   rtx pattern;
487
488   *pre = 0;
489   *post = 0;
490
491   pattern = PATTERN (insn);
492   if (RTX_FRAME_RELATED_P (insn))
493     {
494       rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
495       if (expr)
496         pattern = XEXP (expr, 0);
497     }
498
499   if (GET_CODE (pattern) == SET)
500     stack_adjust_offset_pre_post (pattern, pre, post);
501   else if (GET_CODE (pattern) == PARALLEL
502            || GET_CODE (pattern) == SEQUENCE)
503     {
504       int i;
505
506       /* There may be stack adjustments inside compound insns.  Search
507          for them.  */
508       for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
509         if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
510           stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
511     }
512 }
513
514 /* Compute stack adjustment in basic block BB.  */
515
516 static void
517 bb_stack_adjust_offset (basic_block bb)
518 {
519   HOST_WIDE_INT offset;
520   int i;
521
522   offset = VTI (bb)->in.stack_adjust;
523   for (i = 0; i < VTI (bb)->n_mos; i++)
524     {
525       if (VTI (bb)->mos[i].type == MO_ADJUST)
526         offset += VTI (bb)->mos[i].u.adjust;
527       else if (VTI (bb)->mos[i].type != MO_CALL)
528         {
529           if (MEM_P (VTI (bb)->mos[i].u.loc))
530             {
531               VTI (bb)->mos[i].u.loc
532                 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
533             }
534         }
535     }
536   VTI (bb)->out.stack_adjust = offset;
537 }
538
539 /* Compute stack adjustments for all blocks by traversing DFS tree.
540    Return true when the adjustments on all incoming edges are consistent.
541    Heavily borrowed from pre_and_rev_post_order_compute.  */
542
543 static bool
544 vt_stack_adjustments (void)
545 {
546   edge_iterator *stack;
547   int sp;
548
549   /* Initialize entry block.  */
550   VTI (ENTRY_BLOCK_PTR)->visited = true;
551   VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
552
553   /* Allocate stack for back-tracking up CFG.  */
554   stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
555   sp = 0;
556
557   /* Push the first edge on to the stack.  */
558   stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
559
560   while (sp)
561     {
562       edge_iterator ei;
563       basic_block src;
564       basic_block dest;
565
566       /* Look at the edge on the top of the stack.  */
567       ei = stack[sp - 1];
568       src = ei_edge (ei)->src;
569       dest = ei_edge (ei)->dest;
570
571       /* Check if the edge destination has been visited yet.  */
572       if (!VTI (dest)->visited)
573         {
574           VTI (dest)->visited = true;
575           VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
576           bb_stack_adjust_offset (dest);
577
578           if (EDGE_COUNT (dest->succs) > 0)
579             /* Since the DEST node has been visited for the first
580                time, check its successors.  */
581             stack[sp++] = ei_start (dest->succs);
582         }
583       else
584         {
585           /* Check whether the adjustments on the edges are the same.  */
586           if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
587             {
588               free (stack);
589               return false;
590             }
591
592           if (! ei_one_before_end_p (ei))
593             /* Go to the next edge.  */
594             ei_next (&stack[sp - 1]);
595           else
596             /* Return to previous level if there are no more edges.  */
597             sp--;
598         }
599     }
600
601   free (stack);
602   return true;
603 }
604
605 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
606    to the argument pointer.  Return the new rtx.  */
607
608 static rtx
609 adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
610 {
611   rtx addr, cfa, tmp;
612
613 #ifdef FRAME_POINTER_CFA_OFFSET
614   adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
615   cfa = plus_constant (frame_pointer_rtx, adjustment);
616 #else
617   adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
618   cfa = plus_constant (arg_pointer_rtx, adjustment);
619 #endif
620
621   addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
622   tmp = simplify_rtx (addr);
623   if (tmp)
624     addr = tmp;
625
626   return replace_equiv_address_nv (mem, addr);
627 }
628
629 /* The hash function for variable_htab, computes the hash value
630    from the declaration of variable X.  */
631
632 static hashval_t
633 variable_htab_hash (const void *x)
634 {
635   const_variable const v = (const_variable) x;
636
637   return (VARIABLE_HASH_VAL (v->decl));
638 }
639
640 /* Compare the declaration of variable X with declaration Y.  */
641
642 static int
643 variable_htab_eq (const void *x, const void *y)
644 {
645   const_variable const v = (const_variable) x;
646   const_tree const decl = (const_tree) y;
647
648   return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
649 }
650
651 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
652
653 static void
654 variable_htab_free (void *elem)
655 {
656   int i;
657   variable var = (variable) elem;
658   location_chain node, next;
659
660   gcc_assert (var->refcount > 0);
661
662   var->refcount--;
663   if (var->refcount > 0)
664     return;
665
666   for (i = 0; i < var->n_var_parts; i++)
667     {
668       for (node = var->var_part[i].loc_chain; node; node = next)
669         {
670           next = node->next;
671           pool_free (loc_chain_pool, node);
672         }
673       var->var_part[i].loc_chain = NULL;
674     }
675   pool_free (var_pool, var);
676 }
677
678 /* Initialize the set (array) SET of attrs to empty lists.  */
679
680 static void
681 init_attrs_list_set (attrs *set)
682 {
683   int i;
684
685   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
686     set[i] = NULL;
687 }
688
689 /* Make the list *LISTP empty.  */
690
691 static void
692 attrs_list_clear (attrs *listp)
693 {
694   attrs list, next;
695
696   for (list = *listp; list; list = next)
697     {
698       next = list->next;
699       pool_free (attrs_pool, list);
700     }
701   *listp = NULL;
702 }
703
704 /* Return true if the pair of DECL and OFFSET is the member of the LIST.  */
705
706 static attrs
707 attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset)
708 {
709   for (; list; list = list->next)
710     if (list->decl == decl && list->offset == offset)
711       return list;
712   return NULL;
713 }
714
715 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
716
717 static void
718 attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc)
719 {
720   attrs list;
721
722   list = (attrs) pool_alloc (attrs_pool);
723   list->loc = loc;
724   list->decl = decl;
725   list->offset = offset;
726   list->next = *listp;
727   *listp = list;
728 }
729
730 /* Copy all nodes from SRC and create a list *DSTP of the copies.  */
731
732 static void
733 attrs_list_copy (attrs *dstp, attrs src)
734 {
735   attrs n;
736
737   attrs_list_clear (dstp);
738   for (; src; src = src->next)
739     {
740       n = (attrs) pool_alloc (attrs_pool);
741       n->loc = src->loc;
742       n->decl = src->decl;
743       n->offset = src->offset;
744       n->next = *dstp;
745       *dstp = n;
746     }
747 }
748
749 /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
750
751 static void
752 attrs_list_union (attrs *dstp, attrs src)
753 {
754   for (; src; src = src->next)
755     {
756       if (!attrs_list_member (*dstp, src->decl, src->offset))
757         attrs_list_insert (dstp, src->decl, src->offset, src->loc);
758     }
759 }
760
761 /* Shared hashtable support.  */
762
763 /* Return true if VARS is shared.  */
764
765 static inline bool
766 shared_hash_shared (shared_hash vars)
767 {
768   return vars->refcount > 1;
769 }
770
771 /* Return the hash table for VARS.  */
772
773 static inline htab_t
774 shared_hash_htab (shared_hash vars)
775 {
776   return vars->htab;
777 }
778
779 /* Copy variables into a new hash table.  */
780
781 static shared_hash
782 shared_hash_unshare (shared_hash vars)
783 {
784   shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
785   gcc_assert (vars->refcount > 1);
786   new_vars->refcount = 1;
787   new_vars->htab
788     = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
789                    variable_htab_eq, variable_htab_free);
790   vars_copy (new_vars->htab, vars->htab);
791   vars->refcount--;
792   return new_vars;
793 }
794
795 /* Increment reference counter on VARS and return it.  */
796
797 static inline shared_hash
798 shared_hash_copy (shared_hash vars)
799 {
800   vars->refcount++;
801   return vars;
802 }
803
804 /* Decrement reference counter and destroy hash table if not shared
805    anymore.  */
806
807 static void
808 shared_hash_destroy (shared_hash vars)
809 {
810   gcc_assert (vars->refcount > 0);
811   if (--vars->refcount == 0)
812     {
813       htab_delete (vars->htab);
814       pool_free (shared_hash_pool, vars);
815     }
816 }
817
818 /* Unshare *PVARS if shared and return slot for DECL.  If INS is
819    INSERT, insert it if not already present.  */
820
821 static inline void **
822 shared_hash_find_slot_unshare (shared_hash *pvars, tree decl,
823                                enum insert_option ins)
824 {
825   if (shared_hash_shared (*pvars))
826     *pvars = shared_hash_unshare (*pvars);
827   return htab_find_slot_with_hash (shared_hash_htab (*pvars), decl,
828                                    VARIABLE_HASH_VAL (decl), ins);
829 }
830
831 /* Return slot for DECL, if it is already present in the hash table.
832    If it is not present, insert it only VARS is not shared, otherwise
833    return NULL.  */
834
835 static inline void **
836 shared_hash_find_slot (shared_hash vars, tree decl)
837 {
838   return htab_find_slot_with_hash (shared_hash_htab (vars), decl,
839                                    VARIABLE_HASH_VAL (decl),
840                                    shared_hash_shared (vars)
841                                    ? NO_INSERT : INSERT);
842 }
843
844 /* Return slot for DECL only if it is already present in the hash table.  */
845
846 static inline void **
847 shared_hash_find_slot_noinsert (shared_hash vars, tree decl)
848 {
849   return htab_find_slot_with_hash (shared_hash_htab (vars), decl,
850                                    VARIABLE_HASH_VAL (decl), NO_INSERT);
851 }
852
853 /* Return variable for DECL or NULL if not already present in the hash
854    table.  */
855
856 static inline variable
857 shared_hash_find (shared_hash vars, tree decl)
858 {
859   return (variable)
860          htab_find_with_hash (shared_hash_htab (vars), decl,
861                               VARIABLE_HASH_VAL (decl));
862 }
863
864 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
865
866 static variable
867 unshare_variable (dataflow_set *set, variable var, 
868                   enum var_init_status initialized)
869 {
870   void **slot;
871   variable new_var;
872   int i;
873
874   new_var = (variable) pool_alloc (var_pool);
875   new_var->decl = var->decl;
876   new_var->refcount = 1;
877   var->refcount--;
878   new_var->n_var_parts = var->n_var_parts;
879
880   if (! flag_var_tracking_uninit)
881     initialized = VAR_INIT_STATUS_INITIALIZED;
882
883   for (i = 0; i < var->n_var_parts; i++)
884     {
885       location_chain node;
886       location_chain *nextp;
887
888       new_var->var_part[i].offset = var->var_part[i].offset;
889       nextp = &new_var->var_part[i].loc_chain;
890       for (node = var->var_part[i].loc_chain; node; node = node->next)
891         {
892           location_chain new_lc;
893
894           new_lc = (location_chain) pool_alloc (loc_chain_pool);
895           new_lc->next = NULL;
896           if (node->init > initialized)
897             new_lc->init = node->init;
898           else
899             new_lc->init = initialized;
900           if (node->set_src && !(MEM_P (node->set_src)))
901             new_lc->set_src = node->set_src;
902           else
903             new_lc->set_src = NULL;
904           new_lc->loc = node->loc;
905
906           *nextp = new_lc;
907           nextp = &new_lc->next;
908         }
909
910       /* We are at the basic block boundary when copying variable description
911          so set the CUR_LOC to be the first element of the chain.  */
912       if (new_var->var_part[i].loc_chain)
913         new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
914       else
915         new_var->var_part[i].cur_loc = NULL;
916     }
917
918   slot = shared_hash_find_slot_unshare (&set->vars, new_var->decl, INSERT);
919   *slot = new_var;
920   return new_var;
921 }
922
923 /* Add a variable from *SLOT to hash table DATA and increase its reference
924    count.  */
925
926 static int
927 vars_copy_1 (void **slot, void *data)
928 {
929   htab_t dst = (htab_t) data;
930   variable src, *dstp;
931
932   src = *(variable *) slot;
933   src->refcount++;
934
935   dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
936                                                 VARIABLE_HASH_VAL (src->decl),
937                                                 INSERT);
938   *dstp = src;
939
940   /* Continue traversing the hash table.  */
941   return 1;
942 }
943
944 /* Copy all variables from hash table SRC to hash table DST.  */
945
946 static void
947 vars_copy (htab_t dst, htab_t src)
948 {
949   htab_traverse_noresize (src, vars_copy_1, dst);
950 }
951
952 /* Map a decl to its main debug decl.  */
953
954 static inline tree
955 var_debug_decl (tree decl)
956 {
957   if (decl && DECL_P (decl)
958       && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
959       && DECL_P (DECL_DEBUG_EXPR (decl)))
960     decl = DECL_DEBUG_EXPR (decl);
961
962   return decl;
963 }
964
965 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
966
967 static void
968 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized, 
969              rtx set_src)
970 {
971   tree decl = REG_EXPR (loc);
972   HOST_WIDE_INT offset = REG_OFFSET (loc);
973   attrs node;
974
975   decl = var_debug_decl (decl);
976
977   for (node = set->regs[REGNO (loc)]; node; node = node->next)
978     if (node->decl == decl && node->offset == offset)
979       break;
980   if (!node)
981     attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
982   set_variable_part (set, loc, decl, offset, initialized, set_src);
983 }
984
985 static enum var_init_status
986 get_init_value (dataflow_set *set, rtx loc, tree decl)
987 {
988   variable var;
989   int i;
990   enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
991
992   if (! flag_var_tracking_uninit)
993     return VAR_INIT_STATUS_INITIALIZED;
994
995   var = shared_hash_find (set->vars, decl);
996   if (var)
997     {
998       for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
999         {
1000           location_chain nextp;
1001           for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1002             if (rtx_equal_p (nextp->loc, loc))
1003               {
1004                 ret_val = nextp->init;
1005                 break;
1006               }
1007         }
1008     }
1009
1010   return ret_val;
1011 }
1012
1013 /* Delete current content of register LOC in dataflow set SET and set
1014    the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  If
1015    MODIFY is true, any other live copies of the same variable part are
1016    also deleted from the dataflow set, otherwise the variable part is
1017    assumed to be copied from another location holding the same
1018    part.  */
1019
1020 static void
1021 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify, 
1022                         enum var_init_status initialized, rtx set_src)
1023 {
1024   tree decl = REG_EXPR (loc);
1025   HOST_WIDE_INT offset = REG_OFFSET (loc);
1026   attrs node, next;
1027   attrs *nextp;
1028
1029   decl = var_debug_decl (decl);
1030
1031   if (initialized == VAR_INIT_STATUS_UNKNOWN)
1032     initialized = get_init_value (set, loc, decl);
1033
1034   nextp = &set->regs[REGNO (loc)];
1035   for (node = *nextp; node; node = next)
1036     {
1037       next = node->next;
1038       if (node->decl != decl || node->offset != offset)
1039         {
1040           delete_variable_part (set, node->loc, node->decl, node->offset);
1041           pool_free (attrs_pool, node);
1042           *nextp = next;
1043         }
1044       else
1045         {
1046           node->loc = loc;
1047           nextp = &node->next;
1048         }
1049     }
1050   if (modify)
1051     clobber_variable_part (set, loc, decl, offset, set_src);
1052   var_reg_set (set, loc, initialized, set_src);
1053 }
1054
1055 /* Delete current content of register LOC in dataflow set SET.  If
1056    CLOBBER is true, also delete any other live copies of the same
1057    variable part.  */
1058
1059 static void
1060 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
1061 {
1062   attrs *reg = &set->regs[REGNO (loc)];
1063   attrs node, next;
1064
1065   if (clobber)
1066     {
1067       tree decl = REG_EXPR (loc);
1068       HOST_WIDE_INT offset = REG_OFFSET (loc);
1069
1070       decl = var_debug_decl (decl);
1071
1072       clobber_variable_part (set, NULL, decl, offset, NULL);
1073     }
1074
1075   for (node = *reg; node; node = next)
1076     {
1077       next = node->next;
1078       delete_variable_part (set, node->loc, node->decl, node->offset);
1079       pool_free (attrs_pool, node);
1080     }
1081   *reg = NULL;
1082 }
1083
1084 /* Delete content of register with number REGNO in dataflow set SET.  */
1085
1086 static void
1087 var_regno_delete (dataflow_set *set, int regno)
1088 {
1089   attrs *reg = &set->regs[regno];
1090   attrs node, next;
1091
1092   for (node = *reg; node; node = next)
1093     {
1094       next = node->next;
1095       delete_variable_part (set, node->loc, node->decl, node->offset);
1096       pool_free (attrs_pool, node);
1097     }
1098   *reg = NULL;
1099 }
1100
1101 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
1102    SET to LOC.
1103    Adjust the address first if it is stack pointer based.  */
1104
1105 static void
1106 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized, 
1107              rtx set_src)
1108 {
1109   tree decl = MEM_EXPR (loc);
1110   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1111
1112   decl = var_debug_decl (decl);
1113
1114   set_variable_part (set, loc, decl, offset, initialized, set_src);
1115 }
1116
1117 /* Delete and set the location part of variable MEM_EXPR (LOC) in
1118    dataflow set SET to LOC.  If MODIFY is true, any other live copies
1119    of the same variable part are also deleted from the dataflow set,
1120    otherwise the variable part is assumed to be copied from another
1121    location holding the same part.
1122    Adjust the address first if it is stack pointer based.  */
1123
1124 static void
1125 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify, 
1126                         enum var_init_status initialized, rtx set_src)
1127 {
1128   tree decl = MEM_EXPR (loc);
1129   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1130
1131   decl = var_debug_decl (decl);
1132
1133   if (initialized == VAR_INIT_STATUS_UNKNOWN)
1134     initialized = get_init_value (set, loc, decl);
1135
1136   if (modify)
1137     clobber_variable_part (set, NULL, decl, offset, set_src);
1138   var_mem_set (set, loc, initialized, set_src);
1139 }
1140
1141 /* Delete the location part LOC from dataflow set SET.  If CLOBBER is
1142    true, also delete any other live copies of the same variable part.
1143    Adjust the address first if it is stack pointer based.  */
1144
1145 static void
1146 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1147 {
1148   tree decl = MEM_EXPR (loc);
1149   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1150
1151   decl = var_debug_decl (decl);
1152   if (clobber)
1153     clobber_variable_part (set, NULL, decl, offset, NULL);
1154   delete_variable_part (set, loc, decl, offset);
1155 }
1156
1157 /* Initialize dataflow set SET to be empty. 
1158    VARS_SIZE is the initial size of hash table VARS.  */
1159
1160 static void
1161 dataflow_set_init (dataflow_set *set)
1162 {
1163   init_attrs_list_set (set->regs);
1164   set->vars = shared_hash_copy (empty_shared_hash);
1165   set->stack_adjust = 0;
1166 }
1167
1168 /* Delete the contents of dataflow set SET.  */
1169
1170 static void
1171 dataflow_set_clear (dataflow_set *set)
1172 {
1173   int i;
1174
1175   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1176     attrs_list_clear (&set->regs[i]);
1177
1178   shared_hash_destroy (set->vars);
1179   set->vars = shared_hash_copy (empty_shared_hash);
1180 }
1181
1182 /* Copy the contents of dataflow set SRC to DST.  */
1183
1184 static void
1185 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1186 {
1187   int i;
1188
1189   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1190     attrs_list_copy (&dst->regs[i], src->regs[i]);
1191
1192   shared_hash_destroy (dst->vars);
1193   dst->vars = shared_hash_copy (src->vars);
1194   dst->stack_adjust = src->stack_adjust;
1195 }
1196
1197 /* Information for merging lists of locations for a given offset of variable.
1198  */
1199 struct variable_union_info
1200 {
1201   /* Node of the location chain.  */
1202   location_chain lc;
1203
1204   /* The sum of positions in the input chains.  */
1205   int pos;
1206
1207   /* The position in the chain of DST dataflow set.  */
1208   int pos_dst;
1209 };
1210
1211 /* Buffer for location list sorting and its allocated size.  */
1212 static struct variable_union_info *vui_vec;
1213 static int vui_allocated;
1214
1215 /* Compare function for qsort, order the structures by POS element.  */
1216
1217 static int
1218 variable_union_info_cmp_pos (const void *n1, const void *n2)
1219 {
1220   const struct variable_union_info *const i1 =
1221     (const struct variable_union_info *) n1;
1222   const struct variable_union_info *const i2 =
1223     ( const struct variable_union_info *) n2;
1224
1225   if (i1->pos != i2->pos)
1226     return i1->pos - i2->pos;
1227   
1228   return (i1->pos_dst - i2->pos_dst);
1229 }
1230
1231 /* Compute union of location parts of variable *SLOT and the same variable
1232    from hash table DATA.  Compute "sorted" union of the location chains
1233    for common offsets, i.e. the locations of a variable part are sorted by
1234    a priority where the priority is the sum of the positions in the 2 chains
1235    (if a location is only in one list the position in the second list is
1236    defined to be larger than the length of the chains).
1237    When we are updating the location parts the newest location is in the
1238    beginning of the chain, so when we do the described "sorted" union
1239    we keep the newest locations in the beginning.  */
1240
1241 static int
1242 variable_union (void **slot, void *data)
1243 {
1244   variable src, dst;
1245   void **dstp;
1246   dataflow_set *set = (dataflow_set *) data;
1247   int i, j, k;
1248
1249   src = *(variable *) slot;
1250   dstp = shared_hash_find_slot (set->vars, src->decl);
1251   if (!dstp || !*dstp)
1252     {
1253       src->refcount++;
1254
1255       /* If CUR_LOC of some variable part is not the first element of
1256          the location chain we are going to change it so we have to make
1257          a copy of the variable.  */
1258       for (k = 0; k < src->n_var_parts; k++)
1259         {
1260           gcc_assert (!src->var_part[k].loc_chain
1261                       == !src->var_part[k].cur_loc);
1262           if (src->var_part[k].loc_chain)
1263             {
1264               gcc_assert (src->var_part[k].cur_loc);
1265               if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
1266                 break;
1267             }
1268         }
1269       if (k < src->n_var_parts)
1270         {
1271           if (dstp)
1272             *dstp = (void *) src;
1273           unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN);
1274         }
1275       else
1276         {
1277           if (!dstp)
1278             dstp = shared_hash_find_slot_unshare (&set->vars, src->decl,
1279                                                   INSERT);
1280           *dstp = (void *) src;
1281         }
1282
1283       /* Continue traversing the hash table.  */
1284       return 1;
1285     }
1286   else
1287     dst = (variable) *dstp;
1288
1289   gcc_assert (src->n_var_parts);
1290
1291   /* Count the number of location parts, result is K.  */
1292   for (i = 0, j = 0, k = 0;
1293        i < src->n_var_parts && j < dst->n_var_parts; k++)
1294     {
1295       if (src->var_part[i].offset == dst->var_part[j].offset)
1296         {
1297           i++;
1298           j++;
1299         }
1300       else if (src->var_part[i].offset < dst->var_part[j].offset)
1301         i++;
1302       else
1303         j++;
1304     }
1305   k += src->n_var_parts - i;
1306   k += dst->n_var_parts - j;
1307
1308   /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1309      thus there are at most MAX_VAR_PARTS different offsets.  */
1310   gcc_assert (k <= MAX_VAR_PARTS);
1311
1312   if ((dst->refcount > 1 || shared_hash_shared (set->vars))
1313       && dst->n_var_parts != k)
1314     dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
1315
1316   i = src->n_var_parts - 1;
1317   j = dst->n_var_parts - 1;
1318   dst->n_var_parts = k;
1319
1320   for (k--; k >= 0; k--)
1321     {
1322       location_chain node, node2;
1323
1324       if (i >= 0 && j >= 0
1325           && src->var_part[i].offset == dst->var_part[j].offset)
1326         {
1327           /* Compute the "sorted" union of the chains, i.e. the locations which
1328              are in both chains go first, they are sorted by the sum of
1329              positions in the chains.  */
1330           int dst_l, src_l;
1331           int ii, jj, n;
1332           struct variable_union_info *vui;
1333
1334           /* If DST is shared compare the location chains.
1335              If they are different we will modify the chain in DST with
1336              high probability so make a copy of DST.  */
1337           if (dst->refcount > 1 || shared_hash_shared (set->vars))
1338             {
1339               for (node = src->var_part[i].loc_chain,
1340                    node2 = dst->var_part[j].loc_chain; node && node2;
1341                    node = node->next, node2 = node2->next)
1342                 {
1343                   if (!((REG_P (node2->loc)
1344                          && REG_P (node->loc)
1345                          && REGNO (node2->loc) == REGNO (node->loc))
1346                         || rtx_equal_p (node2->loc, node->loc)))
1347                     {
1348                       if (node2->init < node->init)
1349                         node2->init = node->init;
1350                       break;
1351                     }
1352                 }
1353               if (node || node2)
1354                 dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
1355             }
1356
1357           src_l = 0;
1358           for (node = src->var_part[i].loc_chain; node; node = node->next)
1359             src_l++;
1360           dst_l = 0;
1361           for (node = dst->var_part[j].loc_chain; node; node = node->next)
1362             dst_l++;
1363
1364           if (dst_l == 1)
1365             {
1366               /* The most common case, much simpler, no qsort is needed.  */
1367               location_chain dstnode = dst->var_part[j].loc_chain;
1368               dst->var_part[k].loc_chain = dstnode;
1369               dst->var_part[k].offset = dst->var_part[j].offset;
1370               node2 = dstnode;
1371               for (node = src->var_part[i].loc_chain; node; node = node->next)
1372                 if (!((REG_P (dstnode->loc)
1373                        && REG_P (node->loc)
1374                        && REGNO (dstnode->loc) == REGNO (node->loc))
1375                       || rtx_equal_p (dstnode->loc, node->loc)))
1376                   {
1377                     location_chain new_node;
1378
1379                     /* Copy the location from SRC.  */
1380                     new_node = (location_chain) pool_alloc (loc_chain_pool);
1381                     new_node->loc = node->loc;
1382                     new_node->init = node->init;
1383                     if (!node->set_src || MEM_P (node->set_src))
1384                       new_node->set_src = NULL;
1385                     else
1386                       new_node->set_src = node->set_src;
1387                     node2->next = new_node;
1388                     node2 = new_node;
1389                   }
1390               node2->next = NULL;
1391             }
1392           else
1393             {
1394               if (src_l + dst_l > vui_allocated)
1395                 {
1396                   vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
1397                   vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
1398                                         vui_allocated);
1399                 }
1400               vui = vui_vec;
1401
1402               /* Fill in the locations from DST.  */
1403               for (node = dst->var_part[j].loc_chain, jj = 0; node;
1404                    node = node->next, jj++)
1405                 {
1406                   vui[jj].lc = node;
1407                   vui[jj].pos_dst = jj;
1408
1409                   /* Pos plus value larger than a sum of 2 valid positions.  */
1410                   vui[jj].pos = jj + src_l + dst_l;
1411                 }
1412
1413               /* Fill in the locations from SRC.  */
1414               n = dst_l;
1415               for (node = src->var_part[i].loc_chain, ii = 0; node;
1416                    node = node->next, ii++)
1417                 {
1418                   /* Find location from NODE.  */
1419                   for (jj = 0; jj < dst_l; jj++)
1420                     {
1421                       if ((REG_P (vui[jj].lc->loc)
1422                            && REG_P (node->loc)
1423                            && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
1424                           || rtx_equal_p (vui[jj].lc->loc, node->loc))
1425                         {
1426                           vui[jj].pos = jj + ii;
1427                           break;
1428                         }
1429                     }
1430                   if (jj >= dst_l)      /* The location has not been found.  */
1431                     {
1432                       location_chain new_node;
1433
1434                       /* Copy the location from SRC.  */
1435                       new_node = (location_chain) pool_alloc (loc_chain_pool);
1436                       new_node->loc = node->loc;
1437                       new_node->init = node->init;
1438                       if (!node->set_src || MEM_P (node->set_src))
1439                         new_node->set_src = NULL;
1440                       else
1441                         new_node->set_src = node->set_src;
1442                       vui[n].lc = new_node;
1443                       vui[n].pos_dst = src_l + dst_l;
1444                       vui[n].pos = ii + src_l + dst_l;
1445                       n++;
1446                     }
1447                 }
1448
1449               if (dst_l == 2)
1450                 {
1451                   /* Special case still very common case.  For dst_l == 2
1452                      all entries dst_l ... n-1 are sorted, with for i >= dst_l
1453                      vui[i].pos == i + src_l + dst_l.  */
1454                   if (vui[0].pos > vui[1].pos)
1455                     {
1456                       /* Order should be 1, 0, 2... */
1457                       dst->var_part[k].loc_chain = vui[1].lc;
1458                       vui[1].lc->next = vui[0].lc;
1459                       if (n >= 3)
1460                         {
1461                           vui[0].lc->next = vui[2].lc;
1462                           vui[n - 1].lc->next = NULL;
1463                         }
1464                       else
1465                         vui[0].lc->next = NULL;
1466                       ii = 3;
1467                     }
1468                   else
1469                     {
1470                       dst->var_part[k].loc_chain = vui[0].lc;
1471                       if (n >= 3 && vui[2].pos < vui[1].pos)
1472                         {
1473                           /* Order should be 0, 2, 1, 3... */
1474                           vui[0].lc->next = vui[2].lc;
1475                           vui[2].lc->next = vui[1].lc;
1476                           if (n >= 4)
1477                             {
1478                               vui[1].lc->next = vui[3].lc;
1479                               vui[n - 1].lc->next = NULL;
1480                             }
1481                           else
1482                             vui[1].lc->next = NULL;
1483                           ii = 4;
1484                         }
1485                       else
1486                         {
1487                           /* Order should be 0, 1, 2... */
1488                           ii = 1;
1489                           vui[n - 1].lc->next = NULL;
1490                         }
1491                     }
1492                   for (; ii < n; ii++)
1493                     vui[ii - 1].lc->next = vui[ii].lc;
1494                 }
1495               else
1496                 {
1497                   qsort (vui, n, sizeof (struct variable_union_info),
1498                          variable_union_info_cmp_pos);
1499
1500                   /* Reconnect the nodes in sorted order.  */
1501                   for (ii = 1; ii < n; ii++)
1502                     vui[ii - 1].lc->next = vui[ii].lc;
1503                   vui[n - 1].lc->next = NULL;
1504                   dst->var_part[k].loc_chain = vui[0].lc;
1505                 }
1506
1507               dst->var_part[k].offset = dst->var_part[j].offset;
1508             }
1509           i--;
1510           j--;
1511         }
1512       else if ((i >= 0 && j >= 0
1513                 && src->var_part[i].offset < dst->var_part[j].offset)
1514                || i < 0)
1515         {
1516           dst->var_part[k] = dst->var_part[j];
1517           j--;
1518         }
1519       else if ((i >= 0 && j >= 0
1520                 && src->var_part[i].offset > dst->var_part[j].offset)
1521                || j < 0)
1522         {
1523           location_chain *nextp;
1524
1525           /* Copy the chain from SRC.  */
1526           nextp = &dst->var_part[k].loc_chain;
1527           for (node = src->var_part[i].loc_chain; node; node = node->next)
1528             {
1529               location_chain new_lc;
1530
1531               new_lc = (location_chain) pool_alloc (loc_chain_pool);
1532               new_lc->next = NULL;
1533               new_lc->init = node->init;
1534               if (!node->set_src || MEM_P (node->set_src))
1535                 new_lc->set_src = NULL;
1536               else
1537                 new_lc->set_src = node->set_src;
1538               new_lc->loc = node->loc;
1539
1540               *nextp = new_lc;
1541               nextp = &new_lc->next;
1542             }
1543
1544           dst->var_part[k].offset = src->var_part[i].offset;
1545           i--;
1546         }
1547
1548       /* We are at the basic block boundary when computing union
1549          so set the CUR_LOC to be the first element of the chain.  */
1550       if (dst->var_part[k].loc_chain)
1551         dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc;
1552       else
1553         dst->var_part[k].cur_loc = NULL;
1554     }
1555
1556   if (flag_var_tracking_uninit)
1557     for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
1558       {
1559         location_chain node, node2;
1560         for (node = src->var_part[i].loc_chain; node; node = node->next)
1561           for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
1562             if (rtx_equal_p (node->loc, node2->loc))
1563               {
1564                 if (node->init > node2->init)
1565                   node2->init = node->init;
1566               }
1567       }
1568
1569   /* Continue traversing the hash table.  */
1570   return 1;
1571 }
1572
1573 /* Like variable_union, but only used when doing dataflow_set_union
1574    into an empty hashtab.  To allow sharing, dst is initially shared
1575    with src (so all variables are "copied" from src to dst hashtab),
1576    so only unshare_variable for variables that need canonicalization
1577    are needed.  */
1578
1579 static int
1580 variable_canonicalize (void **slot, void *data)
1581 {
1582   variable src;
1583   dataflow_set *set = (dataflow_set *) data;
1584   int k;
1585
1586   src = *(variable *) slot;
1587
1588   /* If CUR_LOC of some variable part is not the first element of
1589      the location chain we are going to change it so we have to make
1590      a copy of the variable.  */
1591   for (k = 0; k < src->n_var_parts; k++)
1592     {
1593       gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc);
1594       if (src->var_part[k].loc_chain)
1595         {
1596           gcc_assert (src->var_part[k].cur_loc);
1597           if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
1598             break;
1599         }
1600     }
1601   if (k < src->n_var_parts)
1602     unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN);
1603   return 1;
1604 }
1605
1606 /* Compute union of dataflow sets SRC and DST and store it to DST.  */
1607
1608 static void
1609 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
1610 {
1611   int i;
1612
1613   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1614     attrs_list_union (&dst->regs[i], src->regs[i]);
1615
1616   if (dst->vars == empty_shared_hash)
1617     {
1618       shared_hash_destroy (dst->vars);
1619       dst->vars = shared_hash_copy (src->vars);
1620       htab_traverse (shared_hash_htab (src->vars), variable_canonicalize, dst);
1621     }
1622   else
1623     htab_traverse (shared_hash_htab (src->vars), variable_union, dst);
1624 }
1625
1626 /* Flag whether two dataflow sets being compared contain different data.  */
1627 static bool
1628 dataflow_set_different_value;
1629
1630 static bool
1631 variable_part_different_p (variable_part *vp1, variable_part *vp2)
1632 {
1633   location_chain lc1, lc2;
1634
1635   for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
1636     {
1637       for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
1638         {
1639           if (REG_P (lc1->loc) && REG_P (lc2->loc))
1640             {
1641               if (REGNO (lc1->loc) == REGNO (lc2->loc))
1642                 break;
1643             }
1644           if (rtx_equal_p (lc1->loc, lc2->loc))
1645             break;
1646         }
1647       if (!lc2)
1648         return true;
1649     }
1650   return false;
1651 }
1652
1653 /* Return true if variables VAR1 and VAR2 are different.
1654    If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1655    variable part.  */
1656
1657 static bool
1658 variable_different_p (variable var1, variable var2,
1659                       bool compare_current_location)
1660 {
1661   int i;
1662
1663   if (var1 == var2)
1664     return false;
1665
1666   if (var1->n_var_parts != var2->n_var_parts)
1667     return true;
1668
1669   for (i = 0; i < var1->n_var_parts; i++)
1670     {
1671       if (var1->var_part[i].offset != var2->var_part[i].offset)
1672         return true;
1673       if (compare_current_location)
1674         {
1675           if (!((REG_P (var1->var_part[i].cur_loc)
1676                  && REG_P (var2->var_part[i].cur_loc)
1677                  && (REGNO (var1->var_part[i].cur_loc)
1678                      == REGNO (var2->var_part[i].cur_loc)))
1679                 || rtx_equal_p (var1->var_part[i].cur_loc,
1680                                 var2->var_part[i].cur_loc)))
1681             return true;
1682         }
1683       if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
1684         return true;
1685       if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
1686         return true;
1687     }
1688   return false;
1689 }
1690
1691 /* Compare variable *SLOT with the same variable in hash table DATA
1692    and set DATAFLOW_SET_DIFFERENT_VALUE if they are different.  */
1693
1694 static int
1695 dataflow_set_different_1 (void **slot, void *data)
1696 {
1697   htab_t htab = (htab_t) data;
1698   variable var1, var2;
1699
1700   var1 = *(variable *) slot;
1701   var2 = (variable) htab_find_with_hash (htab, var1->decl,
1702                               VARIABLE_HASH_VAL (var1->decl));
1703   if (!var2)
1704     {
1705       dataflow_set_different_value = true;
1706
1707       /* Stop traversing the hash table.  */
1708       return 0;
1709     }
1710
1711   if (variable_different_p (var1, var2, false))
1712     {
1713       dataflow_set_different_value = true;
1714
1715       /* Stop traversing the hash table.  */
1716       return 0;
1717     }
1718
1719   /* Continue traversing the hash table.  */
1720   return 1;
1721 }
1722
1723 /* Return true if dataflow sets OLD_SET and NEW_SET differ.  */
1724
1725 static bool
1726 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
1727 {
1728   if (old_set->vars == new_set->vars)
1729     return false;
1730
1731   if (htab_elements (shared_hash_htab (old_set->vars))
1732       != htab_elements (shared_hash_htab (new_set->vars)))
1733     return true;
1734
1735   dataflow_set_different_value = false;
1736
1737   htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1,
1738                  shared_hash_htab (new_set->vars));
1739   /* No need to traverse the second hashtab, if both have the same number
1740      of elements and the second one had all entries found in the first one,
1741      then it can't have any extra entries.  */
1742   return dataflow_set_different_value;
1743 }
1744
1745 /* Free the contents of dataflow set SET.  */
1746
1747 static void
1748 dataflow_set_destroy (dataflow_set *set)
1749 {
1750   int i;
1751
1752   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1753     attrs_list_clear (&set->regs[i]);
1754
1755   shared_hash_destroy (set->vars);
1756   set->vars = NULL;
1757 }
1758
1759 /* Return true if RTL X contains a SYMBOL_REF.  */
1760
1761 static bool
1762 contains_symbol_ref (rtx x)
1763 {
1764   const char *fmt;
1765   RTX_CODE code;
1766   int i;
1767
1768   if (!x)
1769     return false;
1770
1771   code = GET_CODE (x);
1772   if (code == SYMBOL_REF)
1773     return true;
1774
1775   fmt = GET_RTX_FORMAT (code);
1776   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1777     {
1778       if (fmt[i] == 'e')
1779         {
1780           if (contains_symbol_ref (XEXP (x, i)))
1781             return true;
1782         }
1783       else if (fmt[i] == 'E')
1784         {
1785           int j;
1786           for (j = 0; j < XVECLEN (x, i); j++)
1787             if (contains_symbol_ref (XVECEXP (x, i, j)))
1788               return true;
1789         }
1790     }
1791
1792   return false;
1793 }
1794
1795 /* Shall EXPR be tracked?  */
1796
1797 static bool
1798 track_expr_p (tree expr)
1799 {
1800   rtx decl_rtl;
1801   tree realdecl;
1802
1803   /* If EXPR is not a parameter or a variable do not track it.  */
1804   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
1805     return 0;
1806
1807   /* It also must have a name...  */
1808   if (!DECL_NAME (expr))
1809     return 0;
1810
1811   /* ... and a RTL assigned to it.  */
1812   decl_rtl = DECL_RTL_IF_SET (expr);
1813   if (!decl_rtl)
1814     return 0;
1815   
1816   /* If this expression is really a debug alias of some other declaration, we 
1817      don't need to track this expression if the ultimate declaration is
1818      ignored.  */
1819   realdecl = expr;
1820   if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
1821     {
1822       realdecl = DECL_DEBUG_EXPR (realdecl);
1823       /* ??? We don't yet know how to emit DW_OP_piece for variable
1824          that has been SRA'ed.  */
1825       if (!DECL_P (realdecl))
1826         return 0;
1827     }
1828
1829   /* Do not track EXPR if REALDECL it should be ignored for debugging
1830      purposes.  */ 
1831   if (DECL_IGNORED_P (realdecl))
1832     return 0;
1833
1834   /* Do not track global variables until we are able to emit correct location
1835      list for them.  */
1836   if (TREE_STATIC (realdecl))
1837     return 0;
1838
1839   /* When the EXPR is a DECL for alias of some variable (see example)
1840      the TREE_STATIC flag is not used.  Disable tracking all DECLs whose
1841      DECL_RTL contains SYMBOL_REF.
1842
1843      Example:
1844      extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1845      char **_dl_argv;
1846   */
1847   if (MEM_P (decl_rtl)
1848       && contains_symbol_ref (XEXP (decl_rtl, 0)))
1849     return 0;
1850
1851   /* If RTX is a memory it should not be very large (because it would be
1852      an array or struct).  */
1853   if (MEM_P (decl_rtl))
1854     {
1855       /* Do not track structures and arrays.  */
1856       if (GET_MODE (decl_rtl) == BLKmode
1857           || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
1858         return 0;
1859       if (MEM_SIZE (decl_rtl)
1860           && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
1861         return 0;
1862     }
1863
1864   return 1;
1865 }
1866
1867 /* Determine whether a given LOC refers to the same variable part as
1868    EXPR+OFFSET.  */
1869
1870 static bool
1871 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
1872 {
1873   tree expr2;
1874   HOST_WIDE_INT offset2;
1875
1876   if (! DECL_P (expr))
1877     return false;
1878
1879   if (REG_P (loc))
1880     {
1881       expr2 = REG_EXPR (loc);
1882       offset2 = REG_OFFSET (loc);
1883     }
1884   else if (MEM_P (loc))
1885     {
1886       expr2 = MEM_EXPR (loc);
1887       offset2 = INT_MEM_OFFSET (loc);
1888     }
1889   else
1890     return false;
1891
1892   if (! expr2 || ! DECL_P (expr2))
1893     return false;
1894
1895   expr = var_debug_decl (expr);
1896   expr2 = var_debug_decl (expr2);
1897
1898   return (expr == expr2 && offset == offset2);
1899 }
1900
1901 /* LOC is a REG or MEM that we would like to track if possible.
1902    If EXPR is null, we don't know what expression LOC refers to,
1903    otherwise it refers to EXPR + OFFSET.  STORE_REG_P is true if
1904    LOC is an lvalue register.
1905
1906    Return true if EXPR is nonnull and if LOC, or some lowpart of it,
1907    is something we can track.  When returning true, store the mode of
1908    the lowpart we can track in *MODE_OUT (if nonnull) and its offset
1909    from EXPR in *OFFSET_OUT (if nonnull).  */
1910
1911 static bool
1912 track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
1913              enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
1914 {
1915   enum machine_mode mode;
1916
1917   if (expr == NULL || !track_expr_p (expr))
1918     return false;
1919
1920   /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
1921      whole subreg, but only the old inner part is really relevant.  */
1922   mode = GET_MODE (loc);
1923   if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
1924     {
1925       enum machine_mode pseudo_mode;
1926
1927       pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
1928       if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
1929         {
1930           offset += byte_lowpart_offset (pseudo_mode, mode);
1931           mode = pseudo_mode;
1932         }
1933     }
1934
1935   /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
1936      Do the same if we are storing to a register and EXPR occupies
1937      the whole of register LOC; in that case, the whole of EXPR is
1938      being changed.  We exclude complex modes from the second case
1939      because the real and imaginary parts are represented as separate
1940      pseudo registers, even if the whole complex value fits into one
1941      hard register.  */
1942   if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
1943        || (store_reg_p
1944            && !COMPLEX_MODE_P (DECL_MODE (expr))
1945            && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
1946       && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
1947     {
1948       mode = DECL_MODE (expr);
1949       offset = 0;
1950     }
1951
1952   if (offset < 0 || offset >= MAX_VAR_PARTS)
1953     return false;
1954
1955   if (mode_out)
1956     *mode_out = mode;
1957   if (offset_out)
1958     *offset_out = offset;
1959   return true;
1960 }
1961
1962 /* Return the MODE lowpart of LOC, or null if LOC is not something we
1963    want to track.  When returning nonnull, make sure that the attributes
1964    on the returned value are updated.  */
1965
1966 static rtx
1967 var_lowpart (enum machine_mode mode, rtx loc)
1968 {
1969   unsigned int offset, reg_offset, regno;
1970
1971   if (!REG_P (loc) && !MEM_P (loc))
1972     return NULL;
1973
1974   if (GET_MODE (loc) == mode)
1975     return loc;
1976
1977   offset = byte_lowpart_offset (mode, GET_MODE (loc));
1978
1979   if (MEM_P (loc))
1980     return adjust_address_nv (loc, mode, offset);
1981
1982   reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
1983   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
1984                                              reg_offset, mode);
1985   return gen_rtx_REG_offset (loc, mode, regno, offset);
1986 }
1987
1988 /* Count uses (register and memory references) LOC which will be tracked.
1989    INSN is instruction which the LOC is part of.  */
1990
1991 static int
1992 count_uses (rtx *loc, void *insn)
1993 {
1994   basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1995
1996   if (REG_P (*loc))
1997     {
1998       gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
1999       VTI (bb)->n_mos++;
2000     }
2001   else if (MEM_P (*loc)
2002            && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
2003                            false, NULL, NULL))
2004     {
2005       VTI (bb)->n_mos++;
2006     }
2007
2008   return 0;
2009 }
2010
2011 /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
2012
2013 static void
2014 count_uses_1 (rtx *x, void *insn)
2015 {
2016   for_each_rtx (x, count_uses, insn);
2017 }
2018
2019 /* Count stores (register and memory references) LOC which will be tracked.
2020    INSN is instruction which the LOC is part of.  */
2021
2022 static void
2023 count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *insn)
2024 {
2025   count_uses (&loc, insn);
2026 }
2027
2028 /* Add uses (register and memory references) LOC which will be tracked
2029    to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
2030
2031 static int
2032 add_uses (rtx *loc, void *insn)
2033 {
2034   enum machine_mode mode;
2035
2036   if (REG_P (*loc))
2037     {
2038       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
2039       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
2040
2041       if (track_loc_p (*loc, REG_EXPR (*loc), REG_OFFSET (*loc),
2042                        false, &mode, NULL))
2043         {
2044           mo->type = MO_USE;
2045           mo->u.loc = var_lowpart (mode, *loc);
2046         }
2047       else
2048         {
2049           mo->type = MO_USE_NO_VAR;
2050           mo->u.loc = *loc;
2051         }
2052       mo->insn = (rtx) insn;
2053     }
2054   else if (MEM_P (*loc)
2055            && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
2056                            false, &mode, NULL))
2057     {
2058       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
2059       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
2060
2061       mo->type = MO_USE;
2062       mo->u.loc = var_lowpart (mode, *loc);
2063       mo->insn = (rtx) insn;
2064     }
2065
2066   return 0;
2067 }
2068
2069 /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
2070
2071 static void
2072 add_uses_1 (rtx *x, void *insn)
2073 {
2074   for_each_rtx (x, add_uses, insn);
2075 }
2076
2077 /* Add stores (register and memory references) LOC which will be tracked
2078    to VTI (bb)->mos. EXPR is the RTL expression containing the store.
2079    INSN is instruction which the LOC is part of.  */
2080
2081 static void
2082 add_stores (rtx loc, const_rtx expr, void *insn)
2083 {
2084   enum machine_mode mode;
2085
2086   if (REG_P (loc))
2087     {
2088       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
2089       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
2090
2091       if (GET_CODE (expr) == CLOBBER
2092           || !track_loc_p (loc, REG_EXPR (loc), REG_OFFSET (loc),
2093                            true, &mode, NULL))
2094         {
2095           mo->type = MO_CLOBBER;
2096           mo->u.loc = loc;
2097         }
2098       else
2099         {
2100           rtx src = NULL;
2101
2102           if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
2103             src = var_lowpart (mode, SET_SRC (expr));
2104           loc = var_lowpart (mode, loc);
2105
2106           if (src == NULL)
2107             {
2108               mo->type = MO_SET;
2109               mo->u.loc = loc;
2110             }
2111           else
2112             {
2113               if (SET_SRC (expr) != src)
2114                 expr = gen_rtx_SET (VOIDmode, loc, src);
2115               if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
2116                 mo->type = MO_COPY;
2117               else
2118                 mo->type = MO_SET;
2119               mo->u.loc = CONST_CAST_RTX (expr);
2120             }
2121         }
2122       mo->insn = (rtx) insn;
2123     }
2124   else if (MEM_P (loc)
2125            && track_loc_p (loc, MEM_EXPR (loc), INT_MEM_OFFSET (loc),
2126                            false, &mode, NULL))
2127     {
2128       basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
2129       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
2130
2131       if (GET_CODE (expr) == CLOBBER)
2132         {
2133           mo->type = MO_CLOBBER;
2134           mo->u.loc = var_lowpart (mode, loc);
2135         }
2136       else
2137         {
2138           rtx src = NULL;
2139
2140           if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
2141             src = var_lowpart (mode, SET_SRC (expr));
2142           loc = var_lowpart (mode, loc);
2143
2144           if (src == NULL)
2145             {
2146               mo->type = MO_SET;
2147               mo->u.loc = loc;
2148             }
2149           else
2150             {
2151               if (SET_SRC (expr) != src)
2152                 expr = gen_rtx_SET (VOIDmode, loc, src);
2153               if (same_variable_part_p (SET_SRC (expr),
2154                                         MEM_EXPR (loc),
2155                                         INT_MEM_OFFSET (loc)))
2156                 mo->type = MO_COPY;
2157               else
2158                 mo->type = MO_SET;
2159               mo->u.loc = CONST_CAST_RTX (expr);
2160             }
2161         }
2162       mo->insn = (rtx) insn;
2163     }
2164 }
2165
2166 static enum var_init_status
2167 find_src_status (dataflow_set *in, rtx src)
2168 {
2169   tree decl = NULL_TREE;
2170   enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
2171
2172   if (! flag_var_tracking_uninit)
2173     status = VAR_INIT_STATUS_INITIALIZED;
2174
2175   if (src && REG_P (src))
2176     decl = var_debug_decl (REG_EXPR (src));
2177   else if (src && MEM_P (src))
2178     decl = var_debug_decl (MEM_EXPR (src));
2179
2180   if (src && decl)
2181     status = get_init_value (in, src, decl);
2182
2183   return status;
2184 }
2185
2186 /* SRC is the source of an assignment.  Use SET to try to find what
2187    was ultimately assigned to SRC.  Return that value if known,
2188    otherwise return SRC itself.  */
2189
2190 static rtx
2191 find_src_set_src (dataflow_set *set, rtx src)
2192 {
2193   tree decl = NULL_TREE;   /* The variable being copied around.          */
2194   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
2195   variable var;
2196   location_chain nextp;
2197   int i;
2198   bool found;
2199
2200   if (src && REG_P (src))
2201     decl = var_debug_decl (REG_EXPR (src));
2202   else if (src && MEM_P (src))
2203     decl = var_debug_decl (MEM_EXPR (src));
2204
2205   if (src && decl)
2206     {
2207       var = shared_hash_find (set->vars, decl);
2208       if (var)
2209         {
2210           found = false;
2211           for (i = 0; i < var->n_var_parts && !found; i++)
2212             for (nextp = var->var_part[i].loc_chain; nextp && !found; 
2213                  nextp = nextp->next)
2214               if (rtx_equal_p (nextp->loc, src))
2215                 {
2216                   set_src = nextp->set_src;
2217                   found = true;
2218                 }
2219               
2220         }
2221     }
2222
2223   return set_src;
2224 }
2225
2226 /* Compute the changes of variable locations in the basic block BB.  */
2227
2228 static bool
2229 compute_bb_dataflow (basic_block bb)
2230 {
2231   int i, n, r;
2232   bool changed;
2233   dataflow_set old_out;
2234   dataflow_set *in = &VTI (bb)->in;
2235   dataflow_set *out = &VTI (bb)->out;
2236
2237   dataflow_set_init (&old_out);
2238   dataflow_set_copy (&old_out, out);
2239   dataflow_set_copy (out, in);
2240
2241   n = VTI (bb)->n_mos;
2242   for (i = 0; i < n; i++)
2243     {
2244       switch (VTI (bb)->mos[i].type)
2245         {
2246           case MO_CALL:
2247             for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
2248               if (TEST_HARD_REG_BIT (call_used_reg_set, r))
2249                 var_regno_delete (out, r);
2250             break;
2251
2252           case MO_USE:
2253             {
2254               rtx loc = VTI (bb)->mos[i].u.loc;
2255
2256               if (REG_P (loc))
2257                 var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
2258               else if (MEM_P (loc))
2259                 var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
2260             }
2261             break;
2262
2263           case MO_SET:
2264             {
2265               rtx loc = VTI (bb)->mos[i].u.loc;
2266               rtx set_src = NULL;
2267
2268               if (GET_CODE (loc) == SET)
2269                 {
2270                   set_src = SET_SRC (loc);
2271                   loc = SET_DEST (loc);
2272                 }
2273
2274               if (REG_P (loc))
2275                 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2276                                         set_src);
2277               else if (MEM_P (loc))
2278                 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2279                                         set_src);
2280             }
2281             break;
2282
2283           case MO_COPY:
2284             {
2285               rtx loc = VTI (bb)->mos[i].u.loc;
2286               enum var_init_status src_status;
2287               rtx set_src = NULL;
2288
2289               if (GET_CODE (loc) == SET)
2290                 {
2291                   set_src = SET_SRC (loc);
2292                   loc = SET_DEST (loc);
2293                 }
2294
2295               if (! flag_var_tracking_uninit)
2296                 src_status = VAR_INIT_STATUS_INITIALIZED;
2297               else
2298                 {
2299                   src_status = find_src_status (in, set_src);
2300
2301                   if (src_status == VAR_INIT_STATUS_UNKNOWN)
2302                     src_status = find_src_status (out, set_src);
2303                 }
2304
2305               set_src = find_src_set_src (in, set_src);
2306
2307               if (REG_P (loc))
2308                 var_reg_delete_and_set (out, loc, false, src_status, set_src);
2309               else if (MEM_P (loc))
2310                 var_mem_delete_and_set (out, loc, false, src_status, set_src);
2311             }
2312             break;
2313
2314           case MO_USE_NO_VAR:
2315             {
2316               rtx loc = VTI (bb)->mos[i].u.loc;
2317
2318               if (REG_P (loc))
2319                 var_reg_delete (out, loc, false);
2320               else if (MEM_P (loc))
2321                 var_mem_delete (out, loc, false);
2322             }
2323             break;
2324
2325           case MO_CLOBBER:
2326             {
2327               rtx loc = VTI (bb)->mos[i].u.loc;
2328
2329               if (REG_P (loc))
2330                 var_reg_delete (out, loc, true);
2331               else if (MEM_P (loc))
2332                 var_mem_delete (out, loc, true);
2333             }
2334             break;
2335
2336           case MO_ADJUST:
2337             out->stack_adjust += VTI (bb)->mos[i].u.adjust;
2338             break;
2339         }
2340     }
2341
2342   changed = dataflow_set_different (&old_out, out);
2343   dataflow_set_destroy (&old_out);
2344   return changed;
2345 }
2346
2347 /* Find the locations of variables in the whole function.  */
2348
2349 static void
2350 vt_find_locations (void)
2351 {
2352   fibheap_t worklist, pending, fibheap_swap;
2353   sbitmap visited, in_worklist, in_pending, sbitmap_swap;
2354   basic_block bb;
2355   edge e;
2356   int *bb_order;
2357   int *rc_order;
2358   int i;
2359
2360   /* Compute reverse completion order of depth first search of the CFG
2361      so that the data-flow runs faster.  */
2362   rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
2363   bb_order = XNEWVEC (int, last_basic_block);
2364   pre_and_rev_post_order_compute (NULL, rc_order, false);
2365   for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
2366     bb_order[rc_order[i]] = i;
2367   free (rc_order);
2368
2369   worklist = fibheap_new ();
2370   pending = fibheap_new ();
2371   visited = sbitmap_alloc (last_basic_block);
2372   in_worklist = sbitmap_alloc (last_basic_block);
2373   in_pending = sbitmap_alloc (last_basic_block);
2374   sbitmap_zero (in_worklist);
2375
2376   FOR_EACH_BB (bb)
2377     fibheap_insert (pending, bb_order[bb->index], bb);
2378   sbitmap_ones (in_pending);
2379
2380   while (!fibheap_empty (pending))
2381     {
2382       fibheap_swap = pending;
2383       pending = worklist;
2384       worklist = fibheap_swap;
2385       sbitmap_swap = in_pending;
2386       in_pending = in_worklist;
2387       in_worklist = sbitmap_swap;
2388
2389       sbitmap_zero (visited);
2390
2391       while (!fibheap_empty (worklist))
2392         {
2393           bb = (basic_block) fibheap_extract_min (worklist);
2394           RESET_BIT (in_worklist, bb->index);
2395           if (!TEST_BIT (visited, bb->index))
2396             {
2397               bool changed;
2398               edge_iterator ei;
2399
2400               SET_BIT (visited, bb->index);
2401
2402               /* Calculate the IN set as union of predecessor OUT sets.  */
2403               dataflow_set_clear (&VTI (bb)->in);
2404               FOR_EACH_EDGE (e, ei, bb->preds)
2405                 {
2406                   dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
2407                 }
2408
2409               changed = compute_bb_dataflow (bb);
2410               if (changed)
2411                 {
2412                   FOR_EACH_EDGE (e, ei, bb->succs)
2413                     {
2414                       if (e->dest == EXIT_BLOCK_PTR)
2415                         continue;
2416
2417                       if (e->dest == bb)
2418                         continue;
2419
2420                       if (TEST_BIT (visited, e->dest->index))
2421                         {
2422                           if (!TEST_BIT (in_pending, e->dest->index))
2423                             {
2424                               /* Send E->DEST to next round.  */
2425                               SET_BIT (in_pending, e->dest->index);
2426                               fibheap_insert (pending,
2427                                               bb_order[e->dest->index],
2428                                               e->dest);
2429                             }
2430                         }
2431                       else if (!TEST_BIT (in_worklist, e->dest->index))
2432                         {
2433                           /* Add E->DEST to current round.  */
2434                           SET_BIT (in_worklist, e->dest->index);
2435                           fibheap_insert (worklist, bb_order[e->dest->index],
2436                                           e->dest);
2437                         }
2438                     }
2439                 }
2440             }
2441         }
2442     }
2443
2444   free (bb_order);
2445   fibheap_delete (worklist);
2446   fibheap_delete (pending);
2447   sbitmap_free (visited);
2448   sbitmap_free (in_worklist);
2449   sbitmap_free (in_pending);
2450 }
2451
2452 /* Print the content of the LIST to dump file.  */
2453
2454 static void
2455 dump_attrs_list (attrs list)
2456 {
2457   for (; list; list = list->next)
2458     {
2459       print_mem_expr (dump_file, list->decl);
2460       fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
2461     }
2462   fprintf (dump_file, "\n");
2463 }
2464
2465 /* Print the information about variable *SLOT to dump file.  */
2466
2467 static int
2468 dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
2469 {
2470   variable var = *(variable *) slot;
2471   int i;
2472   location_chain node;
2473
2474   fprintf (dump_file, "  name: %s",
2475            IDENTIFIER_POINTER (DECL_NAME (var->decl)));
2476   if (dump_flags & TDF_UID)
2477     fprintf (dump_file, " D.%u\n", DECL_UID (var->decl));
2478   else
2479     fprintf (dump_file, "\n");
2480
2481   for (i = 0; i < var->n_var_parts; i++)
2482     {
2483       fprintf (dump_file, "    offset %ld\n",
2484                (long) var->var_part[i].offset);
2485       for (node = var->var_part[i].loc_chain; node; node = node->next)
2486         {
2487           fprintf (dump_file, "      ");
2488           if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
2489             fprintf (dump_file, "[uninit]");
2490           print_rtl_single (dump_file, node->loc);
2491         }
2492     }
2493
2494   /* Continue traversing the hash table.  */
2495   return 1;
2496 }
2497
2498 /* Print the information about variables from hash table VARS to dump file.  */
2499
2500 static void
2501 dump_vars (htab_t vars)
2502 {
2503   if (htab_elements (vars) > 0)
2504     {
2505       fprintf (dump_file, "Variables:\n");
2506       htab_traverse (vars, dump_variable, NULL);
2507     }
2508 }
2509
2510 /* Print the dataflow set SET to dump file.  */
2511
2512 static void
2513 dump_dataflow_set (dataflow_set *set)
2514 {
2515   int i;
2516
2517   fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
2518            set->stack_adjust);
2519   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2520     {
2521       if (set->regs[i])
2522         {
2523           fprintf (dump_file, "Reg %d:", i);
2524           dump_attrs_list (set->regs[i]);
2525         }
2526     }
2527   dump_vars (shared_hash_htab (set->vars));
2528   fprintf (dump_file, "\n");
2529 }
2530
2531 /* Print the IN and OUT sets for each basic block to dump file.  */
2532
2533 static void
2534 dump_dataflow_sets (void)
2535 {
2536   basic_block bb;
2537
2538   FOR_EACH_BB (bb)
2539     {
2540       fprintf (dump_file, "\nBasic block %d:\n", bb->index);
2541       fprintf (dump_file, "IN:\n");
2542       dump_dataflow_set (&VTI (bb)->in);
2543       fprintf (dump_file, "OUT:\n");
2544       dump_dataflow_set (&VTI (bb)->out);
2545     }
2546 }
2547
2548 /* Add variable VAR to the hash table of changed variables and
2549    if it has no locations delete it from SET's hash table.  */
2550
2551 static void
2552 variable_was_changed (variable var, dataflow_set *set)
2553 {
2554   hashval_t hash = VARIABLE_HASH_VAL (var->decl);
2555
2556   if (emit_notes)
2557     {
2558       variable *slot;
2559
2560       slot = (variable *) htab_find_slot_with_hash (changed_variables,
2561                                                     var->decl, hash, INSERT);
2562
2563       if (set && var->n_var_parts == 0)
2564         {
2565           variable empty_var;
2566
2567           empty_var = (variable) pool_alloc (var_pool);
2568           empty_var->decl = var->decl;
2569           empty_var->refcount = 1;
2570           empty_var->n_var_parts = 0;
2571           *slot = empty_var;
2572           goto drop_var;
2573         }
2574       else
2575         {
2576           var->refcount++;
2577           *slot = var;
2578         }
2579     }
2580   else
2581     {
2582       gcc_assert (set);
2583       if (var->n_var_parts == 0)
2584         {
2585           void **slot;
2586
2587         drop_var:
2588           slot = shared_hash_find_slot_noinsert (set->vars, var->decl);
2589           if (slot)
2590             {
2591               if (shared_hash_shared (set->vars))
2592                 slot = shared_hash_find_slot_unshare (&set->vars, var->decl,
2593                                                       NO_INSERT);
2594               htab_clear_slot (shared_hash_htab (set->vars), slot);
2595             }
2596         }
2597     }
2598 }
2599
2600 /* Look for the index in VAR->var_part corresponding to OFFSET.
2601    Return -1 if not found.  If INSERTION_POINT is non-NULL, the
2602    referenced int will be set to the index that the part has or should
2603    have, if it should be inserted.  */
2604
2605 static inline int
2606 find_variable_location_part (variable var, HOST_WIDE_INT offset,
2607                              int *insertion_point)
2608 {
2609   int pos, low, high;
2610
2611   /* Find the location part.  */
2612   low = 0;
2613   high = var->n_var_parts;
2614   while (low != high)
2615     {
2616       pos = (low + high) / 2;
2617       if (var->var_part[pos].offset < offset)
2618         low = pos + 1;
2619       else
2620         high = pos;
2621     }
2622   pos = low;
2623
2624   if (insertion_point)
2625     *insertion_point = pos;
2626
2627   if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
2628     return pos;
2629
2630   return -1;
2631 }
2632
2633 /* Set the part of variable's location in the dataflow set SET.  The variable
2634    part is specified by variable's declaration DECL and offset OFFSET and the
2635    part's location by LOC.  */
2636
2637 static void
2638 set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset,
2639                    enum var_init_status initialized, rtx set_src)
2640 {
2641   int pos;
2642   location_chain node, next;
2643   location_chain *nextp;
2644   variable var;
2645   void **slot = shared_hash_find_slot (set->vars, decl);
2646
2647   if (! flag_var_tracking_uninit)
2648     initialized = VAR_INIT_STATUS_INITIALIZED;
2649
2650   if (!slot || !*slot)
2651     {
2652       if (!slot)
2653         slot = shared_hash_find_slot_unshare (&set->vars, decl, INSERT);
2654       /* Create new variable information.  */
2655       var = (variable) pool_alloc (var_pool);
2656       var->decl = decl;
2657       var->refcount = 1;
2658       var->n_var_parts = 1;
2659       var->var_part[0].offset = offset;
2660       var->var_part[0].loc_chain = NULL;
2661       var->var_part[0].cur_loc = NULL;
2662       *slot = var;
2663       pos = 0;
2664     }
2665   else
2666     {
2667       int inspos = 0;
2668
2669       var = (variable) *slot;
2670
2671       pos = find_variable_location_part (var, offset, &inspos);
2672
2673       if (pos >= 0)
2674         {
2675           node = var->var_part[pos].loc_chain;
2676
2677           if (node
2678               && ((REG_P (node->loc) && REG_P (loc)
2679                    && REGNO (node->loc) == REGNO (loc))
2680                   || rtx_equal_p (node->loc, loc)))
2681             {
2682               /* LOC is in the beginning of the chain so we have nothing
2683                  to do.  */
2684               if (node->init < initialized)
2685                 node->init = initialized;
2686               if (set_src != NULL)
2687                 node->set_src = set_src;
2688
2689               return;
2690             }
2691           else
2692             {
2693               /* We have to make a copy of a shared variable.  */
2694               if (var->refcount > 1 || shared_hash_shared (set->vars))
2695                 var = unshare_variable (set, var, initialized);
2696             }
2697         }
2698       else
2699         {
2700           /* We have not found the location part, new one will be created.  */
2701
2702           /* We have to make a copy of the shared variable.  */
2703           if (var->refcount > 1 || shared_hash_shared (set->vars))
2704             var = unshare_variable (set, var, initialized);
2705
2706           /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2707              thus there are at most MAX_VAR_PARTS different offsets.  */
2708           gcc_assert (var->n_var_parts < MAX_VAR_PARTS);
2709
2710           /* We have to move the elements of array starting at index
2711              inspos to the next position.  */
2712           for (pos = var->n_var_parts; pos > inspos; pos--)
2713             var->var_part[pos] = var->var_part[pos - 1];
2714
2715           var->n_var_parts++;
2716           var->var_part[pos].offset = offset;
2717           var->var_part[pos].loc_chain = NULL;
2718           var->var_part[pos].cur_loc = NULL;
2719         }
2720     }
2721
2722   /* Delete the location from the list.  */
2723   nextp = &var->var_part[pos].loc_chain;
2724   for (node = var->var_part[pos].loc_chain; node; node = next)
2725     {
2726       next = node->next;
2727       if ((REG_P (node->loc) && REG_P (loc)
2728            && REGNO (node->loc) == REGNO (loc))
2729           || rtx_equal_p (node->loc, loc))
2730         {
2731           /* Save these values, to assign to the new node, before
2732              deleting this one.  */
2733           if (node->init > initialized)
2734             initialized = node->init;
2735           if (node->set_src != NULL && set_src == NULL)
2736             set_src = node->set_src;
2737           pool_free (loc_chain_pool, node);
2738           *nextp = next;
2739           break;
2740         }
2741       else
2742         nextp = &node->next;
2743     }
2744
2745   /* Add the location to the beginning.  */
2746   node = (location_chain) pool_alloc (loc_chain_pool);
2747   node->loc = loc;
2748   node->init = initialized;
2749   node->set_src = set_src;
2750   node->next = var->var_part[pos].loc_chain;
2751   var->var_part[pos].loc_chain = node;
2752
2753   /* If no location was emitted do so.  */
2754   if (var->var_part[pos].cur_loc == NULL)
2755     {
2756       var->var_part[pos].cur_loc = loc;
2757       variable_was_changed (var, set);
2758     }
2759 }
2760
2761 /* Remove all recorded register locations for the given variable part
2762    from dataflow set SET, except for those that are identical to loc.
2763    The variable part is specified by variable's declaration DECL and
2764    offset OFFSET.  */
2765
2766 static void
2767 clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
2768                        HOST_WIDE_INT offset, rtx set_src)
2769 {
2770   variable var;
2771
2772   if (! decl || ! DECL_P (decl))
2773     return;
2774
2775   var = shared_hash_find (set->vars, decl);
2776   if (var)
2777     {
2778       int pos = find_variable_location_part (var, offset, NULL);
2779
2780       if (pos >= 0)
2781         {
2782           location_chain node, next;
2783
2784           /* Remove the register locations from the dataflow set.  */
2785           next = var->var_part[pos].loc_chain;
2786           for (node = next; node; node = next)
2787             {
2788               next = node->next;
2789               if (node->loc != loc 
2790                   && (!flag_var_tracking_uninit
2791                       || !set_src 
2792                       || MEM_P (set_src)
2793                       || !rtx_equal_p (set_src, node->set_src)))
2794                 {
2795                   if (REG_P (node->loc))
2796                     {
2797                       attrs anode, anext;
2798                       attrs *anextp;
2799
2800                       /* Remove the variable part from the register's
2801                          list, but preserve any other variable parts
2802                          that might be regarded as live in that same
2803                          register.  */
2804                       anextp = &set->regs[REGNO (node->loc)];
2805                       for (anode = *anextp; anode; anode = anext)
2806                         {
2807                           anext = anode->next;
2808                           if (anode->decl == decl
2809                               && anode->offset == offset)
2810                             {
2811                               pool_free (attrs_pool, anode);
2812                               *anextp = anext;
2813                             }
2814                           else
2815                             anextp = &anode->next;
2816                         }
2817                     }
2818
2819                   delete_variable_part (set, node->loc, decl, offset);
2820                 }
2821             }
2822         }
2823     }
2824 }
2825
2826 /* Delete the part of variable's location from dataflow set SET.  The variable
2827    part is specified by variable's declaration DECL and offset OFFSET and the
2828    part's location by LOC.  */
2829
2830 static void
2831 delete_variable_part (dataflow_set *set, rtx loc, tree decl,
2832                       HOST_WIDE_INT offset)
2833 {
2834   variable var = shared_hash_find (set->vars, decl);;
2835   if (var)
2836     {
2837       int pos = find_variable_location_part (var, offset, NULL);
2838
2839       if (pos >= 0)
2840         {
2841           location_chain node, next;
2842           location_chain *nextp;
2843           bool changed;
2844
2845           if (var->refcount > 1 || shared_hash_shared (set->vars))
2846             {
2847               /* If the variable contains the location part we have to
2848                  make a copy of the variable.  */
2849               for (node = var->var_part[pos].loc_chain; node;
2850                    node = node->next)
2851                 {
2852                   if ((REG_P (node->loc) && REG_P (loc)
2853                        && REGNO (node->loc) == REGNO (loc))
2854                       || rtx_equal_p (node->loc, loc))
2855                     {
2856                       var = unshare_variable (set, var,
2857                                               VAR_INIT_STATUS_UNKNOWN);
2858                       break;
2859                     }
2860                 }
2861             }
2862
2863           /* Delete the location part.  */
2864           nextp = &var->var_part[pos].loc_chain;
2865           for (node = *nextp; node; node = next)
2866             {
2867               next = node->next;
2868               if ((REG_P (node->loc) && REG_P (loc)
2869                    && REGNO (node->loc) == REGNO (loc))
2870                   || rtx_equal_p (node->loc, loc))
2871                 {
2872                   pool_free (loc_chain_pool, node);
2873                   *nextp = next;
2874                   break;
2875                 }
2876               else
2877                 nextp = &node->next;
2878             }
2879
2880           /* If we have deleted the location which was last emitted
2881              we have to emit new location so add the variable to set
2882              of changed variables.  */
2883           if (var->var_part[pos].cur_loc
2884               && ((REG_P (loc)
2885                    && REG_P (var->var_part[pos].cur_loc)
2886                    && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
2887                   || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
2888             {
2889               changed = true;
2890               if (var->var_part[pos].loc_chain)
2891                 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc;
2892             }
2893           else
2894             changed = false;
2895
2896           if (var->var_part[pos].loc_chain == NULL)
2897             {
2898               var->n_var_parts--;
2899               while (pos < var->n_var_parts)
2900                 {
2901                   var->var_part[pos] = var->var_part[pos + 1];
2902                   pos++;
2903                 }
2904             }
2905           if (changed)
2906             variable_was_changed (var, set);
2907         }
2908     }
2909 }
2910
2911 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP.  DATA contains
2912    additional parameters: WHERE specifies whether the note shall be emitted
2913    before of after instruction INSN.  */
2914
2915 static int
2916 emit_note_insn_var_location (void **varp, void *data)
2917 {
2918   variable var = *(variable *) varp;
2919   rtx insn = ((emit_note_data *)data)->insn;
2920   enum emit_note_where where = ((emit_note_data *)data)->where;
2921   rtx note;
2922   int i, j, n_var_parts;
2923   bool complete;
2924   enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
2925   HOST_WIDE_INT last_limit;
2926   tree type_size_unit;
2927   HOST_WIDE_INT offsets[MAX_VAR_PARTS];
2928   rtx loc[MAX_VAR_PARTS];
2929
2930   gcc_assert (var->decl);
2931
2932   complete = true;
2933   last_limit = 0;
2934   n_var_parts = 0;
2935   for (i = 0; i < var->n_var_parts; i++)
2936     {
2937       enum machine_mode mode, wider_mode;
2938
2939       if (last_limit < var->var_part[i].offset)
2940         {
2941           complete = false;
2942           break;
2943         }
2944       else if (last_limit > var->var_part[i].offset)
2945         continue;
2946       offsets[n_var_parts] = var->var_part[i].offset;
2947       loc[n_var_parts] = var->var_part[i].loc_chain->loc;
2948       mode = GET_MODE (loc[n_var_parts]);
2949       initialized = var->var_part[i].loc_chain->init;
2950       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
2951
2952       /* Attempt to merge adjacent registers or memory.  */
2953       wider_mode = GET_MODE_WIDER_MODE (mode);
2954       for (j = i + 1; j < var->n_var_parts; j++)
2955         if (last_limit <= var->var_part[j].offset)
2956           break;
2957       if (j < var->n_var_parts
2958           && wider_mode != VOIDmode
2959           && GET_CODE (loc[n_var_parts])
2960              == GET_CODE (var->var_part[j].loc_chain->loc)
2961           && mode == GET_MODE (var->var_part[j].loc_chain->loc)
2962           && last_limit == var->var_part[j].offset)
2963         {
2964           rtx new_loc = NULL;
2965           rtx loc2 = var->var_part[j].loc_chain->loc;
2966
2967           if (REG_P (loc[n_var_parts])
2968               && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
2969                  == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
2970               && end_hard_regno (mode, REGNO (loc[n_var_parts]))
2971                  == REGNO (loc2))
2972             {
2973               if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
2974                 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
2975                                            mode, 0);
2976               else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
2977                 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
2978               if (new_loc)
2979                 {
2980                   if (!REG_P (new_loc)
2981                       || REGNO (new_loc) != REGNO (loc[n_var_parts]))
2982                     new_loc = NULL;
2983                   else
2984                     REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
2985                 }
2986             }
2987           else if (MEM_P (loc[n_var_parts])
2988                    && GET_CODE (XEXP (loc2, 0)) == PLUS
2989                    && REG_P (XEXP (XEXP (loc2, 0), 0))
2990                    && CONST_INT_P (XEXP (XEXP (loc2, 0), 1)))
2991             {
2992               if ((REG_P (XEXP (loc[n_var_parts], 0))
2993                    && rtx_equal_p (XEXP (loc[n_var_parts], 0),
2994                                    XEXP (XEXP (loc2, 0), 0))
2995                    && INTVAL (XEXP (XEXP (loc2, 0), 1))
2996                       == GET_MODE_SIZE (mode))
2997                   || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
2998                       && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1))
2999                       && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
3000                                       XEXP (XEXP (loc2, 0), 0))
3001                       && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
3002                          + GET_MODE_SIZE (mode)
3003                          == INTVAL (XEXP (XEXP (loc2, 0), 1))))
3004                 new_loc = adjust_address_nv (loc[n_var_parts],
3005                                              wider_mode, 0);
3006             }
3007
3008           if (new_loc)
3009             {
3010               loc[n_var_parts] = new_loc;
3011               mode = wider_mode;
3012               last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
3013               i = j;
3014             }
3015         }
3016       ++n_var_parts;
3017     }
3018   type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
3019   if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
3020     complete = false;
3021
3022   if (where == EMIT_NOTE_AFTER_INSN)
3023     note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
3024   else
3025     note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
3026
3027   if (! flag_var_tracking_uninit)
3028     initialized = VAR_INIT_STATUS_INITIALIZED;
3029
3030   if (!complete)
3031     {
3032       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
3033                                                        NULL_RTX, (int) initialized);
3034     }
3035   else if (n_var_parts == 1)
3036     {
3037       rtx expr_list
3038         = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
3039
3040       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
3041                                                        expr_list, 
3042                                                        (int) initialized);
3043     }
3044   else if (n_var_parts)
3045     {
3046       rtx parallel;
3047
3048       for (i = 0; i < n_var_parts; i++)
3049         loc[i]
3050           = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
3051
3052       parallel = gen_rtx_PARALLEL (VOIDmode,
3053                                    gen_rtvec_v (n_var_parts, loc));
3054       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
3055                                                        parallel, 
3056                                                        (int) initialized);
3057     }
3058
3059   htab_clear_slot (changed_variables, varp);
3060
3061   /* Continue traversing the hash table.  */
3062   return 1;
3063 }
3064
3065 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
3066    CHANGED_VARIABLES and delete this chain.  WHERE specifies whether the notes
3067    shall be emitted before of after instruction INSN.  */
3068
3069 static void
3070 emit_notes_for_changes (rtx insn, enum emit_note_where where)
3071 {
3072   emit_note_data data;
3073
3074   data.insn = insn;
3075   data.where = where;
3076   htab_traverse (changed_variables, emit_note_insn_var_location, &data);
3077 }
3078
3079 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
3080    same variable in hash table DATA or is not there at all.  */
3081
3082 static int
3083 emit_notes_for_differences_1 (void **slot, void *data)
3084 {
3085   htab_t new_vars = (htab_t) data;
3086   variable old_var, new_var;
3087
3088   old_var = *(variable *) slot;
3089   new_var = (variable) htab_find_with_hash (new_vars, old_var->decl,
3090                                  VARIABLE_HASH_VAL (old_var->decl));
3091
3092   if (!new_var)
3093     {
3094       /* Variable has disappeared.  */
3095       variable empty_var;
3096
3097       empty_var = (variable) pool_alloc (var_pool);
3098       empty_var->decl = old_var->decl;
3099       empty_var->refcount = 0;
3100       empty_var->n_var_parts = 0;
3101       variable_was_changed (empty_var, NULL);
3102     }
3103   else if (variable_different_p (old_var, new_var, true))
3104     {
3105       variable_was_changed (new_var, NULL);
3106     }
3107
3108   /* Continue traversing the hash table.  */
3109   return 1;
3110 }
3111
3112 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
3113    table DATA.  */
3114
3115 static int
3116 emit_notes_for_differences_2 (void **slot, void *data)
3117 {
3118   htab_t old_vars = (htab_t) data;
3119   variable old_var, new_var;
3120
3121   new_var = *(variable *) slot;
3122   old_var = (variable) htab_find_with_hash (old_vars, new_var->decl,
3123                                  VARIABLE_HASH_VAL (new_var->decl));
3124   if (!old_var)
3125     {
3126       /* Variable has appeared.  */
3127       variable_was_changed (new_var, NULL);
3128     }
3129
3130   /* Continue traversing the hash table.  */
3131   return 1;
3132 }
3133
3134 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
3135    NEW_SET.  */
3136
3137 static void
3138 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
3139                             dataflow_set *new_set)
3140 {
3141   htab_traverse (shared_hash_htab (old_set->vars),
3142                  emit_notes_for_differences_1,
3143                  shared_hash_htab (new_set->vars));
3144   htab_traverse (shared_hash_htab (new_set->vars),
3145                  emit_notes_for_differences_2,
3146                  shared_hash_htab (old_set->vars));
3147   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
3148 }
3149
3150 /* Emit the notes for changes of location parts in the basic block BB.  */
3151
3152 static void
3153 emit_notes_in_bb (basic_block bb)
3154 {
3155   int i;
3156   dataflow_set set;
3157
3158   dataflow_set_init (&set);
3159   dataflow_set_copy (&set, &VTI (bb)->in);
3160
3161   for (i = 0; i < VTI (bb)->n_mos; i++)
3162     {
3163       rtx insn = VTI (bb)->mos[i].insn;
3164
3165       switch (VTI (bb)->mos[i].type)
3166         {
3167           case MO_CALL:
3168             {
3169               int r;
3170
3171               for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
3172                 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
3173                   {
3174                     var_regno_delete (&set, r);
3175                   }
3176               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3177             }
3178             break;
3179
3180           case MO_USE:
3181             {
3182               rtx loc = VTI (bb)->mos[i].u.loc;
3183
3184               if (REG_P (loc))
3185                 var_reg_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
3186               else
3187                 var_mem_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
3188
3189               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3190             }
3191             break;
3192
3193           case MO_SET:
3194             {
3195               rtx loc = VTI (bb)->mos[i].u.loc;
3196               rtx set_src = NULL;
3197
3198               if (GET_CODE (loc) == SET)
3199                 {
3200                   set_src = SET_SRC (loc);
3201                   loc = SET_DEST (loc);
3202                 }
3203
3204               if (REG_P (loc))
3205                 var_reg_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED, 
3206                                         set_src);
3207               else
3208                 var_mem_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED, 
3209                                         set_src);
3210
3211               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3212             }
3213             break;
3214
3215           case MO_COPY:
3216             {
3217               rtx loc = VTI (bb)->mos[i].u.loc;
3218               enum var_init_status src_status;
3219               rtx set_src = NULL;
3220
3221               if (GET_CODE (loc) == SET)
3222                 {
3223                   set_src = SET_SRC (loc);
3224                   loc = SET_DEST (loc);
3225                 }
3226
3227               src_status = find_src_status (&set, set_src);
3228               set_src = find_src_set_src (&set, set_src);
3229
3230               if (REG_P (loc))
3231                 var_reg_delete_and_set (&set, loc, false, src_status, set_src);
3232               else
3233                 var_mem_delete_and_set (&set, loc, false, src_status, set_src);
3234
3235               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3236             }
3237             break;
3238
3239           case MO_USE_NO_VAR:
3240             {
3241               rtx loc = VTI (bb)->mos[i].u.loc;
3242
3243               if (REG_P (loc))
3244                 var_reg_delete (&set, loc, false);
3245               else
3246                 var_mem_delete (&set, loc, false);
3247
3248               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3249             }
3250             break;
3251
3252           case MO_CLOBBER:
3253             {
3254               rtx loc = VTI (bb)->mos[i].u.loc;
3255
3256               if (REG_P (loc))
3257                 var_reg_delete (&set, loc, true);
3258               else
3259                 var_mem_delete (&set, loc, true);
3260
3261               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3262             }
3263             break;
3264
3265           case MO_ADJUST:
3266             set.stack_adjust += VTI (bb)->mos[i].u.adjust;
3267             break;
3268         }
3269     }
3270   dataflow_set_destroy (&set);
3271 }
3272
3273 /* Emit notes for the whole function.  */
3274
3275 static void
3276 vt_emit_notes (void)
3277 {
3278   basic_block bb;
3279   dataflow_set *last_out;
3280   dataflow_set empty;
3281
3282   gcc_assert (!htab_elements (changed_variables));
3283
3284   /* Enable emitting notes by functions (mainly by set_variable_part and
3285      delete_variable_part).  */
3286   emit_notes = true;
3287
3288   dataflow_set_init (&empty);
3289   last_out = &empty;
3290
3291   FOR_EACH_BB (bb)
3292     {
3293       /* Emit the notes for changes of variable locations between two
3294          subsequent basic blocks.  */
3295       emit_notes_for_differences (BB_HEAD (bb), last_out, &VTI (bb)->in);
3296
3297       /* Emit the notes for the changes in the basic block itself.  */
3298       emit_notes_in_bb (bb);
3299
3300       last_out = &VTI (bb)->out;
3301     }
3302   dataflow_set_destroy (&empty);
3303   emit_notes = false;
3304 }
3305
3306 /* If there is a declaration and offset associated with register/memory RTL
3307    assign declaration to *DECLP and offset to *OFFSETP, and return true.  */
3308
3309 static bool
3310 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
3311 {
3312   if (REG_P (rtl))
3313     {
3314       if (REG_ATTRS (rtl))
3315         {
3316           *declp = REG_EXPR (rtl);
3317           *offsetp = REG_OFFSET (rtl);
3318           return true;
3319         }
3320     }
3321   else if (MEM_P (rtl))
3322     {
3323       if (MEM_ATTRS (rtl))
3324         {
3325           *declp = MEM_EXPR (rtl);
3326           *offsetp = INT_MEM_OFFSET (rtl);
3327           return true;
3328         }
3329     }
3330   return false;
3331 }
3332
3333 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK.  */
3334
3335 static void
3336 vt_add_function_parameters (void)
3337 {
3338   tree parm;
3339   
3340   for (parm = DECL_ARGUMENTS (current_function_decl);
3341        parm; parm = TREE_CHAIN (parm))
3342     {
3343       rtx decl_rtl = DECL_RTL_IF_SET (parm);
3344       rtx incoming = DECL_INCOMING_RTL (parm);
3345       tree decl;
3346       enum machine_mode mode;
3347       HOST_WIDE_INT offset;
3348       dataflow_set *out;
3349
3350       if (TREE_CODE (parm) != PARM_DECL)
3351         continue;
3352
3353       if (!DECL_NAME (parm))
3354         continue;
3355
3356       if (!decl_rtl || !incoming)
3357         continue;
3358
3359       if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
3360         continue;
3361
3362       if (!vt_get_decl_and_offset (incoming, &decl, &offset))
3363         {
3364           if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
3365             continue;
3366           offset += byte_lowpart_offset (GET_MODE (incoming),
3367                                          GET_MODE (decl_rtl));
3368         }
3369
3370       if (!decl)
3371         continue;
3372
3373       if (parm != decl)
3374         {
3375           /* Assume that DECL_RTL was a pseudo that got spilled to
3376              memory.  The spill slot sharing code will force the
3377              memory to reference spill_slot_decl (%sfp), so we don't
3378              match above.  That's ok, the pseudo must have referenced
3379              the entire parameter, so just reset OFFSET.  */
3380           gcc_assert (decl == get_spill_slot_decl (false));
3381           offset = 0;
3382         }
3383
3384       if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
3385         continue;
3386
3387       out = &VTI (ENTRY_BLOCK_PTR)->out;
3388
3389       if (REG_P (incoming))
3390         {
3391           incoming = var_lowpart (mode, incoming);
3392           gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
3393           attrs_list_insert (&out->regs[REGNO (incoming)],
3394                              parm, offset, incoming);
3395           set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED, 
3396                              NULL);
3397         }
3398       else if (MEM_P (incoming))
3399         {
3400           incoming = var_lowpart (mode, incoming);
3401           set_variable_part (out, incoming, parm, offset,
3402                              VAR_INIT_STATUS_INITIALIZED, NULL);
3403         }
3404     }
3405 }
3406
3407 /* Allocate and initialize the data structures for variable tracking
3408    and parse the RTL to get the micro operations.  */
3409
3410 static void
3411 vt_initialize (void)
3412 {
3413   basic_block bb;
3414
3415   alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
3416
3417   FOR_EACH_BB (bb)
3418     {
3419       rtx insn;
3420       HOST_WIDE_INT pre, post = 0;
3421
3422       /* Count the number of micro operations.  */
3423       VTI (bb)->n_mos = 0;
3424       for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3425            insn = NEXT_INSN (insn))
3426         {
3427           if (INSN_P (insn))
3428             {
3429               if (!frame_pointer_needed)
3430                 {
3431                   insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3432                   if (pre)
3433                     VTI (bb)->n_mos++;
3434                   if (post)
3435                     VTI (bb)->n_mos++;
3436                 }
3437               note_uses (&PATTERN (insn), count_uses_1, insn);
3438               note_stores (PATTERN (insn), count_stores, insn);
3439               if (CALL_P (insn))
3440                 VTI (bb)->n_mos++;
3441             }
3442         }
3443
3444       /* Add the micro-operations to the array.  */
3445       VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos);
3446       VTI (bb)->n_mos = 0;
3447       for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3448            insn = NEXT_INSN (insn))
3449         {
3450           if (INSN_P (insn))
3451             {
3452               int n1, n2;
3453
3454               if (!frame_pointer_needed)
3455                 {
3456                   insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3457                   if (pre)
3458                     {
3459                       micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3460
3461                       mo->type = MO_ADJUST;
3462                       mo->u.adjust = pre;
3463                       mo->insn = insn;
3464                     }
3465                 }
3466
3467               n1 = VTI (bb)->n_mos;
3468               note_uses (&PATTERN (insn), add_uses_1, insn);
3469               n2 = VTI (bb)->n_mos - 1;
3470
3471               /* Order the MO_USEs to be before MO_USE_NO_VARs.  */
3472               while (n1 < n2)
3473                 {
3474                   while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
3475                     n1++;
3476                   while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR)
3477                     n2--;
3478                   if (n1 < n2)
3479                     {
3480                       micro_operation sw;
3481
3482                       sw = VTI (bb)->mos[n1];
3483                       VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3484                       VTI (bb)->mos[n2] = sw;
3485                     }
3486                 }
3487
3488               if (CALL_P (insn))
3489                 {
3490                   micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3491
3492                   mo->type = MO_CALL;
3493                   mo->insn = insn;
3494                 }
3495
3496               n1 = VTI (bb)->n_mos;
3497               /* This will record NEXT_INSN (insn), such that we can
3498                  insert notes before it without worrying about any
3499                  notes that MO_USEs might emit after the insn.  */
3500               note_stores (PATTERN (insn), add_stores, insn);
3501               n2 = VTI (bb)->n_mos - 1;
3502
3503               /* Order the MO_CLOBBERs to be before MO_SETs.  */
3504               while (n1 < n2)
3505                 {
3506                   while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
3507                     n1++;
3508                   while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET
3509                                      || VTI (bb)->mos[n2].type == MO_COPY))
3510                     n2--;
3511                   if (n1 < n2)
3512                     {
3513                       micro_operation sw;
3514
3515                       sw = VTI (bb)->mos[n1];
3516                       VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3517                       VTI (bb)->mos[n2] = sw;
3518                     }
3519                 }
3520
3521               if (!frame_pointer_needed && post)
3522                 {
3523                   micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3524
3525                   mo->type = MO_ADJUST;
3526                   mo->u.adjust = post;
3527                   mo->insn = insn;
3528                 }
3529             }
3530         }
3531     }
3532
3533   attrs_pool = create_alloc_pool ("attrs_def pool",
3534                                   sizeof (struct attrs_def), 1024);
3535   var_pool = create_alloc_pool ("variable_def pool",
3536                                 sizeof (struct variable_def), 64);
3537   loc_chain_pool = create_alloc_pool ("location_chain_def pool",
3538                                       sizeof (struct location_chain_def),
3539                                       1024);
3540   shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
3541                                         sizeof (struct shared_hash_def), 256);
3542   empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
3543   empty_shared_hash->refcount = 1;
3544   empty_shared_hash->htab
3545     = htab_create (1, variable_htab_hash, variable_htab_eq,
3546                    variable_htab_free);
3547   changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
3548                                    variable_htab_free);
3549
3550   /* Init the IN and OUT sets.  */
3551   FOR_ALL_BB (bb)
3552     {
3553       VTI (bb)->visited = false;
3554       dataflow_set_init (&VTI (bb)->in);
3555       dataflow_set_init (&VTI (bb)->out);
3556     }
3557
3558   vt_add_function_parameters ();
3559 }
3560
3561 /* Free the data structures needed for variable tracking.  */
3562
3563 static void
3564 vt_finalize (void)
3565 {
3566   basic_block bb;
3567
3568   FOR_EACH_BB (bb)
3569     {
3570       free (VTI (bb)->mos);
3571     }
3572
3573   FOR_ALL_BB (bb)
3574     {
3575       dataflow_set_destroy (&VTI (bb)->in);
3576       dataflow_set_destroy (&VTI (bb)->out);
3577     }
3578   free_aux_for_blocks ();
3579   htab_delete (empty_shared_hash->htab);
3580   htab_delete (changed_variables);
3581   free_alloc_pool (attrs_pool);
3582   free_alloc_pool (var_pool);
3583   free_alloc_pool (loc_chain_pool);
3584   free_alloc_pool (shared_hash_pool);
3585   if (vui_vec)
3586     free (vui_vec);
3587   vui_vec = NULL;
3588   vui_allocated = 0;
3589 }
3590
3591 /* The entry point to variable tracking pass.  */
3592
3593 unsigned int
3594 variable_tracking_main (void)
3595 {
3596   if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
3597     return 0;
3598
3599   mark_dfs_back_edges ();
3600   vt_initialize ();
3601   if (!frame_pointer_needed)
3602     {
3603       if (!vt_stack_adjustments ())
3604         {
3605           vt_finalize ();
3606           return 0;
3607         }
3608     }
3609
3610   vt_find_locations ();
3611   vt_emit_notes ();
3612
3613   if (dump_file && (dump_flags & TDF_DETAILS))
3614     {
3615       dump_dataflow_sets ();
3616       dump_flow_info (dump_file, dump_flags);
3617     }
3618
3619   vt_finalize ();
3620   return 0;
3621 }
3622 \f
3623 static bool
3624 gate_handle_var_tracking (void)
3625 {
3626   return (flag_var_tracking);
3627 }
3628
3629
3630
3631 struct rtl_opt_pass pass_variable_tracking =
3632 {
3633  {
3634   RTL_PASS,
3635   "vartrack",                           /* name */
3636   gate_handle_var_tracking,             /* gate */
3637   variable_tracking_main,               /* execute */
3638   NULL,                                 /* sub */
3639   NULL,                                 /* next */
3640   0,                                    /* static_pass_number */
3641   TV_VAR_TRACKING,                      /* tv_id */
3642   0,                                    /* properties_required */
3643   0,                                    /* properties_provided */
3644   0,                                    /* properties_destroyed */
3645   0,                                    /* todo_flags_start */
3646   TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */
3647  }
3648 };