OSDN Git Service

362a881517482268bac8a6c6dcd631ad48a890c2
[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, 2010
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 #include "tree-flow.h"
110 #include "cselib.h"
111 #include "target.h"
112 #include "toplev.h"
113 #include "params.h"
114 #include "diagnostic.h"
115 #include "pointer-set.h"
116 #include "recog.h"
117
118 /* var-tracking.c assumes that tree code with the same value as VALUE rtx code
119    has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
120    Currently the value is the same as IDENTIFIER_NODE, which has such
121    a property.  If this compile time assertion ever fails, make sure that
122    the new tree code that equals (int) VALUE has the same property.  */
123 extern char check_value_val[(int) VALUE == (int) IDENTIFIER_NODE ? 1 : -1];
124
125 /* Type of micro operation.  */
126 enum micro_operation_type
127 {
128   MO_USE,       /* Use location (REG or MEM).  */
129   MO_USE_NO_VAR,/* Use location which is not associated with a variable
130                    or the variable is not trackable.  */
131   MO_VAL_USE,   /* Use location which is associated with a value.  */
132   MO_VAL_LOC,   /* Use location which appears in a debug insn.  */
133   MO_VAL_SET,   /* Set location associated with a value.  */
134   MO_SET,       /* Set location.  */
135   MO_COPY,      /* Copy the same portion of a variable from one
136                    location to another.  */
137   MO_CLOBBER,   /* Clobber location.  */
138   MO_CALL,      /* Call insn.  */
139   MO_ADJUST     /* Adjust stack pointer.  */
140
141 };
142
143 static const char * const ATTRIBUTE_UNUSED
144 micro_operation_type_name[] = {
145   "MO_USE",
146   "MO_USE_NO_VAR",
147   "MO_VAL_USE",
148   "MO_VAL_LOC",
149   "MO_VAL_SET",
150   "MO_SET",
151   "MO_COPY",
152   "MO_CLOBBER",
153   "MO_CALL",
154   "MO_ADJUST"
155 };
156
157 /* Where shall the note be emitted?  BEFORE or AFTER the instruction.
158    Notes emitted as AFTER_CALL are to take effect during the call,
159    rather than after the call.  */
160 enum emit_note_where
161 {
162   EMIT_NOTE_BEFORE_INSN,
163   EMIT_NOTE_AFTER_INSN,
164   EMIT_NOTE_AFTER_CALL_INSN
165 };
166
167 /* Structure holding information about micro operation.  */
168 typedef struct micro_operation_def
169 {
170   /* Type of micro operation.  */
171   enum micro_operation_type type;
172
173   /* The instruction which the micro operation is in, for MO_USE,
174      MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
175      instruction or note in the original flow (before any var-tracking
176      notes are inserted, to simplify emission of notes), for MO_SET
177      and MO_CLOBBER.  */
178   rtx insn;
179
180   union {
181     /* Location.  For MO_SET and MO_COPY, this is the SET that
182        performs the assignment, if known, otherwise it is the target
183        of the assignment.  For MO_VAL_USE and MO_VAL_SET, it is a
184        CONCAT of the VALUE and the LOC associated with it.  For
185        MO_VAL_LOC, it is a CONCAT of the VALUE and the VAR_LOCATION
186        associated with it.  */
187     rtx loc;
188
189     /* Stack adjustment.  */
190     HOST_WIDE_INT adjust;
191   } u;
192 } micro_operation;
193
194 DEF_VEC_O(micro_operation);
195 DEF_VEC_ALLOC_O(micro_operation,heap);
196
197 /* A declaration of a variable, or an RTL value being handled like a
198    declaration.  */
199 typedef void *decl_or_value;
200
201 /* Structure for passing some other parameters to function
202    emit_note_insn_var_location.  */
203 typedef struct emit_note_data_def
204 {
205   /* The instruction which the note will be emitted before/after.  */
206   rtx insn;
207
208   /* Where the note will be emitted (before/after insn)?  */
209   enum emit_note_where where;
210
211   /* The variables and values active at this point.  */
212   htab_t vars;
213 } emit_note_data;
214
215 /* Description of location of a part of a variable.  The content of a physical
216    register is described by a chain of these structures.
217    The chains are pretty short (usually 1 or 2 elements) and thus
218    chain is the best data structure.  */
219 typedef struct attrs_def
220 {
221   /* Pointer to next member of the list.  */
222   struct attrs_def *next;
223
224   /* The rtx of register.  */
225   rtx loc;
226
227   /* The declaration corresponding to LOC.  */
228   decl_or_value dv;
229
230   /* Offset from start of DECL.  */
231   HOST_WIDE_INT offset;
232 } *attrs;
233
234 /* Structure holding a refcounted hash table.  If refcount > 1,
235    it must be first unshared before modified.  */
236 typedef struct shared_hash_def
237 {
238   /* Reference count.  */
239   int refcount;
240
241   /* Actual hash table.  */
242   htab_t htab;
243 } *shared_hash;
244
245 /* Structure holding the IN or OUT set for a basic block.  */
246 typedef struct dataflow_set_def
247 {
248   /* Adjustment of stack offset.  */
249   HOST_WIDE_INT stack_adjust;
250
251   /* Attributes for registers (lists of attrs).  */
252   attrs regs[FIRST_PSEUDO_REGISTER];
253
254   /* Variable locations.  */
255   shared_hash vars;
256
257   /* Vars that is being traversed.  */
258   shared_hash traversed_vars;
259 } dataflow_set;
260
261 /* The structure (one for each basic block) containing the information
262    needed for variable tracking.  */
263 typedef struct variable_tracking_info_def
264 {
265   /* The vector of micro operations.  */
266   VEC(micro_operation, heap) *mos;
267
268   /* The IN and OUT set for dataflow analysis.  */
269   dataflow_set in;
270   dataflow_set out;
271
272   /* The permanent-in dataflow set for this block.  This is used to
273      hold values for which we had to compute entry values.  ??? This
274      should probably be dynamically allocated, to avoid using more
275      memory in non-debug builds.  */
276   dataflow_set *permp;
277
278   /* Has the block been visited in DFS?  */
279   bool visited;
280
281   /* Has the block been flooded in VTA?  */
282   bool flooded;
283
284 } *variable_tracking_info;
285
286 /* Structure for chaining the locations.  */
287 typedef struct location_chain_def
288 {
289   /* Next element in the chain.  */
290   struct location_chain_def *next;
291
292   /* The location (REG, MEM or VALUE).  */
293   rtx loc;
294
295   /* The "value" stored in this location.  */
296   rtx set_src;
297
298   /* Initialized? */
299   enum var_init_status init;
300 } *location_chain;
301
302 /* Structure describing one part of variable.  */
303 typedef struct variable_part_def
304 {
305   /* Chain of locations of the part.  */
306   location_chain loc_chain;
307
308   /* Location which was last emitted to location list.  */
309   rtx cur_loc;
310
311   /* The offset in the variable.  */
312   HOST_WIDE_INT offset;
313 } variable_part;
314
315 /* Maximum number of location parts.  */
316 #define MAX_VAR_PARTS 16
317
318 /* Structure describing where the variable is located.  */
319 typedef struct variable_def
320 {
321   /* The declaration of the variable, or an RTL value being handled
322      like a declaration.  */
323   decl_or_value dv;
324
325   /* Reference count.  */
326   int refcount;
327
328   /* Number of variable parts.  */
329   char n_var_parts;
330
331   /* True if this variable changed (any of its) cur_loc fields
332      during the current emit_notes_for_changes resp.
333      emit_notes_for_differences call.  */
334   bool cur_loc_changed;
335
336   /* True if this variable_def struct is currently in the
337      changed_variables hash table.  */
338   bool in_changed_variables;
339
340   /* The variable parts.  */
341   variable_part var_part[1];
342 } *variable;
343 typedef const struct variable_def *const_variable;
344
345 /* Structure for chaining backlinks from referenced VALUEs to
346    DVs that are referencing them.  */
347 typedef struct value_chain_def
348 {
349   /* Next value_chain entry.  */
350   struct value_chain_def *next;
351
352   /* The declaration of the variable, or an RTL value
353      being handled like a declaration, whose var_parts[0].loc_chain
354      references the VALUE owning this value_chain.  */
355   decl_or_value dv;
356
357   /* Reference count.  */
358   int refcount;
359 } *value_chain;
360 typedef const struct value_chain_def *const_value_chain;
361
362 /* Pointer to the BB's information specific to variable tracking pass.  */
363 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
364
365 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
366 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
367
368 /* Alloc pool for struct attrs_def.  */
369 static alloc_pool attrs_pool;
370
371 /* Alloc pool for struct variable_def with MAX_VAR_PARTS entries.  */
372 static alloc_pool var_pool;
373
374 /* Alloc pool for struct variable_def with a single var_part entry.  */
375 static alloc_pool valvar_pool;
376
377 /* Alloc pool for struct location_chain_def.  */
378 static alloc_pool loc_chain_pool;
379
380 /* Alloc pool for struct shared_hash_def.  */
381 static alloc_pool shared_hash_pool;
382
383 /* Alloc pool for struct value_chain_def.  */
384 static alloc_pool value_chain_pool;
385
386 /* Changed variables, notes will be emitted for them.  */
387 static htab_t changed_variables;
388
389 /* Links from VALUEs to DVs referencing them in their current loc_chains.  */
390 static htab_t value_chains;
391
392 /* Shall notes be emitted?  */
393 static bool emit_notes;
394
395 /* Empty shared hashtable.  */
396 static shared_hash empty_shared_hash;
397
398 /* Scratch register bitmap used by cselib_expand_value_rtx.  */
399 static bitmap scratch_regs = NULL;
400
401 /* Variable used to tell whether cselib_process_insn called our hook.  */
402 static bool cselib_hook_called;
403
404 /* Local function prototypes.  */
405 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
406                                           HOST_WIDE_INT *);
407 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
408                                                HOST_WIDE_INT *);
409 static bool vt_stack_adjustments (void);
410 static rtx compute_cfa_pointer (HOST_WIDE_INT);
411 static hashval_t variable_htab_hash (const void *);
412 static int variable_htab_eq (const void *, const void *);
413 static void variable_htab_free (void *);
414
415 static void init_attrs_list_set (attrs *);
416 static void attrs_list_clear (attrs *);
417 static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
418 static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
419 static void attrs_list_copy (attrs *, attrs);
420 static void attrs_list_union (attrs *, attrs);
421
422 static void **unshare_variable (dataflow_set *set, void **slot, variable var,
423                                 enum var_init_status);
424 static int vars_copy_1 (void **, void *);
425 static void vars_copy (htab_t, htab_t);
426 static tree var_debug_decl (tree);
427 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
428 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
429                                     enum var_init_status, rtx);
430 static void var_reg_delete (dataflow_set *, rtx, bool);
431 static void var_regno_delete (dataflow_set *, int);
432 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
433 static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
434                                     enum var_init_status, rtx);
435 static void var_mem_delete (dataflow_set *, rtx, bool);
436
437 static void dataflow_set_init (dataflow_set *);
438 static void dataflow_set_clear (dataflow_set *);
439 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
440 static int variable_union_info_cmp_pos (const void *, const void *);
441 static int variable_union (void **, void *);
442 static void dataflow_set_union (dataflow_set *, dataflow_set *);
443 static location_chain find_loc_in_1pdv (rtx, variable, htab_t);
444 static bool canon_value_cmp (rtx, rtx);
445 static int loc_cmp (rtx, rtx);
446 static bool variable_part_different_p (variable_part *, variable_part *);
447 static bool onepart_variable_different_p (variable, variable);
448 static bool variable_different_p (variable, variable);
449 static int dataflow_set_different_1 (void **, void *);
450 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
451 static void dataflow_set_destroy (dataflow_set *);
452
453 static bool contains_symbol_ref (rtx);
454 static bool track_expr_p (tree, bool);
455 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
456 static int add_uses (rtx *, void *);
457 static void add_uses_1 (rtx *, void *);
458 static void add_stores (rtx, const_rtx, void *);
459 static bool compute_bb_dataflow (basic_block);
460 static bool vt_find_locations (void);
461
462 static void dump_attrs_list (attrs);
463 static int dump_var_slot (void **, void *);
464 static void dump_var (variable);
465 static void dump_vars (htab_t);
466 static void dump_dataflow_set (dataflow_set *);
467 static void dump_dataflow_sets (void);
468
469 static void variable_was_changed (variable, dataflow_set *);
470 static void **set_slot_part (dataflow_set *, rtx, void **,
471                              decl_or_value, HOST_WIDE_INT,
472                              enum var_init_status, rtx);
473 static void set_variable_part (dataflow_set *, rtx,
474                                decl_or_value, HOST_WIDE_INT,
475                                enum var_init_status, rtx, enum insert_option);
476 static void **clobber_slot_part (dataflow_set *, rtx,
477                                  void **, HOST_WIDE_INT, rtx);
478 static void clobber_variable_part (dataflow_set *, rtx,
479                                    decl_or_value, HOST_WIDE_INT, rtx);
480 static void **delete_slot_part (dataflow_set *, rtx, void **, HOST_WIDE_INT);
481 static void delete_variable_part (dataflow_set *, rtx,
482                                   decl_or_value, HOST_WIDE_INT);
483 static int emit_note_insn_var_location (void **, void *);
484 static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash);
485 static int emit_notes_for_differences_1 (void **, void *);
486 static int emit_notes_for_differences_2 (void **, void *);
487 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
488 static void emit_notes_in_bb (basic_block, dataflow_set *);
489 static void vt_emit_notes (void);
490
491 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
492 static void vt_add_function_parameters (void);
493 static bool vt_initialize (void);
494 static void vt_finalize (void);
495
496 /* Given a SET, calculate the amount of stack adjustment it contains
497    PRE- and POST-modifying stack pointer.
498    This function is similar to stack_adjust_offset.  */
499
500 static void
501 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
502                               HOST_WIDE_INT *post)
503 {
504   rtx src = SET_SRC (pattern);
505   rtx dest = SET_DEST (pattern);
506   enum rtx_code code;
507
508   if (dest == stack_pointer_rtx)
509     {
510       /* (set (reg sp) (plus (reg sp) (const_int))) */
511       code = GET_CODE (src);
512       if (! (code == PLUS || code == MINUS)
513           || XEXP (src, 0) != stack_pointer_rtx
514           || !CONST_INT_P (XEXP (src, 1)))
515         return;
516
517       if (code == MINUS)
518         *post += INTVAL (XEXP (src, 1));
519       else
520         *post -= INTVAL (XEXP (src, 1));
521     }
522   else if (MEM_P (dest))
523     {
524       /* (set (mem (pre_dec (reg sp))) (foo)) */
525       src = XEXP (dest, 0);
526       code = GET_CODE (src);
527
528       switch (code)
529         {
530         case PRE_MODIFY:
531         case POST_MODIFY:
532           if (XEXP (src, 0) == stack_pointer_rtx)
533             {
534               rtx val = XEXP (XEXP (src, 1), 1);
535               /* We handle only adjustments by constant amount.  */
536               gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
537                           CONST_INT_P (val));
538
539               if (code == PRE_MODIFY)
540                 *pre -= INTVAL (val);
541               else
542                 *post -= INTVAL (val);
543               break;
544             }
545           return;
546
547         case PRE_DEC:
548           if (XEXP (src, 0) == stack_pointer_rtx)
549             {
550               *pre += GET_MODE_SIZE (GET_MODE (dest));
551               break;
552             }
553           return;
554
555         case POST_DEC:
556           if (XEXP (src, 0) == stack_pointer_rtx)
557             {
558               *post += GET_MODE_SIZE (GET_MODE (dest));
559               break;
560             }
561           return;
562
563         case PRE_INC:
564           if (XEXP (src, 0) == stack_pointer_rtx)
565             {
566               *pre -= GET_MODE_SIZE (GET_MODE (dest));
567               break;
568             }
569           return;
570
571         case POST_INC:
572           if (XEXP (src, 0) == stack_pointer_rtx)
573             {
574               *post -= GET_MODE_SIZE (GET_MODE (dest));
575               break;
576             }
577           return;
578
579         default:
580           return;
581         }
582     }
583 }
584
585 /* Given an INSN, calculate the amount of stack adjustment it contains
586    PRE- and POST-modifying stack pointer.  */
587
588 static void
589 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
590                                    HOST_WIDE_INT *post)
591 {
592   rtx pattern;
593
594   *pre = 0;
595   *post = 0;
596
597   pattern = PATTERN (insn);
598   if (RTX_FRAME_RELATED_P (insn))
599     {
600       rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
601       if (expr)
602         pattern = XEXP (expr, 0);
603     }
604
605   if (GET_CODE (pattern) == SET)
606     stack_adjust_offset_pre_post (pattern, pre, post);
607   else if (GET_CODE (pattern) == PARALLEL
608            || GET_CODE (pattern) == SEQUENCE)
609     {
610       int i;
611
612       /* There may be stack adjustments inside compound insns.  Search
613          for them.  */
614       for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
615         if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
616           stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
617     }
618 }
619
620 /* Compute stack adjustments for all blocks by traversing DFS tree.
621    Return true when the adjustments on all incoming edges are consistent.
622    Heavily borrowed from pre_and_rev_post_order_compute.  */
623
624 static bool
625 vt_stack_adjustments (void)
626 {
627   edge_iterator *stack;
628   int sp;
629
630   /* Initialize entry block.  */
631   VTI (ENTRY_BLOCK_PTR)->visited = true;
632   VTI (ENTRY_BLOCK_PTR)->in.stack_adjust = INCOMING_FRAME_SP_OFFSET;
633   VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
634
635   /* Allocate stack for back-tracking up CFG.  */
636   stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
637   sp = 0;
638
639   /* Push the first edge on to the stack.  */
640   stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
641
642   while (sp)
643     {
644       edge_iterator ei;
645       basic_block src;
646       basic_block dest;
647
648       /* Look at the edge on the top of the stack.  */
649       ei = stack[sp - 1];
650       src = ei_edge (ei)->src;
651       dest = ei_edge (ei)->dest;
652
653       /* Check if the edge destination has been visited yet.  */
654       if (!VTI (dest)->visited)
655         {
656           rtx insn;
657           HOST_WIDE_INT pre, post, offset;
658           VTI (dest)->visited = true;
659           VTI (dest)->in.stack_adjust = offset = VTI (src)->out.stack_adjust;
660
661           if (dest != EXIT_BLOCK_PTR)
662             for (insn = BB_HEAD (dest);
663                  insn != NEXT_INSN (BB_END (dest));
664                  insn = NEXT_INSN (insn))
665               if (INSN_P (insn))
666                 {
667                   insn_stack_adjust_offset_pre_post (insn, &pre, &post);
668                   offset += pre + post;
669                 }
670
671           VTI (dest)->out.stack_adjust = offset;
672
673           if (EDGE_COUNT (dest->succs) > 0)
674             /* Since the DEST node has been visited for the first
675                time, check its successors.  */
676             stack[sp++] = ei_start (dest->succs);
677         }
678       else
679         {
680           /* Check whether the adjustments on the edges are the same.  */
681           if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
682             {
683               free (stack);
684               return false;
685             }
686
687           if (! ei_one_before_end_p (ei))
688             /* Go to the next edge.  */
689             ei_next (&stack[sp - 1]);
690           else
691             /* Return to previous level if there are no more edges.  */
692             sp--;
693         }
694     }
695
696   free (stack);
697   return true;
698 }
699
700 /* Compute a CFA-based value for the stack pointer.  */
701
702 static rtx
703 compute_cfa_pointer (HOST_WIDE_INT adjustment)
704 {
705   rtx cfa;
706
707 #ifdef FRAME_POINTER_CFA_OFFSET
708   adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
709   cfa = plus_constant (frame_pointer_rtx, adjustment);
710 #else
711   adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
712   cfa = plus_constant (arg_pointer_rtx, adjustment);
713 #endif
714
715   return cfa;
716 }
717
718 /* Adjustment for hard_frame_pointer_rtx to cfa base reg,
719    or -1 if the replacement shouldn't be done.  */
720 static HOST_WIDE_INT hard_frame_pointer_adjustment = -1;
721
722 /* Data for adjust_mems callback.  */
723
724 struct adjust_mem_data
725 {
726   bool store;
727   enum machine_mode mem_mode;
728   HOST_WIDE_INT stack_adjust;
729   rtx side_effects;
730 };
731
732 /* Helper function for adjusting used MEMs.  */
733
734 static rtx
735 adjust_mems (rtx loc, const_rtx old_rtx, void *data)
736 {
737   struct adjust_mem_data *amd = (struct adjust_mem_data *) data;
738   rtx mem, addr = loc, tem;
739   enum machine_mode mem_mode_save;
740   bool store_save;
741   switch (GET_CODE (loc))
742     {
743     case REG:
744       /* Don't do any sp or fp replacements outside of MEM addresses.  */
745       if (amd->mem_mode == VOIDmode)
746         return loc;
747       if (loc == stack_pointer_rtx
748           && !frame_pointer_needed)
749         return compute_cfa_pointer (amd->stack_adjust);
750       else if (loc == hard_frame_pointer_rtx
751                && frame_pointer_needed
752                && hard_frame_pointer_adjustment != -1)
753         return compute_cfa_pointer (hard_frame_pointer_adjustment);
754       return loc;
755     case MEM:
756       mem = loc;
757       if (!amd->store)
758         {
759           mem = targetm.delegitimize_address (mem);
760           if (mem != loc && !MEM_P (mem))
761             return simplify_replace_fn_rtx (mem, old_rtx, adjust_mems, data);
762         }
763
764       addr = XEXP (mem, 0);
765       mem_mode_save = amd->mem_mode;
766       amd->mem_mode = GET_MODE (mem);
767       store_save = amd->store;
768       amd->store = false;
769       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
770       amd->store = store_save;
771       amd->mem_mode = mem_mode_save;
772       if (mem == loc)
773         addr = targetm.delegitimize_address (addr);
774       if (addr != XEXP (mem, 0))
775         mem = replace_equiv_address_nv (mem, addr);
776       if (!amd->store)
777         mem = avoid_constant_pool_reference (mem);
778       return mem;
779     case PRE_INC:
780     case PRE_DEC:
781       addr = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
782                            GEN_INT (GET_CODE (loc) == PRE_INC
783                                     ? GET_MODE_SIZE (amd->mem_mode)
784                                     : -GET_MODE_SIZE (amd->mem_mode)));
785     case POST_INC:
786     case POST_DEC:
787       if (addr == loc)
788         addr = XEXP (loc, 0);
789       gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
790       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
791       tem = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
792                            GEN_INT ((GET_CODE (loc) == PRE_INC
793                                      || GET_CODE (loc) == POST_INC)
794                                     ? GET_MODE_SIZE (amd->mem_mode)
795                                     : -GET_MODE_SIZE (amd->mem_mode)));
796       amd->side_effects = alloc_EXPR_LIST (0,
797                                            gen_rtx_SET (VOIDmode,
798                                                         XEXP (loc, 0),
799                                                         tem),
800                                            amd->side_effects);
801       return addr;
802     case PRE_MODIFY:
803       addr = XEXP (loc, 1);
804     case POST_MODIFY:
805       if (addr == loc)
806         addr = XEXP (loc, 0);
807       gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
808       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
809       amd->side_effects = alloc_EXPR_LIST (0,
810                                            gen_rtx_SET (VOIDmode,
811                                                         XEXP (loc, 0),
812                                                         XEXP (loc, 1)),
813                                            amd->side_effects);
814       return addr;
815     case SUBREG:
816       /* First try without delegitimization of whole MEMs and
817          avoid_constant_pool_reference, which is more likely to succeed.  */
818       store_save = amd->store;
819       amd->store = true;
820       addr = simplify_replace_fn_rtx (SUBREG_REG (loc), old_rtx, adjust_mems,
821                                       data);
822       amd->store = store_save;
823       mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
824       if (mem == SUBREG_REG (loc))
825         return loc;
826       tem = simplify_gen_subreg (GET_MODE (loc), mem,
827                                  GET_MODE (SUBREG_REG (loc)),
828                                  SUBREG_BYTE (loc));
829       if (tem)
830         return tem;
831       tem = simplify_gen_subreg (GET_MODE (loc), addr,
832                                  GET_MODE (SUBREG_REG (loc)),
833                                  SUBREG_BYTE (loc));
834       if (tem)
835         return tem;
836       return gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
837     default:
838       break;
839     }
840   return NULL_RTX;
841 }
842
843 /* Helper function for replacement of uses.  */
844
845 static void
846 adjust_mem_uses (rtx *x, void *data)
847 {
848   rtx new_x = simplify_replace_fn_rtx (*x, NULL_RTX, adjust_mems, data);
849   if (new_x != *x)
850     validate_change (NULL_RTX, x, new_x, true);
851 }
852
853 /* Helper function for replacement of stores.  */
854
855 static void
856 adjust_mem_stores (rtx loc, const_rtx expr, void *data)
857 {
858   if (MEM_P (loc))
859     {
860       rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr), NULL_RTX,
861                                               adjust_mems, data);
862       if (new_dest != SET_DEST (expr))
863         {
864           rtx xexpr = CONST_CAST_RTX (expr);
865           validate_change (NULL_RTX, &SET_DEST (xexpr), new_dest, true);
866         }
867     }
868 }
869
870 /* Simplify INSN.  Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes,
871    replace them with their value in the insn and add the side-effects
872    as other sets to the insn.  */
873
874 static void
875 adjust_insn (basic_block bb, rtx insn)
876 {
877   struct adjust_mem_data amd;
878   rtx set;
879   amd.mem_mode = VOIDmode;
880   amd.stack_adjust = -VTI (bb)->out.stack_adjust;
881   amd.side_effects = NULL_RTX;
882
883   amd.store = true;
884   note_stores (PATTERN (insn), adjust_mem_stores, &amd);
885
886   amd.store = false;
887   note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
888
889   /* For read-only MEMs containing some constant, prefer those
890      constants.  */
891   set = single_set (insn);
892   if (set && MEM_P (SET_SRC (set)) && MEM_READONLY_P (SET_SRC (set)))
893     {
894       rtx note = find_reg_equal_equiv_note (insn);
895
896       if (note && CONSTANT_P (XEXP (note, 0)))
897         validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true);
898     }
899
900   if (amd.side_effects)
901     {
902       rtx *pat, new_pat, s;
903       int i, oldn, newn;
904
905       pat = &PATTERN (insn);
906       if (GET_CODE (*pat) == COND_EXEC)
907         pat = &COND_EXEC_CODE (*pat);
908       if (GET_CODE (*pat) == PARALLEL)
909         oldn = XVECLEN (*pat, 0);
910       else
911         oldn = 1;
912       for (s = amd.side_effects, newn = 0; s; newn++)
913         s = XEXP (s, 1);
914       new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn));
915       if (GET_CODE (*pat) == PARALLEL)
916         for (i = 0; i < oldn; i++)
917           XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i);
918       else
919         XVECEXP (new_pat, 0, 0) = *pat;
920       for (s = amd.side_effects, i = oldn; i < oldn + newn; i++, s = XEXP (s, 1))
921         XVECEXP (new_pat, 0, i) = XEXP (s, 0);
922       free_EXPR_LIST_list (&amd.side_effects);
923       validate_change (NULL_RTX, pat, new_pat, true);
924     }
925 }
926
927 /* Return true if a decl_or_value DV is a DECL or NULL.  */
928 static inline bool
929 dv_is_decl_p (decl_or_value dv)
930 {
931   return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE;
932 }
933
934 /* Return true if a decl_or_value is a VALUE rtl.  */
935 static inline bool
936 dv_is_value_p (decl_or_value dv)
937 {
938   return dv && !dv_is_decl_p (dv);
939 }
940
941 /* Return the decl in the decl_or_value.  */
942 static inline tree
943 dv_as_decl (decl_or_value dv)
944 {
945 #ifdef ENABLE_CHECKING
946   gcc_assert (dv_is_decl_p (dv));
947 #endif
948   return (tree) dv;
949 }
950
951 /* Return the value in the decl_or_value.  */
952 static inline rtx
953 dv_as_value (decl_or_value dv)
954 {
955 #ifdef ENABLE_CHECKING
956   gcc_assert (dv_is_value_p (dv));
957 #endif
958   return (rtx)dv;
959 }
960
961 /* Return the opaque pointer in the decl_or_value.  */
962 static inline void *
963 dv_as_opaque (decl_or_value dv)
964 {
965   return dv;
966 }
967
968 /* Return true if a decl_or_value must not have more than one variable
969    part.  */
970 static inline bool
971 dv_onepart_p (decl_or_value dv)
972 {
973   tree decl;
974
975   if (!MAY_HAVE_DEBUG_INSNS)
976     return false;
977
978   if (dv_is_value_p (dv))
979     return true;
980
981   decl = dv_as_decl (dv);
982
983   if (!decl)
984     return true;
985
986   if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
987     return true;
988
989   return (target_for_debug_bind (decl) != NULL_TREE);
990 }
991
992 /* Return the variable pool to be used for dv, depending on whether it
993    can have multiple parts or not.  */
994 static inline alloc_pool
995 dv_pool (decl_or_value dv)
996 {
997   return dv_onepart_p (dv) ? valvar_pool : var_pool;
998 }
999
1000 /* Build a decl_or_value out of a decl.  */
1001 static inline decl_or_value
1002 dv_from_decl (tree decl)
1003 {
1004   decl_or_value dv;
1005   dv = decl;
1006 #ifdef ENABLE_CHECKING
1007   gcc_assert (dv_is_decl_p (dv));
1008 #endif
1009   return dv;
1010 }
1011
1012 /* Build a decl_or_value out of a value.  */
1013 static inline decl_or_value
1014 dv_from_value (rtx value)
1015 {
1016   decl_or_value dv;
1017   dv = value;
1018 #ifdef ENABLE_CHECKING
1019   gcc_assert (dv_is_value_p (dv));
1020 #endif
1021   return dv;
1022 }
1023
1024 extern void debug_dv (decl_or_value dv);
1025
1026 void
1027 debug_dv (decl_or_value dv)
1028 {
1029   if (dv_is_value_p (dv))
1030     debug_rtx (dv_as_value (dv));
1031   else
1032     debug_generic_stmt (dv_as_decl (dv));
1033 }
1034
1035 typedef unsigned int dvuid;
1036
1037 /* Return the uid of DV.  */
1038
1039 static inline dvuid
1040 dv_uid (decl_or_value dv)
1041 {
1042   if (dv_is_value_p (dv))
1043     return CSELIB_VAL_PTR (dv_as_value (dv))->uid;
1044   else
1045     return DECL_UID (dv_as_decl (dv));
1046 }
1047
1048 /* Compute the hash from the uid.  */
1049
1050 static inline hashval_t
1051 dv_uid2hash (dvuid uid)
1052 {
1053   return uid;
1054 }
1055
1056 /* The hash function for a mask table in a shared_htab chain.  */
1057
1058 static inline hashval_t
1059 dv_htab_hash (decl_or_value dv)
1060 {
1061   return dv_uid2hash (dv_uid (dv));
1062 }
1063
1064 /* The hash function for variable_htab, computes the hash value
1065    from the declaration of variable X.  */
1066
1067 static hashval_t
1068 variable_htab_hash (const void *x)
1069 {
1070   const_variable const v = (const_variable) x;
1071
1072   return dv_htab_hash (v->dv);
1073 }
1074
1075 /* Compare the declaration of variable X with declaration Y.  */
1076
1077 static int
1078 variable_htab_eq (const void *x, const void *y)
1079 {
1080   const_variable const v = (const_variable) x;
1081   decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
1082
1083   return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
1084 }
1085
1086 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
1087
1088 static void
1089 variable_htab_free (void *elem)
1090 {
1091   int i;
1092   variable var = (variable) elem;
1093   location_chain node, next;
1094
1095   gcc_assert (var->refcount > 0);
1096
1097   var->refcount--;
1098   if (var->refcount > 0)
1099     return;
1100
1101   for (i = 0; i < var->n_var_parts; i++)
1102     {
1103       for (node = var->var_part[i].loc_chain; node; node = next)
1104         {
1105           next = node->next;
1106           pool_free (loc_chain_pool, node);
1107         }
1108       var->var_part[i].loc_chain = NULL;
1109     }
1110   pool_free (dv_pool (var->dv), var);
1111 }
1112
1113 /* The hash function for value_chains htab, computes the hash value
1114    from the VALUE.  */
1115
1116 static hashval_t
1117 value_chain_htab_hash (const void *x)
1118 {
1119   const_value_chain const v = (const_value_chain) x;
1120
1121   return dv_htab_hash (v->dv);
1122 }
1123
1124 /* Compare the VALUE X with VALUE Y.  */
1125
1126 static int
1127 value_chain_htab_eq (const void *x, const void *y)
1128 {
1129   const_value_chain const v = (const_value_chain) x;
1130   decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
1131
1132   return dv_as_opaque (v->dv) == dv_as_opaque (dv);
1133 }
1134
1135 /* Initialize the set (array) SET of attrs to empty lists.  */
1136
1137 static void
1138 init_attrs_list_set (attrs *set)
1139 {
1140   int i;
1141
1142   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1143     set[i] = NULL;
1144 }
1145
1146 /* Make the list *LISTP empty.  */
1147
1148 static void
1149 attrs_list_clear (attrs *listp)
1150 {
1151   attrs list, next;
1152
1153   for (list = *listp; list; list = next)
1154     {
1155       next = list->next;
1156       pool_free (attrs_pool, list);
1157     }
1158   *listp = NULL;
1159 }
1160
1161 /* Return true if the pair of DECL and OFFSET is the member of the LIST.  */
1162
1163 static attrs
1164 attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
1165 {
1166   for (; list; list = list->next)
1167     if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
1168       return list;
1169   return NULL;
1170 }
1171
1172 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
1173
1174 static void
1175 attrs_list_insert (attrs *listp, decl_or_value dv,
1176                    HOST_WIDE_INT offset, rtx loc)
1177 {
1178   attrs list;
1179
1180   list = (attrs) pool_alloc (attrs_pool);
1181   list->loc = loc;
1182   list->dv = dv;
1183   list->offset = offset;
1184   list->next = *listp;
1185   *listp = list;
1186 }
1187
1188 /* Copy all nodes from SRC and create a list *DSTP of the copies.  */
1189
1190 static void
1191 attrs_list_copy (attrs *dstp, attrs src)
1192 {
1193   attrs n;
1194
1195   attrs_list_clear (dstp);
1196   for (; src; src = src->next)
1197     {
1198       n = (attrs) pool_alloc (attrs_pool);
1199       n->loc = src->loc;
1200       n->dv = src->dv;
1201       n->offset = src->offset;
1202       n->next = *dstp;
1203       *dstp = n;
1204     }
1205 }
1206
1207 /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
1208
1209 static void
1210 attrs_list_union (attrs *dstp, attrs src)
1211 {
1212   for (; src; src = src->next)
1213     {
1214       if (!attrs_list_member (*dstp, src->dv, src->offset))
1215         attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1216     }
1217 }
1218
1219 /* Combine nodes that are not onepart nodes from SRC and SRC2 into
1220    *DSTP.  */
1221
1222 static void
1223 attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
1224 {
1225   gcc_assert (!*dstp);
1226   for (; src; src = src->next)
1227     {
1228       if (!dv_onepart_p (src->dv))
1229         attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1230     }
1231   for (src = src2; src; src = src->next)
1232     {
1233       if (!dv_onepart_p (src->dv)
1234           && !attrs_list_member (*dstp, src->dv, src->offset))
1235         attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1236     }
1237 }
1238
1239 /* Shared hashtable support.  */
1240
1241 /* Return true if VARS is shared.  */
1242
1243 static inline bool
1244 shared_hash_shared (shared_hash vars)
1245 {
1246   return vars->refcount > 1;
1247 }
1248
1249 /* Return the hash table for VARS.  */
1250
1251 static inline htab_t
1252 shared_hash_htab (shared_hash vars)
1253 {
1254   return vars->htab;
1255 }
1256
1257 /* Return true if VAR is shared, or maybe because VARS is shared.  */
1258
1259 static inline bool
1260 shared_var_p (variable var, shared_hash vars)
1261 {
1262   /* Don't count an entry in the changed_variables table as a duplicate.  */
1263   return ((var->refcount > 1 + (int) var->in_changed_variables)
1264           || shared_hash_shared (vars));
1265 }
1266
1267 /* Copy variables into a new hash table.  */
1268
1269 static shared_hash
1270 shared_hash_unshare (shared_hash vars)
1271 {
1272   shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
1273   gcc_assert (vars->refcount > 1);
1274   new_vars->refcount = 1;
1275   new_vars->htab
1276     = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
1277                    variable_htab_eq, variable_htab_free);
1278   vars_copy (new_vars->htab, vars->htab);
1279   vars->refcount--;
1280   return new_vars;
1281 }
1282
1283 /* Increment reference counter on VARS and return it.  */
1284
1285 static inline shared_hash
1286 shared_hash_copy (shared_hash vars)
1287 {
1288   vars->refcount++;
1289   return vars;
1290 }
1291
1292 /* Decrement reference counter and destroy hash table if not shared
1293    anymore.  */
1294
1295 static void
1296 shared_hash_destroy (shared_hash vars)
1297 {
1298   gcc_assert (vars->refcount > 0);
1299   if (--vars->refcount == 0)
1300     {
1301       htab_delete (vars->htab);
1302       pool_free (shared_hash_pool, vars);
1303     }
1304 }
1305
1306 /* Unshare *PVARS if shared and return slot for DV.  If INS is
1307    INSERT, insert it if not already present.  */
1308
1309 static inline void **
1310 shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
1311                                  hashval_t dvhash, enum insert_option ins)
1312 {
1313   if (shared_hash_shared (*pvars))
1314     *pvars = shared_hash_unshare (*pvars);
1315   return htab_find_slot_with_hash (shared_hash_htab (*pvars), dv, dvhash, ins);
1316 }
1317
1318 static inline void **
1319 shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
1320                                enum insert_option ins)
1321 {
1322   return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
1323 }
1324
1325 /* Return slot for DV, if it is already present in the hash table.
1326    If it is not present, insert it only VARS is not shared, otherwise
1327    return NULL.  */
1328
1329 static inline void **
1330 shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
1331 {
1332   return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
1333                                    shared_hash_shared (vars)
1334                                    ? NO_INSERT : INSERT);
1335 }
1336
1337 static inline void **
1338 shared_hash_find_slot (shared_hash vars, decl_or_value dv)
1339 {
1340   return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
1341 }
1342
1343 /* Return slot for DV only if it is already present in the hash table.  */
1344
1345 static inline void **
1346 shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
1347                                   hashval_t dvhash)
1348 {
1349   return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
1350                                    NO_INSERT);
1351 }
1352
1353 static inline void **
1354 shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
1355 {
1356   return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
1357 }
1358
1359 /* Return variable for DV or NULL if not already present in the hash
1360    table.  */
1361
1362 static inline variable
1363 shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
1364 {
1365   return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash);
1366 }
1367
1368 static inline variable
1369 shared_hash_find (shared_hash vars, decl_or_value dv)
1370 {
1371   return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
1372 }
1373
1374 /* Return true if TVAL is better than CVAL as a canonival value.  We
1375    choose lowest-numbered VALUEs, using the RTX address as a
1376    tie-breaker.  The idea is to arrange them into a star topology,
1377    such that all of them are at most one step away from the canonical
1378    value, and the canonical value has backlinks to all of them, in
1379    addition to all the actual locations.  We don't enforce this
1380    topology throughout the entire dataflow analysis, though.
1381  */
1382
1383 static inline bool
1384 canon_value_cmp (rtx tval, rtx cval)
1385 {
1386   return !cval
1387     || CSELIB_VAL_PTR (tval)->uid < CSELIB_VAL_PTR (cval)->uid;
1388 }
1389
1390 static bool dst_can_be_shared;
1391
1392 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
1393
1394 static void **
1395 unshare_variable (dataflow_set *set, void **slot, variable var,
1396                   enum var_init_status initialized)
1397 {
1398   variable new_var;
1399   int i;
1400
1401   new_var = (variable) pool_alloc (dv_pool (var->dv));
1402   new_var->dv = var->dv;
1403   new_var->refcount = 1;
1404   var->refcount--;
1405   new_var->n_var_parts = var->n_var_parts;
1406   new_var->cur_loc_changed = var->cur_loc_changed;
1407   var->cur_loc_changed = false;
1408   new_var->in_changed_variables = false;
1409
1410   if (! flag_var_tracking_uninit)
1411     initialized = VAR_INIT_STATUS_INITIALIZED;
1412
1413   for (i = 0; i < var->n_var_parts; i++)
1414     {
1415       location_chain node;
1416       location_chain *nextp;
1417
1418       new_var->var_part[i].offset = var->var_part[i].offset;
1419       nextp = &new_var->var_part[i].loc_chain;
1420       for (node = var->var_part[i].loc_chain; node; node = node->next)
1421         {
1422           location_chain new_lc;
1423
1424           new_lc = (location_chain) pool_alloc (loc_chain_pool);
1425           new_lc->next = NULL;
1426           if (node->init > initialized)
1427             new_lc->init = node->init;
1428           else
1429             new_lc->init = initialized;
1430           if (node->set_src && !(MEM_P (node->set_src)))
1431             new_lc->set_src = node->set_src;
1432           else
1433             new_lc->set_src = NULL;
1434           new_lc->loc = node->loc;
1435
1436           *nextp = new_lc;
1437           nextp = &new_lc->next;
1438         }
1439
1440       new_var->var_part[i].cur_loc = var->var_part[i].cur_loc;
1441     }
1442
1443   dst_can_be_shared = false;
1444   if (shared_hash_shared (set->vars))
1445     slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT);
1446   else if (set->traversed_vars && set->vars != set->traversed_vars)
1447     slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
1448   *slot = new_var;
1449   if (var->in_changed_variables)
1450     {
1451       void **cslot
1452         = htab_find_slot_with_hash (changed_variables, var->dv,
1453                                     dv_htab_hash (var->dv), NO_INSERT);
1454       gcc_assert (*cslot == (void *) var);
1455       var->in_changed_variables = false;
1456       variable_htab_free (var);
1457       *cslot = new_var;
1458       new_var->in_changed_variables = true;
1459     }
1460   return slot;
1461 }
1462
1463 /* Add a variable from *SLOT to hash table DATA and increase its reference
1464    count.  */
1465
1466 static int
1467 vars_copy_1 (void **slot, void *data)
1468 {
1469   htab_t dst = (htab_t) data;
1470   variable src;
1471   void **dstp;
1472
1473   src = (variable) *slot;
1474   src->refcount++;
1475
1476   dstp = htab_find_slot_with_hash (dst, src->dv,
1477                                    dv_htab_hash (src->dv),
1478                                    INSERT);
1479   *dstp = src;
1480
1481   /* Continue traversing the hash table.  */
1482   return 1;
1483 }
1484
1485 /* Copy all variables from hash table SRC to hash table DST.  */
1486
1487 static void
1488 vars_copy (htab_t dst, htab_t src)
1489 {
1490   htab_traverse_noresize (src, vars_copy_1, dst);
1491 }
1492
1493 /* Map a decl to its main debug decl.  */
1494
1495 static inline tree
1496 var_debug_decl (tree decl)
1497 {
1498   if (decl && DECL_P (decl)
1499       && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
1500       && DECL_P (DECL_DEBUG_EXPR (decl)))
1501     decl = DECL_DEBUG_EXPR (decl);
1502
1503   return decl;
1504 }
1505
1506 /* Set the register LOC to contain DV, OFFSET.  */
1507
1508 static void
1509 var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1510                   decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1511                   enum insert_option iopt)
1512 {
1513   attrs node;
1514   bool decl_p = dv_is_decl_p (dv);
1515
1516   if (decl_p)
1517     dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1518
1519   for (node = set->regs[REGNO (loc)]; node; node = node->next)
1520     if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
1521         && node->offset == offset)
1522       break;
1523   if (!node)
1524     attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc);
1525   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1526 }
1527
1528 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
1529
1530 static void
1531 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1532              rtx set_src)
1533 {
1534   tree decl = REG_EXPR (loc);
1535   HOST_WIDE_INT offset = REG_OFFSET (loc);
1536
1537   var_reg_decl_set (set, loc, initialized,
1538                     dv_from_decl (decl), offset, set_src, INSERT);
1539 }
1540
1541 static enum var_init_status
1542 get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
1543 {
1544   variable var;
1545   int i;
1546   enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
1547
1548   if (! flag_var_tracking_uninit)
1549     return VAR_INIT_STATUS_INITIALIZED;
1550
1551   var = shared_hash_find (set->vars, dv);
1552   if (var)
1553     {
1554       for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
1555         {
1556           location_chain nextp;
1557           for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1558             if (rtx_equal_p (nextp->loc, loc))
1559               {
1560                 ret_val = nextp->init;
1561                 break;
1562               }
1563         }
1564     }
1565
1566   return ret_val;
1567 }
1568
1569 /* Delete current content of register LOC in dataflow set SET and set
1570    the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  If
1571    MODIFY is true, any other live copies of the same variable part are
1572    also deleted from the dataflow set, otherwise the variable part is
1573    assumed to be copied from another location holding the same
1574    part.  */
1575
1576 static void
1577 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1578                         enum var_init_status initialized, rtx set_src)
1579 {
1580   tree decl = REG_EXPR (loc);
1581   HOST_WIDE_INT offset = REG_OFFSET (loc);
1582   attrs node, next;
1583   attrs *nextp;
1584
1585   decl = var_debug_decl (decl);
1586
1587   if (initialized == VAR_INIT_STATUS_UNKNOWN)
1588     initialized = get_init_value (set, loc, dv_from_decl (decl));
1589
1590   nextp = &set->regs[REGNO (loc)];
1591   for (node = *nextp; node; node = next)
1592     {
1593       next = node->next;
1594       if (dv_as_opaque (node->dv) != decl || node->offset != offset)
1595         {
1596           delete_variable_part (set, node->loc, node->dv, node->offset);
1597           pool_free (attrs_pool, node);
1598           *nextp = next;
1599         }
1600       else
1601         {
1602           node->loc = loc;
1603           nextp = &node->next;
1604         }
1605     }
1606   if (modify)
1607     clobber_variable_part (set, loc, dv_from_decl (decl), offset, set_src);
1608   var_reg_set (set, loc, initialized, set_src);
1609 }
1610
1611 /* Delete the association of register LOC in dataflow set SET with any
1612    variables that aren't onepart.  If CLOBBER is true, also delete any
1613    other live copies of the same variable part, and delete the
1614    association with onepart dvs too.  */
1615
1616 static void
1617 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
1618 {
1619   attrs *nextp = &set->regs[REGNO (loc)];
1620   attrs node, next;
1621
1622   if (clobber)
1623     {
1624       tree decl = REG_EXPR (loc);
1625       HOST_WIDE_INT offset = REG_OFFSET (loc);
1626
1627       decl = var_debug_decl (decl);
1628
1629       clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
1630     }
1631
1632   for (node = *nextp; node; node = next)
1633     {
1634       next = node->next;
1635       if (clobber || !dv_onepart_p (node->dv))
1636         {
1637           delete_variable_part (set, node->loc, node->dv, node->offset);
1638           pool_free (attrs_pool, node);
1639           *nextp = next;
1640         }
1641       else
1642         nextp = &node->next;
1643     }
1644 }
1645
1646 /* Delete content of register with number REGNO in dataflow set SET.  */
1647
1648 static void
1649 var_regno_delete (dataflow_set *set, int regno)
1650 {
1651   attrs *reg = &set->regs[regno];
1652   attrs node, next;
1653
1654   for (node = *reg; node; node = next)
1655     {
1656       next = node->next;
1657       delete_variable_part (set, node->loc, node->dv, node->offset);
1658       pool_free (attrs_pool, node);
1659     }
1660   *reg = NULL;
1661 }
1662
1663 /* Set the location of DV, OFFSET as the MEM LOC.  */
1664
1665 static void
1666 var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1667                   decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1668                   enum insert_option iopt)
1669 {
1670   if (dv_is_decl_p (dv))
1671     dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1672
1673   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1674 }
1675
1676 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
1677    SET to LOC.
1678    Adjust the address first if it is stack pointer based.  */
1679
1680 static void
1681 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1682              rtx set_src)
1683 {
1684   tree decl = MEM_EXPR (loc);
1685   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1686
1687   var_mem_decl_set (set, loc, initialized,
1688                     dv_from_decl (decl), offset, set_src, INSERT);
1689 }
1690
1691 /* Delete and set the location part of variable MEM_EXPR (LOC) in
1692    dataflow set SET to LOC.  If MODIFY is true, any other live copies
1693    of the same variable part are also deleted from the dataflow set,
1694    otherwise the variable part is assumed to be copied from another
1695    location holding the same part.
1696    Adjust the address first if it is stack pointer based.  */
1697
1698 static void
1699 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1700                         enum var_init_status initialized, rtx set_src)
1701 {
1702   tree decl = MEM_EXPR (loc);
1703   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1704
1705   decl = var_debug_decl (decl);
1706
1707   if (initialized == VAR_INIT_STATUS_UNKNOWN)
1708     initialized = get_init_value (set, loc, dv_from_decl (decl));
1709
1710   if (modify)
1711     clobber_variable_part (set, NULL, dv_from_decl (decl), offset, set_src);
1712   var_mem_set (set, loc, initialized, set_src);
1713 }
1714
1715 /* Delete the location part LOC from dataflow set SET.  If CLOBBER is
1716    true, also delete any other live copies of the same variable part.
1717    Adjust the address first if it is stack pointer based.  */
1718
1719 static void
1720 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1721 {
1722   tree decl = MEM_EXPR (loc);
1723   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1724
1725   decl = var_debug_decl (decl);
1726   if (clobber)
1727     clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
1728   delete_variable_part (set, loc, dv_from_decl (decl), offset);
1729 }
1730
1731 /* Bind a value to a location it was just stored in.  If MODIFIED
1732    holds, assume the location was modified, detaching it from any
1733    values bound to it.  */
1734
1735 static void
1736 val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
1737 {
1738   cselib_val *v = CSELIB_VAL_PTR (val);
1739
1740   gcc_assert (cselib_preserved_value_p (v));
1741
1742   if (dump_file)
1743     {
1744       fprintf (dump_file, "%i: ", INSN_UID (insn));
1745       print_inline_rtx (dump_file, val, 0);
1746       fprintf (dump_file, " stored in ");
1747       print_inline_rtx (dump_file, loc, 0);
1748       if (v->locs)
1749         {
1750           struct elt_loc_list *l;
1751           for (l = v->locs; l; l = l->next)
1752             {
1753               fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn));
1754               print_inline_rtx (dump_file, l->loc, 0);
1755             }
1756         }
1757       fprintf (dump_file, "\n");
1758     }
1759
1760   if (REG_P (loc))
1761     {
1762       if (modified)
1763         var_regno_delete (set, REGNO (loc));
1764       var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1765                         dv_from_value (val), 0, NULL_RTX, INSERT);
1766     }
1767   else if (MEM_P (loc))
1768     var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1769                       dv_from_value (val), 0, NULL_RTX, INSERT);
1770   else
1771     set_variable_part (set, loc, dv_from_value (val), 0,
1772                        VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1773 }
1774
1775 /* Reset this node, detaching all its equivalences.  Return the slot
1776    in the variable hash table that holds dv, if there is one.  */
1777
1778 static void
1779 val_reset (dataflow_set *set, decl_or_value dv)
1780 {
1781   variable var = shared_hash_find (set->vars, dv) ;
1782   location_chain node;
1783   rtx cval;
1784
1785   if (!var || !var->n_var_parts)
1786     return;
1787
1788   gcc_assert (var->n_var_parts == 1);
1789
1790   cval = NULL;
1791   for (node = var->var_part[0].loc_chain; node; node = node->next)
1792     if (GET_CODE (node->loc) == VALUE
1793         && canon_value_cmp (node->loc, cval))
1794       cval = node->loc;
1795
1796   for (node = var->var_part[0].loc_chain; node; node = node->next)
1797     if (GET_CODE (node->loc) == VALUE && cval != node->loc)
1798       {
1799         /* Redirect the equivalence link to the new canonical
1800            value, or simply remove it if it would point at
1801            itself.  */
1802         if (cval)
1803           set_variable_part (set, cval, dv_from_value (node->loc),
1804                              0, node->init, node->set_src, NO_INSERT);
1805         delete_variable_part (set, dv_as_value (dv),
1806                               dv_from_value (node->loc), 0);
1807       }
1808
1809   if (cval)
1810     {
1811       decl_or_value cdv = dv_from_value (cval);
1812
1813       /* Keep the remaining values connected, accummulating links
1814          in the canonical value.  */
1815       for (node = var->var_part[0].loc_chain; node; node = node->next)
1816         {
1817           if (node->loc == cval)
1818             continue;
1819           else if (GET_CODE (node->loc) == REG)
1820             var_reg_decl_set (set, node->loc, node->init, cdv, 0,
1821                               node->set_src, NO_INSERT);
1822           else if (GET_CODE (node->loc) == MEM)
1823             var_mem_decl_set (set, node->loc, node->init, cdv, 0,
1824                               node->set_src, NO_INSERT);
1825           else
1826             set_variable_part (set, node->loc, cdv, 0,
1827                                node->init, node->set_src, NO_INSERT);
1828         }
1829     }
1830
1831   /* We remove this last, to make sure that the canonical value is not
1832      removed to the point of requiring reinsertion.  */
1833   if (cval)
1834     delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
1835
1836   clobber_variable_part (set, NULL, dv, 0, NULL);
1837
1838   /* ??? Should we make sure there aren't other available values or
1839      variables whose values involve this one other than by
1840      equivalence?  E.g., at the very least we should reset MEMs, those
1841      shouldn't be too hard to find cselib-looking up the value as an
1842      address, then locating the resulting value in our own hash
1843      table.  */
1844 }
1845
1846 /* Find the values in a given location and map the val to another
1847    value, if it is unique, or add the location as one holding the
1848    value.  */
1849
1850 static void
1851 val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
1852 {
1853   decl_or_value dv = dv_from_value (val);
1854
1855   if (dump_file && (dump_flags & TDF_DETAILS))
1856     {
1857       if (insn)
1858         fprintf (dump_file, "%i: ", INSN_UID (insn));
1859       else
1860         fprintf (dump_file, "head: ");
1861       print_inline_rtx (dump_file, val, 0);
1862       fputs (" is at ", dump_file);
1863       print_inline_rtx (dump_file, loc, 0);
1864       fputc ('\n', dump_file);
1865     }
1866
1867   val_reset (set, dv);
1868
1869   if (REG_P (loc))
1870     {
1871       attrs node, found = NULL;
1872
1873       for (node = set->regs[REGNO (loc)]; node; node = node->next)
1874         if (dv_is_value_p (node->dv)
1875             && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc))
1876           {
1877             found = node;
1878
1879             /* Map incoming equivalences.  ??? Wouldn't it be nice if
1880              we just started sharing the location lists?  Maybe a
1881              circular list ending at the value itself or some
1882              such.  */
1883             set_variable_part (set, dv_as_value (node->dv),
1884                                dv_from_value (val), node->offset,
1885                                VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1886             set_variable_part (set, val, node->dv, node->offset,
1887                                VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1888           }
1889
1890       /* If we didn't find any equivalence, we need to remember that
1891          this value is held in the named register.  */
1892       if (!found)
1893         var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1894                           dv_from_value (val), 0, NULL_RTX, INSERT);
1895     }
1896   else if (MEM_P (loc))
1897     /* ??? Merge equivalent MEMs.  */
1898     var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1899                       dv_from_value (val), 0, NULL_RTX, INSERT);
1900   else
1901     /* ??? Merge equivalent expressions.  */
1902     set_variable_part (set, loc, dv_from_value (val), 0,
1903                        VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1904 }
1905
1906 /* Initialize dataflow set SET to be empty.
1907    VARS_SIZE is the initial size of hash table VARS.  */
1908
1909 static void
1910 dataflow_set_init (dataflow_set *set)
1911 {
1912   init_attrs_list_set (set->regs);
1913   set->vars = shared_hash_copy (empty_shared_hash);
1914   set->stack_adjust = 0;
1915   set->traversed_vars = NULL;
1916 }
1917
1918 /* Delete the contents of dataflow set SET.  */
1919
1920 static void
1921 dataflow_set_clear (dataflow_set *set)
1922 {
1923   int i;
1924
1925   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1926     attrs_list_clear (&set->regs[i]);
1927
1928   shared_hash_destroy (set->vars);
1929   set->vars = shared_hash_copy (empty_shared_hash);
1930 }
1931
1932 /* Copy the contents of dataflow set SRC to DST.  */
1933
1934 static void
1935 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1936 {
1937   int i;
1938
1939   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1940     attrs_list_copy (&dst->regs[i], src->regs[i]);
1941
1942   shared_hash_destroy (dst->vars);
1943   dst->vars = shared_hash_copy (src->vars);
1944   dst->stack_adjust = src->stack_adjust;
1945 }
1946
1947 /* Information for merging lists of locations for a given offset of variable.
1948  */
1949 struct variable_union_info
1950 {
1951   /* Node of the location chain.  */
1952   location_chain lc;
1953
1954   /* The sum of positions in the input chains.  */
1955   int pos;
1956
1957   /* The position in the chain of DST dataflow set.  */
1958   int pos_dst;
1959 };
1960
1961 /* Buffer for location list sorting and its allocated size.  */
1962 static struct variable_union_info *vui_vec;
1963 static int vui_allocated;
1964
1965 /* Compare function for qsort, order the structures by POS element.  */
1966
1967 static int
1968 variable_union_info_cmp_pos (const void *n1, const void *n2)
1969 {
1970   const struct variable_union_info *const i1 =
1971     (const struct variable_union_info *) n1;
1972   const struct variable_union_info *const i2 =
1973     ( const struct variable_union_info *) n2;
1974
1975   if (i1->pos != i2->pos)
1976     return i1->pos - i2->pos;
1977
1978   return (i1->pos_dst - i2->pos_dst);
1979 }
1980
1981 /* Compute union of location parts of variable *SLOT and the same variable
1982    from hash table DATA.  Compute "sorted" union of the location chains
1983    for common offsets, i.e. the locations of a variable part are sorted by
1984    a priority where the priority is the sum of the positions in the 2 chains
1985    (if a location is only in one list the position in the second list is
1986    defined to be larger than the length of the chains).
1987    When we are updating the location parts the newest location is in the
1988    beginning of the chain, so when we do the described "sorted" union
1989    we keep the newest locations in the beginning.  */
1990
1991 static int
1992 variable_union (void **slot, void *data)
1993 {
1994   variable src, dst;
1995   void **dstp;
1996   dataflow_set *set = (dataflow_set *) data;
1997   int i, j, k;
1998
1999   src = (variable) *slot;
2000   dstp = shared_hash_find_slot (set->vars, src->dv);
2001   if (!dstp || !*dstp)
2002     {
2003       src->refcount++;
2004
2005       dst_can_be_shared = false;
2006       if (!dstp)
2007         dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT);
2008
2009       *dstp = src;
2010
2011       /* Continue traversing the hash table.  */
2012       return 1;
2013     }
2014   else
2015     dst = (variable) *dstp;
2016
2017   gcc_assert (src->n_var_parts);
2018
2019   /* We can combine one-part variables very efficiently, because their
2020      entries are in canonical order.  */
2021   if (dv_onepart_p (src->dv))
2022     {
2023       location_chain *nodep, dnode, snode;
2024
2025       gcc_assert (src->n_var_parts == 1);
2026       gcc_assert (dst->n_var_parts == 1);
2027
2028       snode = src->var_part[0].loc_chain;
2029       gcc_assert (snode);
2030
2031     restart_onepart_unshared:
2032       nodep = &dst->var_part[0].loc_chain;
2033       dnode = *nodep;
2034       gcc_assert (dnode);
2035
2036       while (snode)
2037         {
2038           int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1;
2039
2040           if (r > 0)
2041             {
2042               location_chain nnode;
2043
2044               if (shared_var_p (dst, set->vars))
2045                 {
2046                   dstp = unshare_variable (set, dstp, dst,
2047                                            VAR_INIT_STATUS_INITIALIZED);
2048                   dst = (variable)*dstp;
2049                   goto restart_onepart_unshared;
2050                 }
2051
2052               *nodep = nnode = (location_chain) pool_alloc (loc_chain_pool);
2053               nnode->loc = snode->loc;
2054               nnode->init = snode->init;
2055               if (!snode->set_src || MEM_P (snode->set_src))
2056                 nnode->set_src = NULL;
2057               else
2058                 nnode->set_src = snode->set_src;
2059               nnode->next = dnode;
2060               dnode = nnode;
2061             }
2062 #ifdef ENABLE_CHECKING
2063           else if (r == 0)
2064             gcc_assert (rtx_equal_p (dnode->loc, snode->loc));
2065 #endif
2066
2067           if (r >= 0)
2068             snode = snode->next;
2069
2070           nodep = &dnode->next;
2071           dnode = *nodep;
2072         }
2073
2074       return 1;
2075     }
2076
2077   /* Count the number of location parts, result is K.  */
2078   for (i = 0, j = 0, k = 0;
2079        i < src->n_var_parts && j < dst->n_var_parts; k++)
2080     {
2081       if (src->var_part[i].offset == dst->var_part[j].offset)
2082         {
2083           i++;
2084           j++;
2085         }
2086       else if (src->var_part[i].offset < dst->var_part[j].offset)
2087         i++;
2088       else
2089         j++;
2090     }
2091   k += src->n_var_parts - i;
2092   k += dst->n_var_parts - j;
2093
2094   /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2095      thus there are at most MAX_VAR_PARTS different offsets.  */
2096   gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS);
2097
2098   if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
2099     {
2100       dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
2101       dst = (variable)*dstp;
2102     }
2103
2104   i = src->n_var_parts - 1;
2105   j = dst->n_var_parts - 1;
2106   dst->n_var_parts = k;
2107
2108   for (k--; k >= 0; k--)
2109     {
2110       location_chain node, node2;
2111
2112       if (i >= 0 && j >= 0
2113           && src->var_part[i].offset == dst->var_part[j].offset)
2114         {
2115           /* Compute the "sorted" union of the chains, i.e. the locations which
2116              are in both chains go first, they are sorted by the sum of
2117              positions in the chains.  */
2118           int dst_l, src_l;
2119           int ii, jj, n;
2120           struct variable_union_info *vui;
2121
2122           /* If DST is shared compare the location chains.
2123              If they are different we will modify the chain in DST with
2124              high probability so make a copy of DST.  */
2125           if (shared_var_p (dst, set->vars))
2126             {
2127               for (node = src->var_part[i].loc_chain,
2128                    node2 = dst->var_part[j].loc_chain; node && node2;
2129                    node = node->next, node2 = node2->next)
2130                 {
2131                   if (!((REG_P (node2->loc)
2132                          && REG_P (node->loc)
2133                          && REGNO (node2->loc) == REGNO (node->loc))
2134                         || rtx_equal_p (node2->loc, node->loc)))
2135                     {
2136                       if (node2->init < node->init)
2137                         node2->init = node->init;
2138                       break;
2139                     }
2140                 }
2141               if (node || node2)
2142                 {
2143                   dstp = unshare_variable (set, dstp, dst,
2144                                            VAR_INIT_STATUS_UNKNOWN);
2145                   dst = (variable)*dstp;
2146                 }
2147             }
2148
2149           src_l = 0;
2150           for (node = src->var_part[i].loc_chain; node; node = node->next)
2151             src_l++;
2152           dst_l = 0;
2153           for (node = dst->var_part[j].loc_chain; node; node = node->next)
2154             dst_l++;
2155
2156           if (dst_l == 1)
2157             {
2158               /* The most common case, much simpler, no qsort is needed.  */
2159               location_chain dstnode = dst->var_part[j].loc_chain;
2160               dst->var_part[k].loc_chain = dstnode;
2161               dst->var_part[k].offset = dst->var_part[j].offset;
2162               node2 = dstnode;
2163               for (node = src->var_part[i].loc_chain; node; node = node->next)
2164                 if (!((REG_P (dstnode->loc)
2165                        && REG_P (node->loc)
2166                        && REGNO (dstnode->loc) == REGNO (node->loc))
2167                       || rtx_equal_p (dstnode->loc, node->loc)))
2168                   {
2169                     location_chain new_node;
2170
2171                     /* Copy the location from SRC.  */
2172                     new_node = (location_chain) pool_alloc (loc_chain_pool);
2173                     new_node->loc = node->loc;
2174                     new_node->init = node->init;
2175                     if (!node->set_src || MEM_P (node->set_src))
2176                       new_node->set_src = NULL;
2177                     else
2178                       new_node->set_src = node->set_src;
2179                     node2->next = new_node;
2180                     node2 = new_node;
2181                   }
2182               node2->next = NULL;
2183             }
2184           else
2185             {
2186               if (src_l + dst_l > vui_allocated)
2187                 {
2188                   vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
2189                   vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
2190                                         vui_allocated);
2191                 }
2192               vui = vui_vec;
2193
2194               /* Fill in the locations from DST.  */
2195               for (node = dst->var_part[j].loc_chain, jj = 0; node;
2196                    node = node->next, jj++)
2197                 {
2198                   vui[jj].lc = node;
2199                   vui[jj].pos_dst = jj;
2200
2201                   /* Pos plus value larger than a sum of 2 valid positions.  */
2202                   vui[jj].pos = jj + src_l + dst_l;
2203                 }
2204
2205               /* Fill in the locations from SRC.  */
2206               n = dst_l;
2207               for (node = src->var_part[i].loc_chain, ii = 0; node;
2208                    node = node->next, ii++)
2209                 {
2210                   /* Find location from NODE.  */
2211                   for (jj = 0; jj < dst_l; jj++)
2212                     {
2213                       if ((REG_P (vui[jj].lc->loc)
2214                            && REG_P (node->loc)
2215                            && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
2216                           || rtx_equal_p (vui[jj].lc->loc, node->loc))
2217                         {
2218                           vui[jj].pos = jj + ii;
2219                           break;
2220                         }
2221                     }
2222                   if (jj >= dst_l)      /* The location has not been found.  */
2223                     {
2224                       location_chain new_node;
2225
2226                       /* Copy the location from SRC.  */
2227                       new_node = (location_chain) pool_alloc (loc_chain_pool);
2228                       new_node->loc = node->loc;
2229                       new_node->init = node->init;
2230                       if (!node->set_src || MEM_P (node->set_src))
2231                         new_node->set_src = NULL;
2232                       else
2233                         new_node->set_src = node->set_src;
2234                       vui[n].lc = new_node;
2235                       vui[n].pos_dst = src_l + dst_l;
2236                       vui[n].pos = ii + src_l + dst_l;
2237                       n++;
2238                     }
2239                 }
2240
2241               if (dst_l == 2)
2242                 {
2243                   /* Special case still very common case.  For dst_l == 2
2244                      all entries dst_l ... n-1 are sorted, with for i >= dst_l
2245                      vui[i].pos == i + src_l + dst_l.  */
2246                   if (vui[0].pos > vui[1].pos)
2247                     {
2248                       /* Order should be 1, 0, 2... */
2249                       dst->var_part[k].loc_chain = vui[1].lc;
2250                       vui[1].lc->next = vui[0].lc;
2251                       if (n >= 3)
2252                         {
2253                           vui[0].lc->next = vui[2].lc;
2254                           vui[n - 1].lc->next = NULL;
2255                         }
2256                       else
2257                         vui[0].lc->next = NULL;
2258                       ii = 3;
2259                     }
2260                   else
2261                     {
2262                       dst->var_part[k].loc_chain = vui[0].lc;
2263                       if (n >= 3 && vui[2].pos < vui[1].pos)
2264                         {
2265                           /* Order should be 0, 2, 1, 3... */
2266                           vui[0].lc->next = vui[2].lc;
2267                           vui[2].lc->next = vui[1].lc;
2268                           if (n >= 4)
2269                             {
2270                               vui[1].lc->next = vui[3].lc;
2271                               vui[n - 1].lc->next = NULL;
2272                             }
2273                           else
2274                             vui[1].lc->next = NULL;
2275                           ii = 4;
2276                         }
2277                       else
2278                         {
2279                           /* Order should be 0, 1, 2... */
2280                           ii = 1;
2281                           vui[n - 1].lc->next = NULL;
2282                         }
2283                     }
2284                   for (; ii < n; ii++)
2285                     vui[ii - 1].lc->next = vui[ii].lc;
2286                 }
2287               else
2288                 {
2289                   qsort (vui, n, sizeof (struct variable_union_info),
2290                          variable_union_info_cmp_pos);
2291
2292                   /* Reconnect the nodes in sorted order.  */
2293                   for (ii = 1; ii < n; ii++)
2294                     vui[ii - 1].lc->next = vui[ii].lc;
2295                   vui[n - 1].lc->next = NULL;
2296                   dst->var_part[k].loc_chain = vui[0].lc;
2297                 }
2298
2299               dst->var_part[k].offset = dst->var_part[j].offset;
2300             }
2301           i--;
2302           j--;
2303         }
2304       else if ((i >= 0 && j >= 0
2305                 && src->var_part[i].offset < dst->var_part[j].offset)
2306                || i < 0)
2307         {
2308           dst->var_part[k] = dst->var_part[j];
2309           j--;
2310         }
2311       else if ((i >= 0 && j >= 0
2312                 && src->var_part[i].offset > dst->var_part[j].offset)
2313                || j < 0)
2314         {
2315           location_chain *nextp;
2316
2317           /* Copy the chain from SRC.  */
2318           nextp = &dst->var_part[k].loc_chain;
2319           for (node = src->var_part[i].loc_chain; node; node = node->next)
2320             {
2321               location_chain new_lc;
2322
2323               new_lc = (location_chain) pool_alloc (loc_chain_pool);
2324               new_lc->next = NULL;
2325               new_lc->init = node->init;
2326               if (!node->set_src || MEM_P (node->set_src))
2327                 new_lc->set_src = NULL;
2328               else
2329                 new_lc->set_src = node->set_src;
2330               new_lc->loc = node->loc;
2331
2332               *nextp = new_lc;
2333               nextp = &new_lc->next;
2334             }
2335
2336           dst->var_part[k].offset = src->var_part[i].offset;
2337           i--;
2338         }
2339       dst->var_part[k].cur_loc = NULL;
2340     }
2341
2342   if (flag_var_tracking_uninit)
2343     for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
2344       {
2345         location_chain node, node2;
2346         for (node = src->var_part[i].loc_chain; node; node = node->next)
2347           for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
2348             if (rtx_equal_p (node->loc, node2->loc))
2349               {
2350                 if (node->init > node2->init)
2351                   node2->init = node->init;
2352               }
2353       }
2354
2355   /* Continue traversing the hash table.  */
2356   return 1;
2357 }
2358
2359 /* Compute union of dataflow sets SRC and DST and store it to DST.  */
2360
2361 static void
2362 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
2363 {
2364   int i;
2365
2366   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2367     attrs_list_union (&dst->regs[i], src->regs[i]);
2368
2369   if (dst->vars == empty_shared_hash)
2370     {
2371       shared_hash_destroy (dst->vars);
2372       dst->vars = shared_hash_copy (src->vars);
2373     }
2374   else
2375     htab_traverse (shared_hash_htab (src->vars), variable_union, dst);
2376 }
2377
2378 /* Whether the value is currently being expanded.  */
2379 #define VALUE_RECURSED_INTO(x) \
2380   (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
2381 /* Whether the value is in changed_variables hash table.  */
2382 #define VALUE_CHANGED(x) \
2383   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
2384 /* Whether the decl is in changed_variables hash table.  */
2385 #define DECL_CHANGED(x) TREE_VISITED (x)
2386
2387 /* Record that DV has been added into resp. removed from changed_variables
2388    hashtable.  */
2389
2390 static inline void
2391 set_dv_changed (decl_or_value dv, bool newv)
2392 {
2393   if (dv_is_value_p (dv))
2394     VALUE_CHANGED (dv_as_value (dv)) = newv;
2395   else
2396     DECL_CHANGED (dv_as_decl (dv)) = newv;
2397 }
2398
2399 /* Return true if DV is present in changed_variables hash table.  */
2400
2401 static inline bool
2402 dv_changed_p (decl_or_value dv)
2403 {
2404   return (dv_is_value_p (dv)
2405           ? VALUE_CHANGED (dv_as_value (dv))
2406           : DECL_CHANGED (dv_as_decl (dv)));
2407 }
2408
2409 /* Return a location list node whose loc is rtx_equal to LOC, in the
2410    location list of a one-part variable or value VAR, or in that of
2411    any values recursively mentioned in the location lists.  */
2412
2413 static location_chain
2414 find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
2415 {
2416   location_chain node;
2417
2418   if (!var)
2419     return NULL;
2420
2421   gcc_assert (dv_onepart_p (var->dv));
2422
2423   if (!var->n_var_parts)
2424     return NULL;
2425
2426   gcc_assert (var->var_part[0].offset == 0);
2427
2428   for (node = var->var_part[0].loc_chain; node; node = node->next)
2429     if (rtx_equal_p (loc, node->loc))
2430       return node;
2431     else if (GET_CODE (node->loc) == VALUE
2432              && !VALUE_RECURSED_INTO (node->loc))
2433       {
2434         decl_or_value dv = dv_from_value (node->loc);
2435         variable var = (variable)
2436                        htab_find_with_hash (vars, dv, dv_htab_hash (dv));
2437
2438         if (var)
2439           {
2440             location_chain where;
2441             VALUE_RECURSED_INTO (node->loc) = true;
2442             if ((where = find_loc_in_1pdv (loc, var, vars)))
2443               {
2444                 VALUE_RECURSED_INTO (node->loc) = false;
2445                 return where;
2446               }
2447             VALUE_RECURSED_INTO (node->loc) = false;
2448           }
2449       }
2450
2451   return NULL;
2452 }
2453
2454 /* Hash table iteration argument passed to variable_merge.  */
2455 struct dfset_merge
2456 {
2457   /* The set in which the merge is to be inserted.  */
2458   dataflow_set *dst;
2459   /* The set that we're iterating in.  */
2460   dataflow_set *cur;
2461   /* The set that may contain the other dv we are to merge with.  */
2462   dataflow_set *src;
2463   /* Number of onepart dvs in src.  */
2464   int src_onepart_cnt;
2465 };
2466
2467 /* Insert LOC in *DNODE, if it's not there yet.  The list must be in
2468    loc_cmp order, and it is maintained as such.  */
2469
2470 static void
2471 insert_into_intersection (location_chain *nodep, rtx loc,
2472                           enum var_init_status status)
2473 {
2474   location_chain node;
2475   int r;
2476
2477   for (node = *nodep; node; nodep = &node->next, node = *nodep)
2478     if ((r = loc_cmp (node->loc, loc)) == 0)
2479       {
2480         node->init = MIN (node->init, status);
2481         return;
2482       }
2483     else if (r > 0)
2484       break;
2485
2486   node = (location_chain) pool_alloc (loc_chain_pool);
2487
2488   node->loc = loc;
2489   node->set_src = NULL;
2490   node->init = status;
2491   node->next = *nodep;
2492   *nodep = node;
2493 }
2494
2495 /* Insert in DEST the intersection the locations present in both
2496    S1NODE and S2VAR, directly or indirectly.  S1NODE is from a
2497    variable in DSM->cur, whereas S2VAR is from DSM->src.  dvar is in
2498    DSM->dst.  */
2499
2500 static void
2501 intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
2502                       location_chain s1node, variable s2var)
2503 {
2504   dataflow_set *s1set = dsm->cur;
2505   dataflow_set *s2set = dsm->src;
2506   location_chain found;
2507
2508   for (; s1node; s1node = s1node->next)
2509     {
2510       if (s1node->loc == val)
2511         continue;
2512
2513       if ((found = find_loc_in_1pdv (s1node->loc, s2var,
2514                                      shared_hash_htab (s2set->vars))))
2515         {
2516           insert_into_intersection (dest, s1node->loc,
2517                                     MIN (s1node->init, found->init));
2518           continue;
2519         }
2520
2521       if (GET_CODE (s1node->loc) == VALUE
2522           && !VALUE_RECURSED_INTO (s1node->loc))
2523         {
2524           decl_or_value dv = dv_from_value (s1node->loc);
2525           variable svar = shared_hash_find (s1set->vars, dv);
2526           if (svar)
2527             {
2528               if (svar->n_var_parts == 1)
2529                 {
2530                   VALUE_RECURSED_INTO (s1node->loc) = true;
2531                   intersect_loc_chains (val, dest, dsm,
2532                                         svar->var_part[0].loc_chain,
2533                                         s2var);
2534                   VALUE_RECURSED_INTO (s1node->loc) = false;
2535                 }
2536             }
2537         }
2538
2539       /* ??? if the location is equivalent to any location in src,
2540          searched recursively
2541
2542            add to dst the values needed to represent the equivalence
2543
2544      telling whether locations S is equivalent to another dv's
2545      location list:
2546
2547        for each location D in the list
2548
2549          if S and D satisfy rtx_equal_p, then it is present
2550
2551          else if D is a value, recurse without cycles
2552
2553          else if S and D have the same CODE and MODE
2554
2555            for each operand oS and the corresponding oD
2556
2557              if oS and oD are not equivalent, then S an D are not equivalent
2558
2559              else if they are RTX vectors
2560
2561                if any vector oS element is not equivalent to its respective oD,
2562                then S and D are not equivalent
2563
2564    */
2565
2566
2567     }
2568 }
2569
2570 /* Return -1 if X should be before Y in a location list for a 1-part
2571    variable, 1 if Y should be before X, and 0 if they're equivalent
2572    and should not appear in the list.  */
2573
2574 static int
2575 loc_cmp (rtx x, rtx y)
2576 {
2577   int i, j, r;
2578   RTX_CODE code = GET_CODE (x);
2579   const char *fmt;
2580
2581   if (x == y)
2582     return 0;
2583
2584   if (REG_P (x))
2585     {
2586       if (!REG_P (y))
2587         return -1;
2588       gcc_assert (GET_MODE (x) == GET_MODE (y));
2589       if (REGNO (x) == REGNO (y))
2590         return 0;
2591       else if (REGNO (x) < REGNO (y))
2592         return -1;
2593       else
2594         return 1;
2595     }
2596
2597   if (REG_P (y))
2598     return 1;
2599
2600   if (MEM_P (x))
2601     {
2602       if (!MEM_P (y))
2603         return -1;
2604       gcc_assert (GET_MODE (x) == GET_MODE (y));
2605       return loc_cmp (XEXP (x, 0), XEXP (y, 0));
2606     }
2607
2608   if (MEM_P (y))
2609     return 1;
2610
2611   if (GET_CODE (x) == VALUE)
2612     {
2613       if (GET_CODE (y) != VALUE)
2614         return -1;
2615       /* Don't assert the modes are the same, that is true only
2616          when not recursing.  (subreg:QI (value:SI 1:1) 0)
2617          and (subreg:QI (value:DI 2:2) 0) can be compared,
2618          even when the modes are different.  */
2619       if (canon_value_cmp (x, y))
2620         return -1;
2621       else
2622         return 1;
2623     }
2624
2625   if (GET_CODE (y) == VALUE)
2626     return 1;
2627
2628   if (GET_CODE (x) == GET_CODE (y))
2629     /* Compare operands below.  */;
2630   else if (GET_CODE (x) < GET_CODE (y))
2631     return -1;
2632   else
2633     return 1;
2634
2635   gcc_assert (GET_MODE (x) == GET_MODE (y));
2636
2637   if (GET_CODE (x) == DEBUG_EXPR)
2638     {
2639       if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
2640           < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)))
2641         return -1;
2642 #ifdef ENABLE_CHECKING
2643       gcc_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
2644                   > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)));
2645 #endif
2646       return 1;
2647     }
2648
2649   fmt = GET_RTX_FORMAT (code);
2650   for (i = 0; i < GET_RTX_LENGTH (code); i++)
2651     switch (fmt[i])
2652       {
2653       case 'w':
2654         if (XWINT (x, i) == XWINT (y, i))
2655           break;
2656         else if (XWINT (x, i) < XWINT (y, i))
2657           return -1;
2658         else
2659           return 1;
2660
2661       case 'n':
2662       case 'i':
2663         if (XINT (x, i) == XINT (y, i))
2664           break;
2665         else if (XINT (x, i) < XINT (y, i))
2666           return -1;
2667         else
2668           return 1;
2669
2670       case 'V':
2671       case 'E':
2672         /* Compare the vector length first.  */
2673         if (XVECLEN (x, i) == XVECLEN (y, i))
2674           /* Compare the vectors elements.  */;
2675         else if (XVECLEN (x, i) < XVECLEN (y, i))
2676           return -1;
2677         else
2678           return 1;
2679
2680         for (j = 0; j < XVECLEN (x, i); j++)
2681           if ((r = loc_cmp (XVECEXP (x, i, j),
2682                             XVECEXP (y, i, j))))
2683             return r;
2684         break;
2685
2686       case 'e':
2687         if ((r = loc_cmp (XEXP (x, i), XEXP (y, i))))
2688           return r;
2689         break;
2690
2691       case 'S':
2692       case 's':
2693         if (XSTR (x, i) == XSTR (y, i))
2694           break;
2695         if (!XSTR (x, i))
2696           return -1;
2697         if (!XSTR (y, i))
2698           return 1;
2699         if ((r = strcmp (XSTR (x, i), XSTR (y, i))) == 0)
2700           break;
2701         else if (r < 0)
2702           return -1;
2703         else
2704           return 1;
2705
2706       case 'u':
2707         /* These are just backpointers, so they don't matter.  */
2708         break;
2709
2710       case '0':
2711       case 't':
2712         break;
2713
2714         /* It is believed that rtx's at this level will never
2715            contain anything but integers and other rtx's,
2716            except for within LABEL_REFs and SYMBOL_REFs.  */
2717       default:
2718         gcc_unreachable ();
2719       }
2720
2721   return 0;
2722 }
2723
2724 /* If decl or value DVP refers to VALUE from *LOC, add backlinks
2725    from VALUE to DVP.  */
2726
2727 static int
2728 add_value_chain (rtx *loc, void *dvp)
2729 {
2730   decl_or_value dv, ldv;
2731   value_chain vc, nvc;
2732   void **slot;
2733
2734   if (GET_CODE (*loc) == VALUE)
2735     ldv = dv_from_value (*loc);
2736   else if (GET_CODE (*loc) == DEBUG_EXPR)
2737     ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
2738   else
2739     return 0;
2740
2741   if (dv_as_opaque (ldv) == dvp)
2742     return 0;
2743
2744   dv = (decl_or_value) dvp;
2745   slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
2746                                    INSERT);
2747   if (!*slot)
2748     {
2749       vc = (value_chain) pool_alloc (value_chain_pool);
2750       vc->dv = ldv;
2751       vc->next = NULL;
2752       vc->refcount = 0;
2753       *slot = (void *) vc;
2754     }
2755   else
2756     {
2757       for (vc = ((value_chain) *slot)->next; vc; vc = vc->next)
2758         if (dv_as_opaque (vc->dv) == dv_as_opaque (dv))
2759           break;
2760       if (vc)
2761         {
2762           vc->refcount++;
2763           return 0;
2764         }
2765     }
2766   vc = (value_chain) *slot;
2767   nvc = (value_chain) pool_alloc (value_chain_pool);
2768   nvc->dv = dv;
2769   nvc->next = vc->next;
2770   nvc->refcount = 1;
2771   vc->next = nvc;
2772   return 0;
2773 }
2774
2775 /* If decl or value DVP refers to VALUEs from within LOC, add backlinks
2776    from those VALUEs to DVP.  */
2777
2778 static void
2779 add_value_chains (decl_or_value dv, rtx loc)
2780 {
2781   if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
2782     {
2783       add_value_chain (&loc, dv_as_opaque (dv));
2784       return;
2785     }
2786   if (REG_P (loc))
2787     return;
2788   if (MEM_P (loc))
2789     loc = XEXP (loc, 0);
2790   for_each_rtx (&loc, add_value_chain, dv_as_opaque (dv));
2791 }
2792
2793 /* If CSELIB_VAL_PTR of value DV refer to VALUEs, add backlinks from those
2794    VALUEs to DV.  */
2795
2796 static void
2797 add_cselib_value_chains (decl_or_value dv)
2798 {
2799   struct elt_loc_list *l;
2800
2801   for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
2802     for_each_rtx (&l->loc, add_value_chain, dv_as_opaque (dv));
2803 }
2804
2805 /* If decl or value DVP refers to VALUE from *LOC, remove backlinks
2806    from VALUE to DVP.  */
2807
2808 static int
2809 remove_value_chain (rtx *loc, void *dvp)
2810 {
2811   decl_or_value dv, ldv;
2812   value_chain vc;
2813   void **slot;
2814
2815   if (GET_CODE (*loc) == VALUE)
2816     ldv = dv_from_value (*loc);
2817   else if (GET_CODE (*loc) == DEBUG_EXPR)
2818     ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
2819   else
2820     return 0;
2821
2822   if (dv_as_opaque (ldv) == dvp)
2823     return 0;
2824
2825   dv = (decl_or_value) dvp;
2826   slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
2827                                    NO_INSERT);
2828   for (vc = (value_chain) *slot; vc->next; vc = vc->next)
2829     if (dv_as_opaque (vc->next->dv) == dv_as_opaque (dv))
2830       {
2831         value_chain dvc = vc->next;
2832         gcc_assert (dvc->refcount > 0);
2833         if (--dvc->refcount == 0)
2834           {
2835             vc->next = dvc->next;
2836             pool_free (value_chain_pool, dvc);
2837             if (vc->next == NULL && vc == (value_chain) *slot)
2838               {
2839                 pool_free (value_chain_pool, vc);
2840                 htab_clear_slot (value_chains, slot);
2841               }
2842           }
2843         return 0;
2844       }
2845   gcc_unreachable ();
2846 }
2847
2848 /* If decl or value DVP refers to VALUEs from within LOC, remove backlinks
2849    from those VALUEs to DVP.  */
2850
2851 static void
2852 remove_value_chains (decl_or_value dv, rtx loc)
2853 {
2854   if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
2855     {
2856       remove_value_chain (&loc, dv_as_opaque (dv));
2857       return;
2858     }
2859   if (REG_P (loc))
2860     return;
2861   if (MEM_P (loc))
2862     loc = XEXP (loc, 0);
2863   for_each_rtx (&loc, remove_value_chain, dv_as_opaque (dv));
2864 }
2865
2866 #if ENABLE_CHECKING
2867 /* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those
2868    VALUEs to DV.  */
2869
2870 static void
2871 remove_cselib_value_chains (decl_or_value dv)
2872 {
2873   struct elt_loc_list *l;
2874
2875   for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
2876     for_each_rtx (&l->loc, remove_value_chain, dv_as_opaque (dv));
2877 }
2878
2879 /* Check the order of entries in one-part variables.   */
2880
2881 static int
2882 canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
2883 {
2884   variable var = (variable) *slot;
2885   decl_or_value dv = var->dv;
2886   location_chain node, next;
2887
2888 #ifdef ENABLE_RTL_CHECKING
2889   int i;
2890   for (i = 0; i < var->n_var_parts; i++)
2891     gcc_assert (var->var_part[0].cur_loc == NULL);
2892   gcc_assert (!var->cur_loc_changed && !var->in_changed_variables);
2893 #endif
2894
2895   if (!dv_onepart_p (dv))
2896     return 1;
2897
2898   gcc_assert (var->n_var_parts == 1);
2899   node = var->var_part[0].loc_chain;
2900   gcc_assert (node);
2901
2902   while ((next = node->next))
2903     {
2904       gcc_assert (loc_cmp (node->loc, next->loc) < 0);
2905       node = next;
2906     }
2907
2908   return 1;
2909 }
2910 #endif
2911
2912 /* Mark with VALUE_RECURSED_INTO values that have neighbors that are
2913    more likely to be chosen as canonical for an equivalence set.
2914    Ensure less likely values can reach more likely neighbors, making
2915    the connections bidirectional.  */
2916
2917 static int
2918 canonicalize_values_mark (void **slot, void *data)
2919 {
2920   dataflow_set *set = (dataflow_set *)data;
2921   variable var = (variable) *slot;
2922   decl_or_value dv = var->dv;
2923   rtx val;
2924   location_chain node;
2925
2926   if (!dv_is_value_p (dv))
2927     return 1;
2928
2929   gcc_assert (var->n_var_parts == 1);
2930
2931   val = dv_as_value (dv);
2932
2933   for (node = var->var_part[0].loc_chain; node; node = node->next)
2934     if (GET_CODE (node->loc) == VALUE)
2935       {
2936         if (canon_value_cmp (node->loc, val))
2937           VALUE_RECURSED_INTO (val) = true;
2938         else
2939           {
2940             decl_or_value odv = dv_from_value (node->loc);
2941             void **oslot = shared_hash_find_slot_noinsert (set->vars, odv);
2942
2943             oslot = set_slot_part (set, val, oslot, odv, 0,
2944                                    node->init, NULL_RTX);
2945
2946             VALUE_RECURSED_INTO (node->loc) = true;
2947           }
2948       }
2949
2950   return 1;
2951 }
2952
2953 /* Remove redundant entries from equivalence lists in onepart
2954    variables, canonicalizing equivalence sets into star shapes.  */
2955
2956 static int
2957 canonicalize_values_star (void **slot, void *data)
2958 {
2959   dataflow_set *set = (dataflow_set *)data;
2960   variable var = (variable) *slot;
2961   decl_or_value dv = var->dv;
2962   location_chain node;
2963   decl_or_value cdv;
2964   rtx val, cval;
2965   void **cslot;
2966   bool has_value;
2967   bool has_marks;
2968
2969   if (!dv_onepart_p (dv))
2970     return 1;
2971
2972   gcc_assert (var->n_var_parts == 1);
2973
2974   if (dv_is_value_p (dv))
2975     {
2976       cval = dv_as_value (dv);
2977       if (!VALUE_RECURSED_INTO (cval))
2978         return 1;
2979       VALUE_RECURSED_INTO (cval) = false;
2980     }
2981   else
2982     cval = NULL_RTX;
2983
2984  restart:
2985   val = cval;
2986   has_value = false;
2987   has_marks = false;
2988
2989   gcc_assert (var->n_var_parts == 1);
2990
2991   for (node = var->var_part[0].loc_chain; node; node = node->next)
2992     if (GET_CODE (node->loc) == VALUE)
2993       {
2994         has_value = true;
2995         if (VALUE_RECURSED_INTO (node->loc))
2996           has_marks = true;
2997         if (canon_value_cmp (node->loc, cval))
2998           cval = node->loc;
2999       }
3000
3001   if (!has_value)
3002     return 1;
3003
3004   if (cval == val)
3005     {
3006       if (!has_marks || dv_is_decl_p (dv))
3007         return 1;
3008
3009       /* Keep it marked so that we revisit it, either after visiting a
3010          child node, or after visiting a new parent that might be
3011          found out.  */
3012       VALUE_RECURSED_INTO (val) = true;
3013
3014       for (node = var->var_part[0].loc_chain; node; node = node->next)
3015         if (GET_CODE (node->loc) == VALUE
3016             && VALUE_RECURSED_INTO (node->loc))
3017           {
3018             cval = node->loc;
3019           restart_with_cval:
3020             VALUE_RECURSED_INTO (cval) = false;
3021             dv = dv_from_value (cval);
3022             slot = shared_hash_find_slot_noinsert (set->vars, dv);
3023             if (!slot)
3024               {
3025                 gcc_assert (dv_is_decl_p (var->dv));
3026                 /* The canonical value was reset and dropped.
3027                    Remove it.  */
3028                 clobber_variable_part (set, NULL, var->dv, 0, NULL);
3029                 return 1;
3030               }
3031             var = (variable)*slot;
3032             gcc_assert (dv_is_value_p (var->dv));
3033             if (var->n_var_parts == 0)
3034               return 1;
3035             gcc_assert (var->n_var_parts == 1);
3036             goto restart;
3037           }
3038
3039       VALUE_RECURSED_INTO (val) = false;
3040
3041       return 1;
3042     }
3043
3044   /* Push values to the canonical one.  */
3045   cdv = dv_from_value (cval);
3046   cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3047
3048   for (node = var->var_part[0].loc_chain; node; node = node->next)
3049     if (node->loc != cval)
3050       {
3051         cslot = set_slot_part (set, node->loc, cslot, cdv, 0,
3052                                node->init, NULL_RTX);
3053         if (GET_CODE (node->loc) == VALUE)
3054           {
3055             decl_or_value ndv = dv_from_value (node->loc);
3056
3057             set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX,
3058                                NO_INSERT);
3059
3060             if (canon_value_cmp (node->loc, val))
3061               {
3062                 /* If it could have been a local minimum, it's not any more,
3063                    since it's now neighbor to cval, so it may have to push
3064                    to it.  Conversely, if it wouldn't have prevailed over
3065                    val, then whatever mark it has is fine: if it was to
3066                    push, it will now push to a more canonical node, but if
3067                    it wasn't, then it has already pushed any values it might
3068                    have to.  */
3069                 VALUE_RECURSED_INTO (node->loc) = true;
3070                 /* Make sure we visit node->loc by ensuring we cval is
3071                    visited too.  */
3072                 VALUE_RECURSED_INTO (cval) = true;
3073               }
3074             else if (!VALUE_RECURSED_INTO (node->loc))
3075               /* If we have no need to "recurse" into this node, it's
3076                  already "canonicalized", so drop the link to the old
3077                  parent.  */
3078               clobber_variable_part (set, cval, ndv, 0, NULL);
3079           }
3080         else if (GET_CODE (node->loc) == REG)
3081           {
3082             attrs list = set->regs[REGNO (node->loc)], *listp;
3083
3084             /* Change an existing attribute referring to dv so that it
3085                refers to cdv, removing any duplicate this might
3086                introduce, and checking that no previous duplicates
3087                existed, all in a single pass.  */
3088
3089             while (list)
3090               {
3091                 if (list->offset == 0
3092                     && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3093                         || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3094                   break;
3095
3096                 list = list->next;
3097               }
3098
3099             gcc_assert (list);
3100             if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3101               {
3102                 list->dv = cdv;
3103                 for (listp = &list->next; (list = *listp); listp = &list->next)
3104                   {
3105                     if (list->offset)
3106                       continue;
3107
3108                     if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3109                       {
3110                         *listp = list->next;
3111                         pool_free (attrs_pool, list);
3112                         list = *listp;
3113                         break;
3114                       }
3115
3116                     gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv));
3117                   }
3118               }
3119             else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3120               {
3121                 for (listp = &list->next; (list = *listp); listp = &list->next)
3122                   {
3123                     if (list->offset)
3124                       continue;
3125
3126                     if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3127                       {
3128                         *listp = list->next;
3129                         pool_free (attrs_pool, list);
3130                         list = *listp;
3131                         break;
3132                       }
3133
3134                     gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv));
3135                   }
3136               }
3137             else
3138               gcc_unreachable ();
3139
3140 #if ENABLE_CHECKING
3141             while (list)
3142               {
3143                 if (list->offset == 0
3144                     && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3145                         || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3146                   gcc_unreachable ();
3147
3148                 list = list->next;
3149               }
3150 #endif
3151           }
3152       }
3153
3154   if (val)
3155     cslot = set_slot_part (set, val, cslot, cdv, 0,
3156                            VAR_INIT_STATUS_INITIALIZED, NULL_RTX);
3157
3158   slot = clobber_slot_part (set, cval, slot, 0, NULL);
3159
3160   /* Variable may have been unshared.  */
3161   var = (variable)*slot;
3162   gcc_assert (var->n_var_parts && var->var_part[0].loc_chain->loc == cval
3163               && var->var_part[0].loc_chain->next == NULL);
3164
3165   if (VALUE_RECURSED_INTO (cval))
3166     goto restart_with_cval;
3167
3168   return 1;
3169 }
3170
3171 /* Combine variable or value in *S1SLOT (in DSM->cur) with the
3172    corresponding entry in DSM->src.  Multi-part variables are combined
3173    with variable_union, whereas onepart dvs are combined with
3174    intersection.  */
3175
3176 static int
3177 variable_merge_over_cur (void **s1slot, void *data)
3178 {
3179   struct dfset_merge *dsm = (struct dfset_merge *)data;
3180   dataflow_set *dst = dsm->dst;
3181   void **dstslot;
3182   variable s1var = (variable) *s1slot;
3183   variable s2var, dvar = NULL;
3184   decl_or_value dv = s1var->dv;
3185   bool onepart = dv_onepart_p (dv);
3186   rtx val;
3187   hashval_t dvhash;
3188   location_chain node, *nodep;
3189
3190   /* If the incoming onepart variable has an empty location list, then
3191      the intersection will be just as empty.  For other variables,
3192      it's always union.  */
3193   gcc_assert (s1var->n_var_parts);
3194   gcc_assert (s1var->var_part[0].loc_chain);
3195
3196   if (!onepart)
3197     return variable_union (s1slot, dst);
3198
3199   gcc_assert (s1var->n_var_parts == 1);
3200   gcc_assert (s1var->var_part[0].offset == 0);
3201
3202   dvhash = dv_htab_hash (dv);
3203   if (dv_is_value_p (dv))
3204     val = dv_as_value (dv);
3205   else
3206     val = NULL;
3207
3208   s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash);
3209   if (!s2var)
3210     {
3211       dst_can_be_shared = false;
3212       return 1;
3213     }
3214
3215   dsm->src_onepart_cnt--;
3216   gcc_assert (s2var->var_part[0].loc_chain);
3217   gcc_assert (s2var->n_var_parts == 1);
3218   gcc_assert (s2var->var_part[0].offset == 0);
3219
3220   dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3221   if (dstslot)
3222     {
3223       dvar = (variable)*dstslot;
3224       gcc_assert (dvar->refcount == 1);
3225       gcc_assert (dvar->n_var_parts == 1);
3226       gcc_assert (dvar->var_part[0].offset == 0);
3227       nodep = &dvar->var_part[0].loc_chain;
3228     }
3229   else
3230     {
3231       nodep = &node;
3232       node = NULL;
3233     }
3234
3235   if (!dstslot && !onepart_variable_different_p (s1var, s2var))
3236     {
3237       dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv,
3238                                                  dvhash, INSERT);
3239       *dstslot = dvar = s2var;
3240       dvar->refcount++;
3241     }
3242   else
3243     {
3244       dst_can_be_shared = false;
3245
3246       intersect_loc_chains (val, nodep, dsm,
3247                             s1var->var_part[0].loc_chain, s2var);
3248
3249       if (!dstslot)
3250         {
3251           if (node)
3252             {
3253               dvar = (variable) pool_alloc (dv_pool (dv));
3254               dvar->dv = dv;
3255               dvar->refcount = 1;
3256               dvar->n_var_parts = 1;
3257               dvar->cur_loc_changed = false;
3258               dvar->in_changed_variables = false;
3259               dvar->var_part[0].offset = 0;
3260               dvar->var_part[0].loc_chain = node;
3261               dvar->var_part[0].cur_loc = NULL;
3262
3263               dstslot
3264                 = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
3265                                                    INSERT);
3266               gcc_assert (!*dstslot);
3267               *dstslot = dvar;
3268             }
3269           else
3270             return 1;
3271         }
3272     }
3273
3274   nodep = &dvar->var_part[0].loc_chain;
3275   while ((node = *nodep))
3276     {
3277       location_chain *nextp = &node->next;
3278
3279       if (GET_CODE (node->loc) == REG)
3280         {
3281           attrs list;
3282
3283           for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
3284             if (GET_MODE (node->loc) == GET_MODE (list->loc)
3285                 && dv_is_value_p (list->dv))
3286               break;
3287
3288           if (!list)
3289             attrs_list_insert (&dst->regs[REGNO (node->loc)],
3290                                dv, 0, node->loc);
3291           /* If this value became canonical for another value that had
3292              this register, we want to leave it alone.  */
3293           else if (dv_as_value (list->dv) != val)
3294             {
3295               dstslot = set_slot_part (dst, dv_as_value (list->dv),
3296                                        dstslot, dv, 0,
3297                                        node->init, NULL_RTX);
3298               dstslot = delete_slot_part (dst, node->loc, dstslot, 0);
3299
3300               /* Since nextp points into the removed node, we can't
3301                  use it.  The pointer to the next node moved to nodep.
3302                  However, if the variable we're walking is unshared
3303                  during our walk, we'll keep walking the location list
3304                  of the previously-shared variable, in which case the
3305                  node won't have been removed, and we'll want to skip
3306                  it.  That's why we test *nodep here.  */
3307               if (*nodep != node)
3308                 nextp = nodep;
3309             }
3310         }
3311       else
3312         /* Canonicalization puts registers first, so we don't have to
3313            walk it all.  */
3314         break;
3315       nodep = nextp;
3316     }
3317
3318   if (dvar != (variable)*dstslot)
3319     dvar = (variable)*dstslot;
3320   nodep = &dvar->var_part[0].loc_chain;
3321
3322   if (val)
3323     {
3324       /* Mark all referenced nodes for canonicalization, and make sure
3325          we have mutual equivalence links.  */
3326       VALUE_RECURSED_INTO (val) = true;
3327       for (node = *nodep; node; node = node->next)
3328         if (GET_CODE (node->loc) == VALUE)
3329           {
3330             VALUE_RECURSED_INTO (node->loc) = true;
3331             set_variable_part (dst, val, dv_from_value (node->loc), 0,
3332                                node->init, NULL, INSERT);
3333           }
3334
3335       dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3336       gcc_assert (*dstslot == dvar);
3337       canonicalize_values_star (dstslot, dst);
3338 #ifdef ENABLE_CHECKING
3339       gcc_assert (dstslot
3340                   == shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash));
3341 #endif
3342       dvar = (variable)*dstslot;
3343     }
3344   else
3345     {
3346       bool has_value = false, has_other = false;
3347
3348       /* If we have one value and anything else, we're going to
3349          canonicalize this, so make sure all values have an entry in
3350          the table and are marked for canonicalization.  */
3351       for (node = *nodep; node; node = node->next)
3352         {
3353           if (GET_CODE (node->loc) == VALUE)
3354             {
3355               /* If this was marked during register canonicalization,
3356                  we know we have to canonicalize values.  */
3357               if (has_value)
3358                 has_other = true;
3359               has_value = true;
3360               if (has_other)
3361                 break;
3362             }
3363           else
3364             {
3365               has_other = true;
3366               if (has_value)
3367                 break;
3368             }
3369         }
3370
3371       if (has_value && has_other)
3372         {
3373           for (node = *nodep; node; node = node->next)
3374             {
3375               if (GET_CODE (node->loc) == VALUE)
3376                 {
3377                   decl_or_value dv = dv_from_value (node->loc);
3378                   void **slot = NULL;
3379
3380                   if (shared_hash_shared (dst->vars))
3381                     slot = shared_hash_find_slot_noinsert (dst->vars, dv);
3382                   if (!slot)
3383                     slot = shared_hash_find_slot_unshare (&dst->vars, dv,
3384                                                           INSERT);
3385                   if (!*slot)
3386                     {
3387                       variable var = (variable) pool_alloc (dv_pool (dv));
3388                       var->dv = dv;
3389                       var->refcount = 1;
3390                       var->n_var_parts = 1;
3391                       var->cur_loc_changed = false;
3392                       var->in_changed_variables = false;
3393                       var->var_part[0].offset = 0;
3394                       var->var_part[0].loc_chain = NULL;
3395                       var->var_part[0].cur_loc = NULL;
3396                       *slot = var;
3397                     }
3398
3399                   VALUE_RECURSED_INTO (node->loc) = true;
3400                 }
3401             }
3402
3403           dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3404           gcc_assert (*dstslot == dvar);
3405           canonicalize_values_star (dstslot, dst);
3406 #ifdef ENABLE_CHECKING
3407           gcc_assert (dstslot
3408                       == shared_hash_find_slot_noinsert_1 (dst->vars,
3409                                                            dv, dvhash));
3410 #endif
3411           dvar = (variable)*dstslot;
3412         }
3413     }
3414
3415   if (!onepart_variable_different_p (dvar, s2var))
3416     {
3417       variable_htab_free (dvar);
3418       *dstslot = dvar = s2var;
3419       dvar->refcount++;
3420     }
3421   else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var))
3422     {
3423       variable_htab_free (dvar);
3424       *dstslot = dvar = s1var;
3425       dvar->refcount++;
3426       dst_can_be_shared = false;
3427     }
3428   else
3429     dst_can_be_shared = false;
3430
3431   return 1;
3432 }
3433
3434 /* Copy s2slot (in DSM->src) to DSM->dst if the variable is a
3435    multi-part variable.  Unions of multi-part variables and
3436    intersections of one-part ones will be handled in
3437    variable_merge_over_cur().  */
3438
3439 static int
3440 variable_merge_over_src (void **s2slot, void *data)
3441 {
3442   struct dfset_merge *dsm = (struct dfset_merge *)data;
3443   dataflow_set *dst = dsm->dst;
3444   variable s2var = (variable) *s2slot;
3445   decl_or_value dv = s2var->dv;
3446   bool onepart = dv_onepart_p (dv);
3447
3448   if (!onepart)
3449     {
3450       void **dstp = shared_hash_find_slot (dst->vars, dv);
3451       *dstp = s2var;
3452       s2var->refcount++;
3453       return 1;
3454     }
3455
3456   dsm->src_onepart_cnt++;
3457   return 1;
3458 }
3459
3460 /* Combine dataflow set information from SRC2 into DST, using PDST
3461    to carry over information across passes.  */
3462
3463 static void
3464 dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
3465 {
3466   dataflow_set cur = *dst;
3467   dataflow_set *src1 = &cur;
3468   struct dfset_merge dsm;
3469   int i;
3470   size_t src1_elems, src2_elems;
3471
3472   src1_elems = htab_elements (shared_hash_htab (src1->vars));
3473   src2_elems = htab_elements (shared_hash_htab (src2->vars));
3474   dataflow_set_init (dst);
3475   dst->stack_adjust = cur.stack_adjust;
3476   shared_hash_destroy (dst->vars);
3477   dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
3478   dst->vars->refcount = 1;
3479   dst->vars->htab
3480     = htab_create (MAX (src1_elems, src2_elems), variable_htab_hash,
3481                    variable_htab_eq, variable_htab_free);
3482
3483   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3484     attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
3485
3486   dsm.dst = dst;
3487   dsm.src = src2;
3488   dsm.cur = src1;
3489   dsm.src_onepart_cnt = 0;
3490
3491   htab_traverse (shared_hash_htab (dsm.src->vars), variable_merge_over_src,
3492                  &dsm);
3493   htab_traverse (shared_hash_htab (dsm.cur->vars), variable_merge_over_cur,
3494                  &dsm);
3495
3496   if (dsm.src_onepart_cnt)
3497     dst_can_be_shared = false;
3498
3499   dataflow_set_destroy (src1);
3500 }
3501
3502 /* Mark register equivalences.  */
3503
3504 static void
3505 dataflow_set_equiv_regs (dataflow_set *set)
3506 {
3507   int i;
3508   attrs list, *listp;
3509
3510   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3511     {
3512       rtx canon[NUM_MACHINE_MODES];
3513
3514       memset (canon, 0, sizeof (canon));
3515
3516       for (list = set->regs[i]; list; list = list->next)
3517         if (list->offset == 0 && dv_is_value_p (list->dv))
3518           {
3519             rtx val = dv_as_value (list->dv);
3520             rtx *cvalp = &canon[(int)GET_MODE (val)];
3521             rtx cval = *cvalp;
3522
3523             if (canon_value_cmp (val, cval))
3524               *cvalp = val;
3525           }
3526
3527       for (list = set->regs[i]; list; list = list->next)
3528         if (list->offset == 0 && dv_onepart_p (list->dv))
3529           {
3530             rtx cval = canon[(int)GET_MODE (list->loc)];
3531
3532             if (!cval)
3533               continue;
3534
3535             if (dv_is_value_p (list->dv))
3536               {
3537                 rtx val = dv_as_value (list->dv);
3538
3539                 if (val == cval)
3540                   continue;
3541
3542                 VALUE_RECURSED_INTO (val) = true;
3543                 set_variable_part (set, val, dv_from_value (cval), 0,
3544                                    VAR_INIT_STATUS_INITIALIZED,
3545                                    NULL, NO_INSERT);
3546               }
3547
3548             VALUE_RECURSED_INTO (cval) = true;
3549             set_variable_part (set, cval, list->dv, 0,
3550                                VAR_INIT_STATUS_INITIALIZED, NULL, NO_INSERT);
3551           }
3552
3553       for (listp = &set->regs[i]; (list = *listp);
3554            listp = list ? &list->next : listp)
3555         if (list->offset == 0 && dv_onepart_p (list->dv))
3556           {
3557             rtx cval = canon[(int)GET_MODE (list->loc)];
3558             void **slot;
3559
3560             if (!cval)
3561               continue;
3562
3563             if (dv_is_value_p (list->dv))
3564               {
3565                 rtx val = dv_as_value (list->dv);
3566                 if (!VALUE_RECURSED_INTO (val))
3567                   continue;
3568               }
3569
3570             slot = shared_hash_find_slot_noinsert (set->vars, list->dv);
3571             canonicalize_values_star (slot, set);
3572             if (*listp != list)
3573               list = NULL;
3574           }
3575     }
3576 }
3577
3578 /* Remove any redundant values in the location list of VAR, which must
3579    be unshared and 1-part.  */
3580
3581 static void
3582 remove_duplicate_values (variable var)
3583 {
3584   location_chain node, *nodep;
3585
3586   gcc_assert (dv_onepart_p (var->dv));
3587   gcc_assert (var->n_var_parts == 1);
3588   gcc_assert (var->refcount == 1);
3589
3590   for (nodep = &var->var_part[0].loc_chain; (node = *nodep); )
3591     {
3592       if (GET_CODE (node->loc) == VALUE)
3593         {
3594           if (VALUE_RECURSED_INTO (node->loc))
3595             {
3596               /* Remove duplicate value node.  */
3597               *nodep = node->next;
3598               pool_free (loc_chain_pool, node);
3599               continue;
3600             }
3601           else
3602             VALUE_RECURSED_INTO (node->loc) = true;
3603         }
3604       nodep = &node->next;
3605     }
3606
3607   for (node = var->var_part[0].loc_chain; node; node = node->next)
3608     if (GET_CODE (node->loc) == VALUE)
3609       {
3610         gcc_assert (VALUE_RECURSED_INTO (node->loc));
3611         VALUE_RECURSED_INTO (node->loc) = false;
3612       }
3613 }
3614
3615
3616 /* Hash table iteration argument passed to variable_post_merge.  */
3617 struct dfset_post_merge
3618 {
3619   /* The new input set for the current block.  */
3620   dataflow_set *set;
3621   /* Pointer to the permanent input set for the current block, or
3622      NULL.  */
3623   dataflow_set **permp;
3624 };
3625
3626 /* Create values for incoming expressions associated with one-part
3627    variables that don't have value numbers for them.  */
3628
3629 static int
3630 variable_post_merge_new_vals (void **slot, void *info)
3631 {
3632   struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
3633   dataflow_set *set = dfpm->set;
3634   variable var = (variable)*slot;
3635   location_chain node;
3636
3637   if (!dv_onepart_p (var->dv) || !var->n_var_parts)
3638     return 1;
3639
3640   gcc_assert (var->n_var_parts == 1);
3641
3642   if (dv_is_decl_p (var->dv))
3643     {
3644       bool check_dupes = false;
3645
3646     restart:
3647       for (node = var->var_part[0].loc_chain; node; node = node->next)
3648         {
3649           if (GET_CODE (node->loc) == VALUE)
3650             gcc_assert (!VALUE_RECURSED_INTO (node->loc));
3651           else if (GET_CODE (node->loc) == REG)
3652             {
3653               attrs att, *attp, *curp = NULL;
3654
3655               if (var->refcount != 1)
3656                 {
3657                   slot = unshare_variable (set, slot, var,
3658                                            VAR_INIT_STATUS_INITIALIZED);
3659                   var = (variable)*slot;
3660                   goto restart;
3661                 }
3662
3663               for (attp = &set->regs[REGNO (node->loc)]; (att = *attp);
3664                    attp = &att->next)
3665                 if (att->offset == 0
3666                     && GET_MODE (att->loc) == GET_MODE (node->loc))
3667                   {
3668                     if (dv_is_value_p (att->dv))
3669                       {
3670                         rtx cval = dv_as_value (att->dv);
3671                         node->loc = cval;
3672                         check_dupes = true;
3673                         break;
3674                       }
3675                     else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv))
3676                       curp = attp;
3677                   }
3678
3679               if (!curp)
3680                 {
3681                   curp = attp;
3682                   while (*curp)
3683                     if ((*curp)->offset == 0
3684                         && GET_MODE ((*curp)->loc) == GET_MODE (node->loc)
3685                         && dv_as_opaque ((*curp)->dv) == dv_as_opaque (var->dv))
3686                       break;
3687                     else
3688                       curp = &(*curp)->next;
3689                   gcc_assert (*curp);
3690                 }
3691
3692               if (!att)
3693                 {
3694                   decl_or_value cdv;
3695                   rtx cval;
3696
3697                   if (!*dfpm->permp)
3698                     {
3699                       *dfpm->permp = XNEW (dataflow_set);
3700                       dataflow_set_init (*dfpm->permp);
3701                     }
3702
3703                   for (att = (*dfpm->permp)->regs[REGNO (node->loc)];
3704                        att; att = att->next)
3705                     if (GET_MODE (att->loc) == GET_MODE (node->loc))
3706                       {
3707                         gcc_assert (att->offset == 0);
3708                         gcc_assert (dv_is_value_p (att->dv));
3709                         val_reset (set, att->dv);
3710                         break;
3711                       }
3712
3713                   if (att)
3714                     {
3715                       cdv = att->dv;
3716                       cval = dv_as_value (cdv);
3717                     }
3718                   else
3719                     {
3720                       /* Create a unique value to hold this register,
3721                          that ought to be found and reused in
3722                          subsequent rounds.  */
3723                       cselib_val *v;
3724                       gcc_assert (!cselib_lookup (node->loc,
3725                                                   GET_MODE (node->loc), 0));
3726                       v = cselib_lookup (node->loc, GET_MODE (node->loc), 1);
3727                       cselib_preserve_value (v);
3728                       cselib_invalidate_rtx (node->loc);
3729                       cval = v->val_rtx;
3730                       cdv = dv_from_value (cval);
3731                       if (dump_file)
3732                         fprintf (dump_file,
3733                                  "Created new value %u:%u for reg %i\n",
3734                                  v->uid, v->hash, REGNO (node->loc));
3735                     }
3736
3737                   var_reg_decl_set (*dfpm->permp, node->loc,
3738                                     VAR_INIT_STATUS_INITIALIZED,
3739                                     cdv, 0, NULL, INSERT);
3740
3741                   node->loc = cval;
3742                   check_dupes = true;
3743                 }
3744
3745               /* Remove attribute referring to the decl, which now
3746                  uses the value for the register, already existing or
3747                  to be added when we bring perm in.  */
3748               att = *curp;
3749               *curp = att->next;
3750               pool_free (attrs_pool, att);
3751             }
3752         }
3753
3754       if (check_dupes)
3755         remove_duplicate_values (var);
3756     }
3757
3758   return 1;
3759 }
3760
3761 /* Reset values in the permanent set that are not associated with the
3762    chosen expression.  */
3763
3764 static int
3765 variable_post_merge_perm_vals (void **pslot, void *info)
3766 {
3767   struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
3768   dataflow_set *set = dfpm->set;
3769   variable pvar = (variable)*pslot, var;
3770   location_chain pnode;
3771   decl_or_value dv;
3772   attrs att;
3773
3774   gcc_assert (dv_is_value_p (pvar->dv));
3775   gcc_assert (pvar->n_var_parts == 1);
3776   pnode = pvar->var_part[0].loc_chain;
3777   gcc_assert (pnode);
3778   gcc_assert (!pnode->next);
3779   gcc_assert (REG_P (pnode->loc));
3780
3781   dv = pvar->dv;
3782
3783   var = shared_hash_find (set->vars, dv);
3784   if (var)
3785     {
3786       if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
3787         return 1;
3788       val_reset (set, dv);
3789     }
3790
3791   for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next)
3792     if (att->offset == 0
3793         && GET_MODE (att->loc) == GET_MODE (pnode->loc)
3794         && dv_is_value_p (att->dv))
3795       break;
3796
3797   /* If there is a value associated with this register already, create
3798      an equivalence.  */
3799   if (att && dv_as_value (att->dv) != dv_as_value (dv))
3800     {
3801       rtx cval = dv_as_value (att->dv);
3802       set_variable_part (set, cval, dv, 0, pnode->init, NULL, INSERT);
3803       set_variable_part (set, dv_as_value (dv), att->dv, 0, pnode->init,
3804                          NULL, INSERT);
3805     }
3806   else if (!att)
3807     {
3808       attrs_list_insert (&set->regs[REGNO (pnode->loc)],
3809                          dv, 0, pnode->loc);
3810       variable_union (pslot, set);
3811     }
3812
3813   return 1;
3814 }
3815
3816 /* Just checking stuff and registering register attributes for
3817    now.  */
3818
3819 static void
3820 dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
3821 {
3822   struct dfset_post_merge dfpm;
3823
3824   dfpm.set = set;
3825   dfpm.permp = permp;
3826
3827   htab_traverse (shared_hash_htab (set->vars), variable_post_merge_new_vals,
3828                  &dfpm);
3829   if (*permp)
3830     htab_traverse (shared_hash_htab ((*permp)->vars),
3831                    variable_post_merge_perm_vals, &dfpm);
3832   htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set);
3833 }
3834
3835 /* Return a node whose loc is a MEM that refers to EXPR in the
3836    location list of a one-part variable or value VAR, or in that of
3837    any values recursively mentioned in the location lists.  */
3838
3839 static location_chain
3840 find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
3841 {
3842   location_chain node;
3843   decl_or_value dv;
3844   variable var;
3845   location_chain where = NULL;
3846
3847   if (!val)
3848     return NULL;
3849
3850   gcc_assert (GET_CODE (val) == VALUE);
3851
3852   gcc_assert (!VALUE_RECURSED_INTO (val));
3853
3854   dv = dv_from_value (val);
3855   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
3856
3857   if (!var)
3858     return NULL;
3859
3860   gcc_assert (dv_onepart_p (var->dv));
3861
3862   if (!var->n_var_parts)
3863     return NULL;
3864
3865   gcc_assert (var->var_part[0].offset == 0);
3866
3867   VALUE_RECURSED_INTO (val) = true;
3868
3869   for (node = var->var_part[0].loc_chain; node; node = node->next)
3870     if (MEM_P (node->loc) && MEM_EXPR (node->loc) == expr
3871         && MEM_OFFSET (node->loc) == 0)
3872       {
3873         where = node;
3874         break;
3875       }
3876     else if (GET_CODE (node->loc) == VALUE
3877              && !VALUE_RECURSED_INTO (node->loc)
3878              && (where = find_mem_expr_in_1pdv (expr, node->loc, vars)))
3879       break;
3880
3881   VALUE_RECURSED_INTO (val) = false;
3882
3883   return where;
3884 }
3885
3886 /* Return TRUE if the value of MEM may vary across a call.  */
3887
3888 static bool
3889 mem_dies_at_call (rtx mem)
3890 {
3891   tree expr = MEM_EXPR (mem);
3892   tree decl;
3893
3894   if (!expr)
3895     return true;
3896
3897   decl = get_base_address (expr);
3898
3899   if (!decl)
3900     return true;
3901
3902   if (!DECL_P (decl))
3903     return true;
3904
3905   return (may_be_aliased (decl)
3906           || (!TREE_READONLY (decl) && is_global_var (decl)));
3907 }
3908
3909 /* Remove all MEMs from the location list of a hash table entry for a
3910    one-part variable, except those whose MEM attributes map back to
3911    the variable itself, directly or within a VALUE.  */
3912
3913 static int
3914 dataflow_set_preserve_mem_locs (void **slot, void *data)
3915 {
3916   dataflow_set *set = (dataflow_set *) data;
3917   variable var = (variable) *slot;
3918
3919   if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv))
3920     {
3921       tree decl = dv_as_decl (var->dv);
3922       location_chain loc, *locp;
3923       bool changed = false;
3924
3925       if (!var->n_var_parts)
3926         return 1;
3927
3928       gcc_assert (var->n_var_parts == 1);
3929
3930       if (shared_var_p (var, set->vars))
3931         {
3932           for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
3933             {
3934               /* We want to remove dying MEMs that doesn't refer to
3935                  DECL.  */
3936               if (GET_CODE (loc->loc) == MEM
3937                   && (MEM_EXPR (loc->loc) != decl
3938                       || MEM_OFFSET (loc->loc))
3939                   && !mem_dies_at_call (loc->loc))
3940                 break;
3941               /* We want to move here MEMs that do refer to DECL.  */
3942               else if (GET_CODE (loc->loc) == VALUE
3943                        && find_mem_expr_in_1pdv (decl, loc->loc,
3944                                                  shared_hash_htab (set->vars)))
3945                 break;
3946             }
3947
3948           if (!loc)
3949             return 1;
3950
3951           slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
3952           var = (variable)*slot;
3953           gcc_assert (var->n_var_parts == 1);
3954         }
3955
3956       for (locp = &var->var_part[0].loc_chain, loc = *locp;
3957            loc; loc = *locp)
3958         {
3959           rtx old_loc = loc->loc;
3960           if (GET_CODE (old_loc) == VALUE)
3961             {
3962               location_chain mem_node
3963                 = find_mem_expr_in_1pdv (decl, loc->loc,
3964                                          shared_hash_htab (set->vars));
3965
3966               /* ??? This picks up only one out of multiple MEMs that
3967                  refer to the same variable.  Do we ever need to be
3968                  concerned about dealing with more than one, or, given
3969                  that they should all map to the same variable
3970                  location, their addresses will have been merged and
3971                  they will be regarded as equivalent?  */
3972               if (mem_node)
3973                 {
3974                   loc->loc = mem_node->loc;
3975                   loc->set_src = mem_node->set_src;
3976                   loc->init = MIN (loc->init, mem_node->init);
3977                 }
3978             }
3979
3980           if (GET_CODE (loc->loc) != MEM
3981               || (MEM_EXPR (loc->loc) == decl
3982                   && MEM_OFFSET (loc->loc) == 0)
3983               || !mem_dies_at_call (loc->loc))
3984             {
3985               if (old_loc != loc->loc && emit_notes)
3986                 {
3987                   if (old_loc == var->var_part[0].cur_loc)
3988                     {
3989                       changed = true;
3990                       var->var_part[0].cur_loc = NULL;
3991                       var->cur_loc_changed = true;
3992                     }
3993                   add_value_chains (var->dv, loc->loc);
3994                   remove_value_chains (var->dv, old_loc);
3995                 }
3996               locp = &loc->next;
3997               continue;
3998             }
3999
4000           if (emit_notes)
4001             {
4002               remove_value_chains (var->dv, old_loc);
4003               if (old_loc == var->var_part[0].cur_loc)
4004                 {
4005                   changed = true;
4006                   var->var_part[0].cur_loc = NULL;
4007                   var->cur_loc_changed = true;
4008                 }
4009             }
4010           *locp = loc->next;
4011           pool_free (loc_chain_pool, loc);
4012         }
4013
4014       if (!var->var_part[0].loc_chain)
4015         {
4016           var->n_var_parts--;
4017           changed = true;
4018         }
4019       if (changed)
4020         variable_was_changed (var, set);
4021     }
4022
4023   return 1;
4024 }
4025
4026 /* Remove all MEMs from the location list of a hash table entry for a
4027    value.  */
4028
4029 static int
4030 dataflow_set_remove_mem_locs (void **slot, void *data)
4031 {
4032   dataflow_set *set = (dataflow_set *) data;
4033   variable var = (variable) *slot;
4034
4035   if (dv_is_value_p (var->dv))
4036     {
4037       location_chain loc, *locp;
4038       bool changed = false;
4039
4040       gcc_assert (var->n_var_parts == 1);
4041
4042       if (shared_var_p (var, set->vars))
4043         {
4044           for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4045             if (GET_CODE (loc->loc) == MEM
4046                 && mem_dies_at_call (loc->loc))
4047               break;
4048
4049           if (!loc)
4050             return 1;
4051
4052           slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4053           var = (variable)*slot;
4054           gcc_assert (var->n_var_parts == 1);
4055         }
4056
4057       for (locp = &var->var_part[0].loc_chain, loc = *locp;
4058            loc; loc = *locp)
4059         {
4060           if (GET_CODE (loc->loc) != MEM
4061               || !mem_dies_at_call (loc->loc))
4062             {
4063               locp = &loc->next;
4064               continue;
4065             }
4066
4067           if (emit_notes)
4068             remove_value_chains (var->dv, loc->loc);
4069           *locp = loc->next;
4070           /* If we have deleted the location which was last emitted
4071              we have to emit new location so add the variable to set
4072              of changed variables.  */
4073           if (var->var_part[0].cur_loc == loc->loc)
4074             {
4075               changed = true;
4076               var->var_part[0].cur_loc = NULL;
4077               var->cur_loc_changed = true;
4078             }
4079           pool_free (loc_chain_pool, loc);
4080         }
4081
4082       if (!var->var_part[0].loc_chain)
4083         {
4084           var->n_var_parts--;
4085           changed = true;
4086         }
4087       if (changed)
4088         variable_was_changed (var, set);
4089     }
4090
4091   return 1;
4092 }
4093
4094 /* Remove all variable-location information about call-clobbered
4095    registers, as well as associations between MEMs and VALUEs.  */
4096
4097 static void
4098 dataflow_set_clear_at_call (dataflow_set *set)
4099 {
4100   int r;
4101
4102   for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
4103     if (TEST_HARD_REG_BIT (call_used_reg_set, r))
4104       var_regno_delete (set, r);
4105
4106   if (MAY_HAVE_DEBUG_INSNS)
4107     {
4108       set->traversed_vars = set->vars;
4109       htab_traverse (shared_hash_htab (set->vars),
4110                      dataflow_set_preserve_mem_locs, set);
4111       set->traversed_vars = set->vars;
4112       htab_traverse (shared_hash_htab (set->vars), dataflow_set_remove_mem_locs,
4113                      set);
4114       set->traversed_vars = NULL;
4115     }
4116 }
4117
4118 /* Flag whether two dataflow sets being compared contain different data.  */
4119 static bool
4120 dataflow_set_different_value;
4121
4122 static bool
4123 variable_part_different_p (variable_part *vp1, variable_part *vp2)
4124 {
4125   location_chain lc1, lc2;
4126
4127   for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
4128     {
4129       for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
4130         {
4131           if (REG_P (lc1->loc) && REG_P (lc2->loc))
4132             {
4133               if (REGNO (lc1->loc) == REGNO (lc2->loc))
4134                 break;
4135             }
4136           if (rtx_equal_p (lc1->loc, lc2->loc))
4137             break;
4138         }
4139       if (!lc2)
4140         return true;
4141     }
4142   return false;
4143 }
4144
4145 /* Return true if one-part variables VAR1 and VAR2 are different.
4146    They must be in canonical order.  */
4147
4148 static bool
4149 onepart_variable_different_p (variable var1, variable var2)
4150 {
4151   location_chain lc1, lc2;
4152
4153   if (var1 == var2)
4154     return false;
4155
4156   gcc_assert (var1->n_var_parts == 1);
4157   gcc_assert (var2->n_var_parts == 1);
4158
4159   lc1 = var1->var_part[0].loc_chain;
4160   lc2 = var2->var_part[0].loc_chain;
4161
4162   gcc_assert (lc1);
4163   gcc_assert (lc2);
4164
4165   while (lc1 && lc2)
4166     {
4167       if (loc_cmp (lc1->loc, lc2->loc))
4168         return true;
4169       lc1 = lc1->next;
4170       lc2 = lc2->next;
4171     }
4172
4173   return lc1 != lc2;
4174 }
4175
4176 /* Return true if variables VAR1 and VAR2 are different.  */
4177
4178 static bool
4179 variable_different_p (variable var1, variable var2)
4180 {
4181   int i;
4182
4183   if (var1 == var2)
4184     return false;
4185
4186   if (var1->n_var_parts != var2->n_var_parts)
4187     return true;
4188
4189   for (i = 0; i < var1->n_var_parts; i++)
4190     {
4191       if (var1->var_part[i].offset != var2->var_part[i].offset)
4192         return true;
4193       /* One-part values have locations in a canonical order.  */
4194       if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv))
4195         {
4196           gcc_assert (var1->n_var_parts == 1);
4197           gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
4198           return onepart_variable_different_p (var1, var2);
4199         }
4200       if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
4201         return true;
4202       if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
4203         return true;
4204     }
4205   return false;
4206 }
4207
4208 /* Compare variable *SLOT with the same variable in hash table DATA
4209    and set DATAFLOW_SET_DIFFERENT_VALUE if they are different.  */
4210
4211 static int
4212 dataflow_set_different_1 (void **slot, void *data)
4213 {
4214   htab_t htab = (htab_t) data;
4215   variable var1, var2;
4216
4217   var1 = (variable) *slot;
4218   var2 = (variable) htab_find_with_hash (htab, var1->dv,
4219                                          dv_htab_hash (var1->dv));
4220   if (!var2)
4221     {
4222       dataflow_set_different_value = true;
4223
4224       if (dump_file && (dump_flags & TDF_DETAILS))
4225         {
4226           fprintf (dump_file, "dataflow difference found: removal of:\n");
4227           dump_var (var1);
4228         }
4229
4230       /* Stop traversing the hash table.  */
4231       return 0;
4232     }
4233
4234   if (variable_different_p (var1, var2))
4235     {
4236       dataflow_set_different_value = true;
4237
4238       if (dump_file && (dump_flags & TDF_DETAILS))
4239         {
4240           fprintf (dump_file, "dataflow difference found: old and new follow:\n");
4241           dump_var (var1);
4242           dump_var (var2);
4243         }
4244
4245       /* Stop traversing the hash table.  */
4246       return 0;
4247     }
4248
4249   /* Continue traversing the hash table.  */
4250   return 1;
4251 }
4252
4253 /* Return true if dataflow sets OLD_SET and NEW_SET differ.  */
4254
4255 static bool
4256 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
4257 {
4258   if (old_set->vars == new_set->vars)
4259     return false;
4260
4261   if (htab_elements (shared_hash_htab (old_set->vars))
4262       != htab_elements (shared_hash_htab (new_set->vars)))
4263     return true;
4264
4265   dataflow_set_different_value = false;
4266
4267   htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1,
4268                  shared_hash_htab (new_set->vars));
4269   /* No need to traverse the second hashtab, if both have the same number
4270      of elements and the second one had all entries found in the first one,
4271      then it can't have any extra entries.  */
4272   return dataflow_set_different_value;
4273 }
4274
4275 /* Free the contents of dataflow set SET.  */
4276
4277 static void
4278 dataflow_set_destroy (dataflow_set *set)
4279 {
4280   int i;
4281
4282   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4283     attrs_list_clear (&set->regs[i]);
4284
4285   shared_hash_destroy (set->vars);
4286   set->vars = NULL;
4287 }
4288
4289 /* Return true if RTL X contains a SYMBOL_REF.  */
4290
4291 static bool
4292 contains_symbol_ref (rtx x)
4293 {
4294   const char *fmt;
4295   RTX_CODE code;
4296   int i;
4297
4298   if (!x)
4299     return false;
4300
4301   code = GET_CODE (x);
4302   if (code == SYMBOL_REF)
4303     return true;
4304
4305   fmt = GET_RTX_FORMAT (code);
4306   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4307     {
4308       if (fmt[i] == 'e')
4309         {
4310           if (contains_symbol_ref (XEXP (x, i)))
4311             return true;
4312         }
4313       else if (fmt[i] == 'E')
4314         {
4315           int j;
4316           for (j = 0; j < XVECLEN (x, i); j++)
4317             if (contains_symbol_ref (XVECEXP (x, i, j)))
4318               return true;
4319         }
4320     }
4321
4322   return false;
4323 }
4324
4325 /* Shall EXPR be tracked?  */
4326
4327 static bool
4328 track_expr_p (tree expr, bool need_rtl)
4329 {
4330   rtx decl_rtl;
4331   tree realdecl;
4332
4333   if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
4334     return DECL_RTL_SET_P (expr);
4335
4336   /* If EXPR is not a parameter or a variable do not track it.  */
4337   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
4338     return 0;
4339
4340   /* It also must have a name...  */
4341   if (!DECL_NAME (expr) && need_rtl)
4342     return 0;
4343
4344   /* ... and a RTL assigned to it.  */
4345   decl_rtl = DECL_RTL_IF_SET (expr);
4346   if (!decl_rtl && need_rtl)
4347     return 0;
4348
4349   /* If this expression is really a debug alias of some other declaration, we
4350      don't need to track this expression if the ultimate declaration is
4351      ignored.  */
4352   realdecl = expr;
4353   if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
4354     {
4355       realdecl = DECL_DEBUG_EXPR (realdecl);
4356       /* ??? We don't yet know how to emit DW_OP_piece for variable
4357          that has been SRA'ed.  */
4358       if (!DECL_P (realdecl))
4359         return 0;
4360     }
4361
4362   /* Do not track EXPR if REALDECL it should be ignored for debugging
4363      purposes.  */
4364   if (DECL_IGNORED_P (realdecl))
4365     return 0;
4366
4367   /* Do not track global variables until we are able to emit correct location
4368      list for them.  */
4369   if (TREE_STATIC (realdecl))
4370     return 0;
4371
4372   /* When the EXPR is a DECL for alias of some variable (see example)
4373      the TREE_STATIC flag is not used.  Disable tracking all DECLs whose
4374      DECL_RTL contains SYMBOL_REF.
4375
4376      Example:
4377      extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
4378      char **_dl_argv;
4379   */
4380   if (decl_rtl && MEM_P (decl_rtl)
4381       && contains_symbol_ref (XEXP (decl_rtl, 0)))
4382     return 0;
4383
4384   /* If RTX is a memory it should not be very large (because it would be
4385      an array or struct).  */
4386   if (decl_rtl && MEM_P (decl_rtl))
4387     {
4388       /* Do not track structures and arrays.  */
4389       if (GET_MODE (decl_rtl) == BLKmode
4390           || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
4391         return 0;
4392       if (MEM_SIZE (decl_rtl)
4393           && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
4394         return 0;
4395     }
4396
4397   DECL_CHANGED (expr) = 0;
4398   DECL_CHANGED (realdecl) = 0;
4399   return 1;
4400 }
4401
4402 /* Determine whether a given LOC refers to the same variable part as
4403    EXPR+OFFSET.  */
4404
4405 static bool
4406 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
4407 {
4408   tree expr2;
4409   HOST_WIDE_INT offset2;
4410
4411   if (! DECL_P (expr))
4412     return false;
4413
4414   if (REG_P (loc))
4415     {
4416       expr2 = REG_EXPR (loc);
4417       offset2 = REG_OFFSET (loc);
4418     }
4419   else if (MEM_P (loc))
4420     {
4421       expr2 = MEM_EXPR (loc);
4422       offset2 = INT_MEM_OFFSET (loc);
4423     }
4424   else
4425     return false;
4426
4427   if (! expr2 || ! DECL_P (expr2))
4428     return false;
4429
4430   expr = var_debug_decl (expr);
4431   expr2 = var_debug_decl (expr2);
4432
4433   return (expr == expr2 && offset == offset2);
4434 }
4435
4436 /* LOC is a REG or MEM that we would like to track if possible.
4437    If EXPR is null, we don't know what expression LOC refers to,
4438    otherwise it refers to EXPR + OFFSET.  STORE_REG_P is true if
4439    LOC is an lvalue register.
4440
4441    Return true if EXPR is nonnull and if LOC, or some lowpart of it,
4442    is something we can track.  When returning true, store the mode of
4443    the lowpart we can track in *MODE_OUT (if nonnull) and its offset
4444    from EXPR in *OFFSET_OUT (if nonnull).  */
4445
4446 static bool
4447 track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
4448              enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
4449 {
4450   enum machine_mode mode;
4451
4452   if (expr == NULL || !track_expr_p (expr, true))
4453     return false;
4454
4455   /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
4456      whole subreg, but only the old inner part is really relevant.  */
4457   mode = GET_MODE (loc);
4458   if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
4459     {
4460       enum machine_mode pseudo_mode;
4461
4462       pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
4463       if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
4464         {
4465           offset += byte_lowpart_offset (pseudo_mode, mode);
4466           mode = pseudo_mode;
4467         }
4468     }
4469
4470   /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
4471      Do the same if we are storing to a register and EXPR occupies
4472      the whole of register LOC; in that case, the whole of EXPR is
4473      being changed.  We exclude complex modes from the second case
4474      because the real and imaginary parts are represented as separate
4475      pseudo registers, even if the whole complex value fits into one
4476      hard register.  */
4477   if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
4478        || (store_reg_p
4479            && !COMPLEX_MODE_P (DECL_MODE (expr))
4480            && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
4481       && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
4482     {
4483       mode = DECL_MODE (expr);
4484       offset = 0;
4485     }
4486
4487   if (offset < 0 || offset >= MAX_VAR_PARTS)
4488     return false;
4489
4490   if (mode_out)
4491     *mode_out = mode;
4492   if (offset_out)
4493     *offset_out = offset;
4494   return true;
4495 }
4496
4497 /* Return the MODE lowpart of LOC, or null if LOC is not something we
4498    want to track.  When returning nonnull, make sure that the attributes
4499    on the returned value are updated.  */
4500
4501 static rtx
4502 var_lowpart (enum machine_mode mode, rtx loc)
4503 {
4504   unsigned int offset, reg_offset, regno;
4505
4506   if (!REG_P (loc) && !MEM_P (loc))
4507     return NULL;
4508
4509   if (GET_MODE (loc) == mode)
4510     return loc;
4511
4512   offset = byte_lowpart_offset (mode, GET_MODE (loc));
4513
4514   if (MEM_P (loc))
4515     return adjust_address_nv (loc, mode, offset);
4516
4517   reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
4518   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
4519                                              reg_offset, mode);
4520   return gen_rtx_REG_offset (loc, mode, regno, offset);
4521 }
4522
4523 /* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or
4524    hard_frame_pointer_rtx is being mapped to it.  */
4525 static rtx cfa_base_rtx;
4526
4527 /* Carry information about uses and stores while walking rtx.  */
4528
4529 struct count_use_info
4530 {
4531   /* The insn where the RTX is.  */
4532   rtx insn;
4533
4534   /* The basic block where insn is.  */
4535   basic_block bb;
4536
4537   /* The array of n_sets sets in the insn, as determined by cselib.  */
4538   struct cselib_set *sets;
4539   int n_sets;
4540
4541   /* True if we're counting stores, false otherwise.  */
4542   bool store_p;
4543 };
4544
4545 /* Find a VALUE corresponding to X.   */
4546
4547 static inline cselib_val *
4548 find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
4549 {
4550   int i;
4551
4552   if (cui->sets)
4553     {
4554       /* This is called after uses are set up and before stores are
4555          processed bycselib, so it's safe to look up srcs, but not
4556          dsts.  So we look up expressions that appear in srcs or in
4557          dest expressions, but we search the sets array for dests of
4558          stores.  */
4559       if (cui->store_p)
4560         {
4561           for (i = 0; i < cui->n_sets; i++)
4562             if (cui->sets[i].dest == x)
4563               return cui->sets[i].src_elt;
4564         }
4565       else
4566         return cselib_lookup (x, mode, 0);
4567     }
4568
4569   return NULL;
4570 }
4571
4572 /* Helper function to get mode of MEM's address.  */
4573
4574 static inline enum machine_mode
4575 get_address_mode (rtx mem)
4576 {
4577   enum machine_mode mode = GET_MODE (XEXP (mem, 0));
4578   if (mode != VOIDmode)
4579     return mode;
4580   return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
4581 }
4582
4583 /* Replace all registers and addresses in an expression with VALUE
4584    expressions that map back to them, unless the expression is a
4585    register.  If no mapping is or can be performed, returns NULL.  */
4586
4587 static rtx
4588 replace_expr_with_values (rtx loc)
4589 {
4590   if (REG_P (loc))
4591     return NULL;
4592   else if (MEM_P (loc))
4593     {
4594       cselib_val *addr = cselib_lookup (XEXP (loc, 0),
4595                                         get_address_mode (loc), 0);
4596       if (addr)
4597         return replace_equiv_address_nv (loc, addr->val_rtx);
4598       else
4599         return NULL;
4600     }
4601   else
4602     return cselib_subst_to_values (loc);
4603 }
4604
4605 /* Determine what kind of micro operation to choose for a USE.  Return
4606    MO_CLOBBER if no micro operation is to be generated.  */
4607
4608 static enum micro_operation_type
4609 use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
4610 {
4611   tree expr;
4612
4613   if (cui && cui->sets)
4614     {
4615       if (GET_CODE (loc) == VAR_LOCATION)
4616         {
4617           if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false))
4618             {
4619               rtx ploc = PAT_VAR_LOCATION_LOC (loc);
4620               if (! VAR_LOC_UNKNOWN_P (ploc))
4621                 {
4622                   cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1);
4623
4624                   /* ??? flag_float_store and volatile mems are never
4625                      given values, but we could in theory use them for
4626                      locations.  */
4627                   gcc_assert (val || 1);
4628                 }
4629               return MO_VAL_LOC;
4630             }
4631           else
4632             return MO_CLOBBER;
4633         }
4634
4635       if (REG_P (loc) || MEM_P (loc))
4636         {
4637           if (modep)
4638             *modep = GET_MODE (loc);
4639           if (cui->store_p)
4640             {
4641               if (REG_P (loc)
4642                   || (find_use_val (loc, GET_MODE (loc), cui)
4643                       && cselib_lookup (XEXP (loc, 0),
4644                                         get_address_mode (loc), 0)))
4645                 return MO_VAL_SET;
4646             }
4647           else
4648             {
4649               cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
4650
4651               if (val && !cselib_preserved_value_p (val))
4652                 return MO_VAL_USE;
4653             }
4654         }
4655     }
4656
4657   if (REG_P (loc))
4658     {
4659       gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER);
4660
4661       if (loc == cfa_base_rtx)
4662         return MO_CLOBBER;
4663       expr = REG_EXPR (loc);
4664
4665       if (!expr)
4666         return MO_USE_NO_VAR;
4667       else if (target_for_debug_bind (var_debug_decl (expr)))
4668         return MO_CLOBBER;
4669       else if (track_loc_p (loc, expr, REG_OFFSET (loc),
4670                             false, modep, NULL))
4671         return MO_USE;
4672       else
4673         return MO_USE_NO_VAR;
4674     }
4675   else if (MEM_P (loc))
4676     {
4677       expr = MEM_EXPR (loc);
4678
4679       if (!expr)
4680         return MO_CLOBBER;
4681       else if (target_for_debug_bind (var_debug_decl (expr)))
4682         return MO_CLOBBER;
4683       else if (track_loc_p (loc, expr, INT_MEM_OFFSET (loc),
4684                             false, modep, NULL))
4685         return MO_USE;
4686       else
4687         return MO_CLOBBER;
4688     }
4689
4690   return MO_CLOBBER;
4691 }
4692
4693 /* Log to OUT information about micro-operation MOPT involving X in
4694    INSN of BB.  */
4695
4696 static inline void
4697 log_op_type (rtx x, basic_block bb, rtx insn,
4698              enum micro_operation_type mopt, FILE *out)
4699 {
4700   fprintf (out, "bb %i op %i insn %i %s ",
4701            bb->index, VEC_length (micro_operation, VTI (bb)->mos),
4702            INSN_UID (insn), micro_operation_type_name[mopt]);
4703   print_inline_rtx (out, x, 2);
4704   fputc ('\n', out);
4705 }
4706
4707 /* Tell whether the CONCAT used to holds a VALUE and its location
4708    needs value resolution, i.e., an attempt of mapping the location
4709    back to other incoming values.  */
4710 #define VAL_NEEDS_RESOLUTION(x) \
4711   (RTL_FLAG_CHECK1 ("VAL_NEEDS_RESOLUTION", (x), CONCAT)->volatil)
4712 /* Whether the location in the CONCAT is a tracked expression, that
4713    should also be handled like a MO_USE.  */
4714 #define VAL_HOLDS_TRACK_EXPR(x) \
4715   (RTL_FLAG_CHECK1 ("VAL_HOLDS_TRACK_EXPR", (x), CONCAT)->used)
4716 /* Whether the location in the CONCAT should be handled like a MO_COPY
4717    as well.  */
4718 #define VAL_EXPR_IS_COPIED(x) \
4719   (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_COPIED", (x), CONCAT)->jump)
4720 /* Whether the location in the CONCAT should be handled like a
4721    MO_CLOBBER as well.  */
4722 #define VAL_EXPR_IS_CLOBBERED(x) \
4723   (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_CLOBBERED", (x), CONCAT)->unchanging)
4724 /* Whether the location is a CONCAT of the MO_VAL_SET expression and
4725    a reverse operation that should be handled afterwards.  */
4726 #define VAL_EXPR_HAS_REVERSE(x) \
4727   (RTL_FLAG_CHECK1 ("VAL_EXPR_HAS_REVERSE", (x), CONCAT)->return_val)
4728
4729 /* All preserved VALUEs.  */
4730 static VEC (rtx, heap) *preserved_values;
4731
4732 /* Ensure VAL is preserved and remember it in a vector for vt_emit_notes.  */
4733
4734 static void
4735 preserve_value (cselib_val *val)
4736 {
4737   cselib_preserve_value (val);
4738   VEC_safe_push (rtx, heap, preserved_values, val->val_rtx);
4739 }
4740
4741 /* Add uses (register and memory references) LOC which will be tracked
4742    to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
4743
4744 static int
4745 add_uses (rtx *ploc, void *data)
4746 {
4747   rtx loc = *ploc;
4748   enum machine_mode mode = VOIDmode;
4749   struct count_use_info *cui = (struct count_use_info *)data;
4750   enum micro_operation_type type = use_type (loc, cui, &mode);
4751
4752   if (type != MO_CLOBBER)
4753     {
4754       basic_block bb = cui->bb;
4755       micro_operation mo;
4756
4757       mo.type = type;
4758       mo.u.loc = type == MO_USE ? var_lowpart (mode, loc) : loc;
4759       mo.insn = cui->insn;
4760
4761       if (type == MO_VAL_LOC)
4762         {
4763           rtx oloc = loc;
4764           rtx vloc = PAT_VAR_LOCATION_LOC (oloc);
4765           cselib_val *val;
4766
4767           gcc_assert (cui->sets);
4768
4769           if (MEM_P (vloc)
4770               && !REG_P (XEXP (vloc, 0))
4771               && !MEM_P (XEXP (vloc, 0))
4772               && (GET_CODE (XEXP (vloc, 0)) != PLUS
4773                   || XEXP (XEXP (vloc, 0), 0) != cfa_base_rtx
4774                   || !CONST_INT_P (XEXP (XEXP (vloc, 0), 1))))
4775             {
4776               rtx mloc = vloc;
4777               enum machine_mode address_mode = get_address_mode (mloc);
4778               cselib_val *val
4779                 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
4780
4781               if (val && !cselib_preserved_value_p (val))
4782                 {
4783                   micro_operation moa;
4784                   preserve_value (val);
4785                   mloc = cselib_subst_to_values (XEXP (mloc, 0));
4786                   moa.type = MO_VAL_USE;
4787                   moa.insn = cui->insn;
4788                   moa.u.loc = gen_rtx_CONCAT (address_mode,
4789                                               val->val_rtx, mloc);
4790                   if (dump_file && (dump_flags & TDF_DETAILS))
4791                     log_op_type (moa.u.loc, cui->bb, cui->insn,
4792                                  moa.type, dump_file);
4793                   VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
4794                 }
4795             }
4796
4797           if (!VAR_LOC_UNKNOWN_P (vloc)
4798               && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
4799             {
4800               enum machine_mode mode2;
4801               enum micro_operation_type type2;
4802               rtx nloc = replace_expr_with_values (vloc);
4803
4804               if (nloc)
4805                 {
4806                   oloc = shallow_copy_rtx (oloc);
4807                   PAT_VAR_LOCATION_LOC (oloc) = nloc;
4808                 }
4809
4810               oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc);
4811
4812               type2 = use_type (vloc, 0, &mode2);
4813
4814               gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
4815                           || type2 == MO_CLOBBER);
4816
4817               if (type2 == MO_CLOBBER
4818                   && !cselib_preserved_value_p (val))
4819                 {
4820                   VAL_NEEDS_RESOLUTION (oloc) = 1;
4821                   preserve_value (val);
4822                 }
4823             }
4824           else if (!VAR_LOC_UNKNOWN_P (vloc))
4825             {
4826               oloc = shallow_copy_rtx (oloc);
4827               PAT_VAR_LOCATION_LOC (oloc) = gen_rtx_UNKNOWN_VAR_LOC ();
4828             }
4829
4830           mo.u.loc = oloc;
4831         }
4832       else if (type == MO_VAL_USE)
4833         {
4834           enum machine_mode mode2 = VOIDmode;
4835           enum micro_operation_type type2;
4836           cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
4837           rtx vloc, oloc = loc, nloc;
4838
4839           gcc_assert (cui->sets);
4840
4841           if (MEM_P (oloc)
4842               && !REG_P (XEXP (oloc, 0))
4843               && !MEM_P (XEXP (oloc, 0))
4844               && (GET_CODE (XEXP (oloc, 0)) != PLUS
4845                   || XEXP (XEXP (oloc, 0), 0) != cfa_base_rtx
4846                   || !CONST_INT_P (XEXP (XEXP (oloc, 0), 1))))
4847             {
4848               rtx mloc = oloc;
4849               enum machine_mode address_mode = get_address_mode (mloc);
4850               cselib_val *val
4851                 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
4852
4853               if (val && !cselib_preserved_value_p (val))
4854                 {
4855                   micro_operation moa;
4856                   preserve_value (val);
4857                   mloc = cselib_subst_to_values (XEXP (mloc, 0));
4858                   moa.type = MO_VAL_USE;
4859                   moa.insn = cui->insn;
4860                   moa.u.loc = gen_rtx_CONCAT (address_mode,
4861                                               val->val_rtx, mloc);
4862                   if (dump_file && (dump_flags & TDF_DETAILS))
4863                     log_op_type (moa.u.loc, cui->bb, cui->insn,
4864                                  moa.type, dump_file);
4865                   VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
4866                 }
4867             }
4868
4869           type2 = use_type (loc, 0, &mode2);
4870
4871           gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
4872                       || type2 == MO_CLOBBER);
4873
4874           if (type2 == MO_USE)
4875             vloc = var_lowpart (mode2, loc);
4876           else
4877             vloc = oloc;
4878
4879           /* The loc of a MO_VAL_USE may have two forms:
4880
4881              (concat val src): val is at src, a value-based
4882              representation.
4883
4884              (concat (concat val use) src): same as above, with use as
4885              the MO_USE tracked value, if it differs from src.
4886
4887           */
4888
4889           nloc = replace_expr_with_values (loc);
4890           if (!nloc)
4891             nloc = oloc;
4892
4893           if (vloc != nloc)
4894             oloc = gen_rtx_CONCAT (mode2, val->val_rtx, vloc);
4895           else
4896             oloc = val->val_rtx;
4897
4898           mo.u.loc = gen_rtx_CONCAT (mode, oloc, nloc);
4899
4900           if (type2 == MO_USE)
4901             VAL_HOLDS_TRACK_EXPR (mo.u.loc) = 1;
4902           if (!cselib_preserved_value_p (val))
4903             {
4904               VAL_NEEDS_RESOLUTION (mo.u.loc) = 1;
4905               preserve_value (val);
4906             }
4907         }
4908       else
4909         gcc_assert (type == MO_USE || type == MO_USE_NO_VAR);
4910
4911       if (dump_file && (dump_flags & TDF_DETAILS))
4912         log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
4913       VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
4914     }
4915
4916   return 0;
4917 }
4918
4919 /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
4920
4921 static void
4922 add_uses_1 (rtx *x, void *cui)
4923 {
4924   for_each_rtx (x, add_uses, cui);
4925 }
4926
4927 /* Attempt to reverse the EXPR operation in the debug info.  Say for
4928    reg1 = reg2 + 6 even when reg2 is no longer live we
4929    can express its value as VAL - 6.  */
4930
4931 static rtx
4932 reverse_op (rtx val, const_rtx expr)
4933 {
4934   rtx src, arg, ret;
4935   cselib_val *v;
4936   enum rtx_code code;
4937
4938   if (GET_CODE (expr) != SET)
4939     return NULL_RTX;
4940
4941   if (!REG_P (SET_DEST (expr)) || GET_MODE (val) != GET_MODE (SET_DEST (expr)))
4942     return NULL_RTX;
4943
4944   src = SET_SRC (expr);
4945   switch (GET_CODE (src))
4946     {
4947     case PLUS:
4948     case MINUS:
4949     case XOR:
4950     case NOT:
4951     case NEG:
4952     case SIGN_EXTEND:
4953     case ZERO_EXTEND:
4954       break;
4955     default:
4956       return NULL_RTX;
4957     }
4958
4959   if (!REG_P (XEXP (src, 0)) || !SCALAR_INT_MODE_P (GET_MODE (src)))
4960     return NULL_RTX;
4961
4962   v = cselib_lookup (XEXP (src, 0), GET_MODE (XEXP (src, 0)), 0);
4963   if (!v || !cselib_preserved_value_p (v))
4964     return NULL_RTX;
4965
4966   switch (GET_CODE (src))
4967     {
4968     case NOT:
4969     case NEG:
4970       if (GET_MODE (v->val_rtx) != GET_MODE (val))
4971         return NULL_RTX;
4972       ret = gen_rtx_fmt_e (GET_CODE (src), GET_MODE (val), val);
4973       break;
4974     case SIGN_EXTEND:
4975     case ZERO_EXTEND:
4976       ret = gen_lowpart_SUBREG (GET_MODE (v->val_rtx), val);
4977       break;
4978     case XOR:
4979       code = XOR;
4980       goto binary;
4981     case PLUS:
4982       code = MINUS;
4983       goto binary;
4984     case MINUS:
4985       code = PLUS;
4986       goto binary;
4987     binary:
4988       if (GET_MODE (v->val_rtx) != GET_MODE (val))
4989         return NULL_RTX;
4990       arg = XEXP (src, 1);
4991       if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
4992         {
4993           arg = cselib_expand_value_rtx (arg, scratch_regs, 5);
4994           if (arg == NULL_RTX)
4995             return NULL_RTX;
4996           if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
4997             return NULL_RTX;
4998         }
4999       ret = simplify_gen_binary (code, GET_MODE (val), val, arg);
5000       if (ret == val)
5001         /* Ensure ret isn't VALUE itself (which can happen e.g. for
5002            (plus (reg1) (reg2)) when reg2 is known to be 0), as that
5003            breaks a lot of routines during var-tracking.  */
5004         ret = gen_rtx_fmt_ee (PLUS, GET_MODE (val), val, const0_rtx);
5005       break;
5006     default:
5007       gcc_unreachable ();
5008     }
5009
5010   return gen_rtx_CONCAT (GET_MODE (v->val_rtx), v->val_rtx, ret);
5011 }
5012
5013 /* Add stores (register and memory references) LOC which will be tracked
5014    to VTI (bb)->mos.  EXPR is the RTL expression containing the store.
5015    CUIP->insn is instruction which the LOC is part of.  */
5016
5017 static void
5018 add_stores (rtx loc, const_rtx expr, void *cuip)
5019 {
5020   enum machine_mode mode = VOIDmode, mode2;
5021   struct count_use_info *cui = (struct count_use_info *)cuip;
5022   basic_block bb = cui->bb;
5023   micro_operation mo;
5024   rtx oloc = loc, nloc, src = NULL;
5025   enum micro_operation_type type = use_type (loc, cui, &mode);
5026   bool track_p = false;
5027   cselib_val *v;
5028   bool resolve, preserve;
5029   rtx reverse;
5030
5031   if (type == MO_CLOBBER)
5032     return;
5033
5034   mode2 = mode;
5035
5036   if (REG_P (loc))
5037     {
5038       gcc_assert (loc != cfa_base_rtx);
5039       if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET)
5040           || !(track_p = use_type (loc, NULL, &mode2) == MO_USE)
5041           || GET_CODE (expr) == CLOBBER)
5042         {
5043           mo.type = MO_CLOBBER;
5044           mo.u.loc = loc;
5045         }
5046       else
5047         {
5048           if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
5049             src = var_lowpart (mode2, SET_SRC (expr));
5050           loc = var_lowpart (mode2, loc);
5051
5052           if (src == NULL)
5053             {
5054               mo.type = MO_SET;
5055               mo.u.loc = loc;
5056             }
5057           else
5058             {
5059               rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
5060               if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
5061                 mo.type = MO_COPY;
5062               else
5063                 mo.type = MO_SET;
5064               mo.u.loc = xexpr;
5065             }
5066         }
5067       mo.insn = cui->insn;
5068     }
5069   else if (MEM_P (loc)
5070            && ((track_p = use_type (loc, NULL, &mode2) == MO_USE)
5071                || cui->sets))
5072     {
5073       if (MEM_P (loc) && type == MO_VAL_SET
5074           && !REG_P (XEXP (loc, 0))
5075           && !MEM_P (XEXP (loc, 0))
5076           && (GET_CODE (XEXP (loc, 0)) != PLUS
5077               || XEXP (XEXP (loc, 0), 0) != cfa_base_rtx
5078               || !CONST_INT_P (XEXP (XEXP (loc, 0), 1))))
5079         {
5080           rtx mloc = loc;
5081           enum machine_mode address_mode = get_address_mode (mloc);
5082           cselib_val *val = cselib_lookup (XEXP (mloc, 0),
5083                                            address_mode, 0);
5084
5085           if (val && !cselib_preserved_value_p (val))
5086             {
5087               preserve_value (val);
5088               mo.type = MO_VAL_USE;
5089               mloc = cselib_subst_to_values (XEXP (mloc, 0));
5090               mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
5091               mo.insn = cui->insn;
5092               if (dump_file && (dump_flags & TDF_DETAILS))
5093                 log_op_type (mo.u.loc, cui->bb, cui->insn,
5094                              mo.type, dump_file);
5095               VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5096             }
5097         }
5098
5099       if (GET_CODE (expr) == CLOBBER || !track_p)
5100         {
5101           mo.type = MO_CLOBBER;
5102           mo.u.loc = track_p ? var_lowpart (mode2, loc) : loc;
5103         }
5104       else
5105         {
5106           if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
5107             src = var_lowpart (mode2, SET_SRC (expr));
5108           loc = var_lowpart (mode2, loc);
5109
5110           if (src == NULL)
5111             {
5112               mo.type = MO_SET;
5113               mo.u.loc = loc;
5114             }
5115           else
5116             {
5117               rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
5118               if (same_variable_part_p (SET_SRC (xexpr),
5119                                         MEM_EXPR (loc),
5120                                         INT_MEM_OFFSET (loc)))
5121                 mo.type = MO_COPY;
5122               else
5123                 mo.type = MO_SET;
5124               mo.u.loc = xexpr;
5125             }
5126         }
5127       mo.insn = cui->insn;
5128     }
5129   else
5130     return;
5131
5132   if (type != MO_VAL_SET)
5133     goto log_and_return;
5134
5135   v = find_use_val (oloc, mode, cui);
5136
5137   if (!v)
5138     goto log_and_return;
5139
5140   resolve = preserve = !cselib_preserved_value_p (v);
5141
5142   nloc = replace_expr_with_values (oloc);
5143   if (nloc)
5144     oloc = nloc;
5145
5146   if (GET_CODE (PATTERN (cui->insn)) == COND_EXEC)
5147     {
5148       cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0);
5149
5150       gcc_assert (oval != v);
5151       gcc_assert (REG_P (oloc) || MEM_P (oloc));
5152
5153       if (!cselib_preserved_value_p (oval))
5154         {
5155           micro_operation moa;
5156
5157           preserve_value (oval);
5158
5159           moa.type = MO_VAL_USE;
5160           moa.u.loc = gen_rtx_CONCAT (mode, oval->val_rtx, oloc);
5161           VAL_NEEDS_RESOLUTION (moa.u.loc) = 1;
5162           moa.insn = cui->insn;
5163
5164           if (dump_file && (dump_flags & TDF_DETAILS))
5165             log_op_type (moa.u.loc, cui->bb, cui->insn,
5166                          moa.type, dump_file);
5167           VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
5168         }
5169
5170       resolve = false;
5171     }
5172   else if (resolve && GET_CODE (mo.u.loc) == SET)
5173     {
5174       nloc = replace_expr_with_values (SET_SRC (expr));
5175
5176       /* Avoid the mode mismatch between oexpr and expr.  */
5177       if (!nloc && mode != mode2)
5178         {
5179           nloc = SET_SRC (expr);
5180           gcc_assert (oloc == SET_DEST (expr));
5181         }
5182
5183       if (nloc)
5184         oloc = gen_rtx_SET (GET_MODE (mo.u.loc), oloc, nloc);
5185       else
5186         {
5187           if (oloc == SET_DEST (mo.u.loc))
5188             /* No point in duplicating.  */
5189             oloc = mo.u.loc;
5190           if (!REG_P (SET_SRC (mo.u.loc)))
5191             resolve = false;
5192         }
5193     }
5194   else if (!resolve)
5195     {
5196       if (GET_CODE (mo.u.loc) == SET
5197           && oloc == SET_DEST (mo.u.loc))
5198         /* No point in duplicating.  */
5199         oloc = mo.u.loc;
5200     }
5201   else
5202     resolve = false;
5203
5204   loc = gen_rtx_CONCAT (mode, v->val_rtx, oloc);
5205
5206   if (mo.u.loc != oloc)
5207     loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, mo.u.loc);
5208
5209   /* The loc of a MO_VAL_SET may have various forms:
5210
5211      (concat val dst): dst now holds val
5212
5213      (concat val (set dst src)): dst now holds val, copied from src
5214
5215      (concat (concat val dstv) dst): dst now holds val; dstv is dst
5216      after replacing mems and non-top-level regs with values.
5217
5218      (concat (concat val dstv) (set dst src)): dst now holds val,
5219      copied from src.  dstv is a value-based representation of dst, if
5220      it differs from dst.  If resolution is needed, src is a REG, and
5221      its mode is the same as that of val.
5222
5223      (concat (concat val (set dstv srcv)) (set dst src)): src
5224      copied to dst, holding val.  dstv and srcv are value-based
5225      representations of dst and src, respectively.
5226
5227   */
5228
5229   if (GET_CODE (PATTERN (cui->insn)) != COND_EXEC)
5230     {
5231       reverse = reverse_op (v->val_rtx, expr);
5232       if (reverse)
5233         {
5234           loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, reverse);
5235           VAL_EXPR_HAS_REVERSE (loc) = 1;
5236         }
5237     }
5238
5239   mo.u.loc = loc;
5240
5241   if (track_p)
5242     VAL_HOLDS_TRACK_EXPR (loc) = 1;
5243   if (preserve)
5244     {
5245       VAL_NEEDS_RESOLUTION (loc) = resolve;
5246       preserve_value (v);
5247     }
5248   if (mo.type == MO_CLOBBER)
5249     VAL_EXPR_IS_CLOBBERED (loc) = 1;
5250   if (mo.type == MO_COPY)
5251     VAL_EXPR_IS_COPIED (loc) = 1;
5252
5253   mo.type = MO_VAL_SET;
5254
5255  log_and_return:
5256   if (dump_file && (dump_flags & TDF_DETAILS))
5257     log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
5258   VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5259 }
5260
5261 /* Callback for cselib_record_sets_hook, that records as micro
5262    operations uses and stores in an insn after cselib_record_sets has
5263    analyzed the sets in an insn, but before it modifies the stored
5264    values in the internal tables, unless cselib_record_sets doesn't
5265    call it directly (perhaps because we're not doing cselib in the
5266    first place, in which case sets and n_sets will be 0).  */
5267
5268 static void
5269 add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
5270 {
5271   basic_block bb = BLOCK_FOR_INSN (insn);
5272   int n1, n2;
5273   struct count_use_info cui;
5274   micro_operation *mos;
5275
5276   cselib_hook_called = true;
5277
5278   cui.insn = insn;
5279   cui.bb = bb;
5280   cui.sets = sets;
5281   cui.n_sets = n_sets;
5282
5283   n1 = VEC_length (micro_operation, VTI (bb)->mos);
5284   cui.store_p = false;
5285   note_uses (&PATTERN (insn), add_uses_1, &cui);
5286   n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5287   mos = VEC_address (micro_operation, VTI (bb)->mos);
5288
5289   /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
5290      MO_VAL_LOC last.  */
5291   while (n1 < n2)
5292     {
5293       while (n1 < n2 && mos[n1].type == MO_USE)
5294         n1++;
5295       while (n1 < n2 && mos[n2].type != MO_USE)
5296         n2--;
5297       if (n1 < n2)
5298         {
5299           micro_operation sw;
5300
5301           sw = mos[n1];
5302           mos[n1] = mos[n2];
5303           mos[n2] = sw;
5304         }
5305     }
5306
5307   n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5308   while (n1 < n2)
5309     {
5310       while (n1 < n2 && mos[n1].type != MO_VAL_LOC)
5311         n1++;
5312       while (n1 < n2 && mos[n2].type == MO_VAL_LOC)
5313         n2--;
5314       if (n1 < n2)
5315         {
5316           micro_operation sw;
5317
5318           sw = mos[n1];
5319           mos[n1] = mos[n2];
5320           mos[n2] = sw;
5321         }
5322     }
5323
5324   if (CALL_P (insn))
5325     {
5326       micro_operation mo;
5327
5328       mo.type = MO_CALL;
5329       mo.insn = insn;
5330       mo.u.loc = NULL_RTX;
5331
5332       if (dump_file && (dump_flags & TDF_DETAILS))
5333         log_op_type (PATTERN (insn), bb, insn, mo.type, dump_file);
5334       VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5335     }
5336
5337   n1 = VEC_length (micro_operation, VTI (bb)->mos);
5338   /* This will record NEXT_INSN (insn), such that we can
5339      insert notes before it without worrying about any
5340      notes that MO_USEs might emit after the insn.  */
5341   cui.store_p = true;
5342   note_stores (PATTERN (insn), add_stores, &cui);
5343   n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5344   mos = VEC_address (micro_operation, VTI (bb)->mos);
5345
5346   /* Order the MO_VAL_USEs first (note_stores does nothing
5347      on DEBUG_INSNs, so there are no MO_VAL_LOCs from this
5348      insn), then MO_CLOBBERs, then MO_SET/MO_COPY/MO_VAL_SET.  */
5349   while (n1 < n2)
5350     {
5351       while (n1 < n2 && mos[n1].type == MO_VAL_USE)
5352         n1++;
5353       while (n1 < n2 && mos[n2].type != MO_VAL_USE)
5354         n2--;
5355       if (n1 < n2)
5356         {
5357           micro_operation sw;
5358
5359           sw = mos[n1];
5360           mos[n1] = mos[n2];
5361           mos[n2] = sw;
5362         }
5363     }
5364
5365   n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5366   while (n1 < n2)
5367     {
5368       while (n1 < n2 && mos[n1].type == MO_CLOBBER)
5369         n1++;
5370       while (n1 < n2 && mos[n2].type != MO_CLOBBER)
5371         n2--;
5372       if (n1 < n2)
5373         {
5374           micro_operation sw;
5375
5376           sw = mos[n1];
5377           mos[n1] = mos[n2];
5378           mos[n2] = sw;
5379         }
5380     }
5381 }
5382
5383 static enum var_init_status
5384 find_src_status (dataflow_set *in, rtx src)
5385 {
5386   tree decl = NULL_TREE;
5387   enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
5388
5389   if (! flag_var_tracking_uninit)
5390     status = VAR_INIT_STATUS_INITIALIZED;
5391
5392   if (src && REG_P (src))
5393     decl = var_debug_decl (REG_EXPR (src));
5394   else if (src && MEM_P (src))
5395     decl = var_debug_decl (MEM_EXPR (src));
5396
5397   if (src && decl)
5398     status = get_init_value (in, src, dv_from_decl (decl));
5399
5400   return status;
5401 }
5402
5403 /* SRC is the source of an assignment.  Use SET to try to find what
5404    was ultimately assigned to SRC.  Return that value if known,
5405    otherwise return SRC itself.  */
5406
5407 static rtx
5408 find_src_set_src (dataflow_set *set, rtx src)
5409 {
5410   tree decl = NULL_TREE;   /* The variable being copied around.          */
5411   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
5412   variable var;
5413   location_chain nextp;
5414   int i;
5415   bool found;
5416
5417   if (src && REG_P (src))
5418     decl = var_debug_decl (REG_EXPR (src));
5419   else if (src && MEM_P (src))
5420     decl = var_debug_decl (MEM_EXPR (src));
5421
5422   if (src && decl)
5423     {
5424       decl_or_value dv = dv_from_decl (decl);
5425
5426       var = shared_hash_find (set->vars, dv);
5427       if (var)
5428         {
5429           found = false;
5430           for (i = 0; i < var->n_var_parts && !found; i++)
5431             for (nextp = var->var_part[i].loc_chain; nextp && !found;
5432                  nextp = nextp->next)
5433               if (rtx_equal_p (nextp->loc, src))
5434                 {
5435                   set_src = nextp->set_src;
5436                   found = true;
5437                 }
5438
5439         }
5440     }
5441
5442   return set_src;
5443 }
5444
5445 /* Compute the changes of variable locations in the basic block BB.  */
5446
5447 static bool
5448 compute_bb_dataflow (basic_block bb)
5449 {
5450   unsigned int i;
5451   micro_operation *mo;
5452   bool changed;
5453   dataflow_set old_out;
5454   dataflow_set *in = &VTI (bb)->in;
5455   dataflow_set *out = &VTI (bb)->out;
5456
5457   dataflow_set_init (&old_out);
5458   dataflow_set_copy (&old_out, out);
5459   dataflow_set_copy (out, in);
5460
5461   for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
5462     {
5463       rtx insn = mo->insn;
5464
5465       switch (mo->type)
5466         {
5467           case MO_CALL:
5468             dataflow_set_clear_at_call (out);
5469             break;
5470
5471           case MO_USE:
5472             {
5473               rtx loc = mo->u.loc;
5474
5475               if (REG_P (loc))
5476                 var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5477               else if (MEM_P (loc))
5478                 var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5479             }
5480             break;
5481
5482           case MO_VAL_LOC:
5483             {
5484               rtx loc = mo->u.loc;
5485               rtx val, vloc;
5486               tree var;
5487
5488               if (GET_CODE (loc) == CONCAT)
5489                 {
5490                   val = XEXP (loc, 0);
5491                   vloc = XEXP (loc, 1);
5492                 }
5493               else
5494                 {
5495                   val = NULL_RTX;
5496                   vloc = loc;
5497                 }
5498
5499               var = PAT_VAR_LOCATION_DECL (vloc);
5500
5501               clobber_variable_part (out, NULL_RTX,
5502                                      dv_from_decl (var), 0, NULL_RTX);
5503               if (val)
5504                 {
5505                   if (VAL_NEEDS_RESOLUTION (loc))
5506                     val_resolve (out, val, PAT_VAR_LOCATION_LOC (vloc), insn);
5507                   set_variable_part (out, val, dv_from_decl (var), 0,
5508                                      VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
5509                                      INSERT);
5510                 }
5511             }
5512             break;
5513
5514           case MO_VAL_USE:
5515             {
5516               rtx loc = mo->u.loc;
5517               rtx val, vloc, uloc;
5518
5519               vloc = uloc = XEXP (loc, 1);
5520               val = XEXP (loc, 0);
5521
5522               if (GET_CODE (val) == CONCAT)
5523                 {
5524                   uloc = XEXP (val, 1);
5525                   val = XEXP (val, 0);
5526                 }
5527
5528               if (VAL_NEEDS_RESOLUTION (loc))
5529                 val_resolve (out, val, vloc, insn);
5530               else
5531                 val_store (out, val, uloc, insn, false);
5532
5533               if (VAL_HOLDS_TRACK_EXPR (loc))
5534                 {
5535                   if (GET_CODE (uloc) == REG)
5536                     var_reg_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5537                                  NULL);
5538                   else if (GET_CODE (uloc) == MEM)
5539                     var_mem_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5540                                  NULL);
5541                 }
5542             }
5543             break;
5544
5545           case MO_VAL_SET:
5546             {
5547               rtx loc = mo->u.loc;
5548               rtx val, vloc, uloc, reverse = NULL_RTX;
5549
5550               vloc = loc;
5551               if (VAL_EXPR_HAS_REVERSE (loc))
5552                 {
5553                   reverse = XEXP (loc, 1);
5554                   vloc = XEXP (loc, 0);
5555                 }
5556               uloc = XEXP (vloc, 1);
5557               val = XEXP (vloc, 0);
5558               vloc = uloc;
5559
5560               if (GET_CODE (val) == CONCAT)
5561                 {
5562                   vloc = XEXP (val, 1);
5563                   val = XEXP (val, 0);
5564                 }
5565
5566               if (GET_CODE (vloc) == SET)
5567                 {
5568                   rtx vsrc = SET_SRC (vloc);
5569
5570                   gcc_assert (val != vsrc);
5571                   gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
5572
5573                   vloc = SET_DEST (vloc);
5574
5575                   if (VAL_NEEDS_RESOLUTION (loc))
5576                     val_resolve (out, val, vsrc, insn);
5577                 }
5578               else if (VAL_NEEDS_RESOLUTION (loc))
5579                 {
5580                   gcc_assert (GET_CODE (uloc) == SET
5581                               && GET_CODE (SET_SRC (uloc)) == REG);
5582                   val_resolve (out, val, SET_SRC (uloc), insn);
5583                 }
5584
5585               if (VAL_HOLDS_TRACK_EXPR (loc))
5586                 {
5587                   if (VAL_EXPR_IS_CLOBBERED (loc))
5588                     {
5589                       if (REG_P (uloc))
5590                         var_reg_delete (out, uloc, true);
5591                       else if (MEM_P (uloc))
5592                         var_mem_delete (out, uloc, true);
5593                     }
5594                   else
5595                     {
5596                       bool copied_p = VAL_EXPR_IS_COPIED (loc);
5597                       rtx set_src = NULL;
5598                       enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
5599
5600                       if (GET_CODE (uloc) == SET)
5601                         {
5602                           set_src = SET_SRC (uloc);
5603                           uloc = SET_DEST (uloc);
5604                         }
5605
5606                       if (copied_p)
5607                         {
5608                           if (flag_var_tracking_uninit)
5609                             {
5610                               status = find_src_status (in, set_src);
5611
5612                               if (status == VAR_INIT_STATUS_UNKNOWN)
5613                                 status = find_src_status (out, set_src);
5614                             }
5615
5616                           set_src = find_src_set_src (in, set_src);
5617                         }
5618
5619                       if (REG_P (uloc))
5620                         var_reg_delete_and_set (out, uloc, !copied_p,
5621                                                 status, set_src);
5622                       else if (MEM_P (uloc))
5623                         var_mem_delete_and_set (out, uloc, !copied_p,
5624                                                 status, set_src);
5625                     }
5626                 }
5627               else if (REG_P (uloc))
5628                 var_regno_delete (out, REGNO (uloc));
5629
5630               val_store (out, val, vloc, insn, true);
5631
5632               if (reverse)
5633                 val_store (out, XEXP (reverse, 0), XEXP (reverse, 1),
5634                            insn, false);
5635             }
5636             break;
5637
5638           case MO_SET:
5639             {
5640               rtx loc = mo->u.loc;
5641               rtx set_src = NULL;
5642
5643               if (GET_CODE (loc) == SET)
5644                 {
5645                   set_src = SET_SRC (loc);
5646                   loc = SET_DEST (loc);
5647                 }
5648
5649               if (REG_P (loc))
5650                 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5651                                         set_src);
5652               else if (MEM_P (loc))
5653                 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5654                                         set_src);
5655             }
5656             break;
5657
5658           case MO_COPY:
5659             {
5660               rtx loc = mo->u.loc;
5661               enum var_init_status src_status;
5662               rtx set_src = NULL;
5663
5664               if (GET_CODE (loc) == SET)
5665                 {
5666                   set_src = SET_SRC (loc);
5667                   loc = SET_DEST (loc);
5668                 }
5669
5670               if (! flag_var_tracking_uninit)
5671                 src_status = VAR_INIT_STATUS_INITIALIZED;
5672               else
5673                 {
5674                   src_status = find_src_status (in, set_src);
5675
5676                   if (src_status == VAR_INIT_STATUS_UNKNOWN)
5677                     src_status = find_src_status (out, set_src);
5678                 }
5679
5680               set_src = find_src_set_src (in, set_src);
5681
5682               if (REG_P (loc))
5683                 var_reg_delete_and_set (out, loc, false, src_status, set_src);
5684               else if (MEM_P (loc))
5685                 var_mem_delete_and_set (out, loc, false, src_status, set_src);
5686             }
5687             break;
5688
5689           case MO_USE_NO_VAR:
5690             {
5691               rtx loc = mo->u.loc;
5692
5693               if (REG_P (loc))
5694                 var_reg_delete (out, loc, false);
5695               else if (MEM_P (loc))
5696                 var_mem_delete (out, loc, false);
5697             }
5698             break;
5699
5700           case MO_CLOBBER:
5701             {
5702               rtx loc = mo->u.loc;
5703
5704               if (REG_P (loc))
5705                 var_reg_delete (out, loc, true);
5706               else if (MEM_P (loc))
5707                 var_mem_delete (out, loc, true);
5708             }
5709             break;
5710
5711           case MO_ADJUST:
5712             out->stack_adjust += mo->u.adjust;
5713             break;
5714         }
5715     }
5716
5717   if (MAY_HAVE_DEBUG_INSNS)
5718     {
5719       dataflow_set_equiv_regs (out);
5720       htab_traverse (shared_hash_htab (out->vars), canonicalize_values_mark,
5721                      out);
5722       htab_traverse (shared_hash_htab (out->vars), canonicalize_values_star,
5723                      out);
5724 #if ENABLE_CHECKING
5725       htab_traverse (shared_hash_htab (out->vars),
5726                      canonicalize_loc_order_check, out);
5727 #endif
5728     }
5729   changed = dataflow_set_different (&old_out, out);
5730   dataflow_set_destroy (&old_out);
5731   return changed;
5732 }
5733
5734 /* Find the locations of variables in the whole function.  */
5735
5736 static bool
5737 vt_find_locations (void)
5738 {
5739   fibheap_t worklist, pending, fibheap_swap;
5740   sbitmap visited, in_worklist, in_pending, sbitmap_swap;
5741   basic_block bb;
5742   edge e;
5743   int *bb_order;
5744   int *rc_order;
5745   int i;
5746   int htabsz = 0;
5747   int htabmax = PARAM_VALUE (PARAM_MAX_VARTRACK_SIZE);
5748   bool success = true;
5749
5750   /* Compute reverse completion order of depth first search of the CFG
5751      so that the data-flow runs faster.  */
5752   rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
5753   bb_order = XNEWVEC (int, last_basic_block);
5754   pre_and_rev_post_order_compute (NULL, rc_order, false);
5755   for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
5756     bb_order[rc_order[i]] = i;
5757   free (rc_order);
5758
5759   worklist = fibheap_new ();
5760   pending = fibheap_new ();
5761   visited = sbitmap_alloc (last_basic_block);
5762   in_worklist = sbitmap_alloc (last_basic_block);
5763   in_pending = sbitmap_alloc (last_basic_block);
5764   sbitmap_zero (in_worklist);
5765
5766   FOR_EACH_BB (bb)
5767     fibheap_insert (pending, bb_order[bb->index], bb);
5768   sbitmap_ones (in_pending);
5769
5770   while (success && !fibheap_empty (pending))
5771     {
5772       fibheap_swap = pending;
5773       pending = worklist;
5774       worklist = fibheap_swap;
5775       sbitmap_swap = in_pending;
5776       in_pending = in_worklist;
5777       in_worklist = sbitmap_swap;
5778
5779       sbitmap_zero (visited);
5780
5781       while (!fibheap_empty (worklist))
5782         {
5783           bb = (basic_block) fibheap_extract_min (worklist);
5784           RESET_BIT (in_worklist, bb->index);
5785           if (!TEST_BIT (visited, bb->index))
5786             {
5787               bool changed;
5788               edge_iterator ei;
5789               int oldinsz, oldoutsz;
5790
5791               SET_BIT (visited, bb->index);
5792
5793               if (VTI (bb)->in.vars)
5794                 {
5795                   htabsz
5796                     -= (htab_size (shared_hash_htab (VTI (bb)->in.vars))
5797                         + htab_size (shared_hash_htab (VTI (bb)->out.vars)));
5798                   oldinsz
5799                     = htab_elements (shared_hash_htab (VTI (bb)->in.vars));
5800                   oldoutsz
5801                     = htab_elements (shared_hash_htab (VTI (bb)->out.vars));
5802                 }
5803               else
5804                 oldinsz = oldoutsz = 0;
5805
5806               if (MAY_HAVE_DEBUG_INSNS)
5807                 {
5808                   dataflow_set *in = &VTI (bb)->in, *first_out = NULL;
5809                   bool first = true, adjust = false;
5810
5811                   /* Calculate the IN set as the intersection of
5812                      predecessor OUT sets.  */
5813
5814                   dataflow_set_clear (in);
5815                   dst_can_be_shared = true;
5816
5817                   FOR_EACH_EDGE (e, ei, bb->preds)
5818                     if (!VTI (e->src)->flooded)
5819                       gcc_assert (bb_order[bb->index]
5820                                   <= bb_order[e->src->index]);
5821                     else if (first)
5822                       {
5823                         dataflow_set_copy (in, &VTI (e->src)->out);
5824                         first_out = &VTI (e->src)->out;
5825                         first = false;
5826                       }
5827                     else
5828                       {
5829                         dataflow_set_merge (in, &VTI (e->src)->out);
5830                         adjust = true;
5831                       }
5832
5833                   if (adjust)
5834                     {
5835                       dataflow_post_merge_adjust (in, &VTI (bb)->permp);
5836 #if ENABLE_CHECKING
5837                       /* Merge and merge_adjust should keep entries in
5838                          canonical order.  */
5839                       htab_traverse (shared_hash_htab (in->vars),
5840                                      canonicalize_loc_order_check,
5841                                      in);
5842 #endif
5843                       if (dst_can_be_shared)
5844                         {
5845                           shared_hash_destroy (in->vars);
5846                           in->vars = shared_hash_copy (first_out->vars);
5847                         }
5848                     }
5849
5850                   VTI (bb)->flooded = true;
5851                 }
5852               else
5853                 {
5854                   /* Calculate the IN set as union of predecessor OUT sets.  */
5855                   dataflow_set_clear (&VTI (bb)->in);
5856                   FOR_EACH_EDGE (e, ei, bb->preds)
5857                     dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
5858                 }
5859
5860               changed = compute_bb_dataflow (bb);
5861               htabsz += (htab_size (shared_hash_htab (VTI (bb)->in.vars))
5862                          + htab_size (shared_hash_htab (VTI (bb)->out.vars)));
5863
5864               if (htabmax && htabsz > htabmax)
5865                 {
5866                   if (MAY_HAVE_DEBUG_INSNS)
5867                     inform (DECL_SOURCE_LOCATION (cfun->decl),
5868                             "variable tracking size limit exceeded with "
5869                             "-fvar-tracking-assignments, retrying without");
5870                   else
5871                     inform (DECL_SOURCE_LOCATION (cfun->decl),
5872                             "variable tracking size limit exceeded");
5873                   success = false;
5874                   break;
5875                 }
5876
5877               if (changed)
5878                 {
5879                   FOR_EACH_EDGE (e, ei, bb->succs)
5880                     {
5881                       if (e->dest == EXIT_BLOCK_PTR)
5882                         continue;
5883
5884                       if (TEST_BIT (visited, e->dest->index))
5885                         {
5886                           if (!TEST_BIT (in_pending, e->dest->index))
5887                             {
5888                               /* Send E->DEST to next round.  */
5889                               SET_BIT (in_pending, e->dest->index);
5890                               fibheap_insert (pending,
5891                                               bb_order[e->dest->index],
5892                                               e->dest);
5893                             }
5894                         }
5895                       else if (!TEST_BIT (in_worklist, e->dest->index))
5896                         {
5897                           /* Add E->DEST to current round.  */
5898                           SET_BIT (in_worklist, e->dest->index);
5899                           fibheap_insert (worklist, bb_order[e->dest->index],
5900                                           e->dest);
5901                         }
5902                     }
5903                 }
5904
5905               if (dump_file)
5906                 fprintf (dump_file,
5907                          "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n",
5908                          bb->index,
5909                          (int)htab_elements (shared_hash_htab (VTI (bb)->in.vars)),
5910                          oldinsz,
5911                          (int)htab_elements (shared_hash_htab (VTI (bb)->out.vars)),
5912                          oldoutsz,
5913                          (int)worklist->nodes, (int)pending->nodes, htabsz);
5914
5915               if (dump_file && (dump_flags & TDF_DETAILS))
5916                 {
5917                   fprintf (dump_file, "BB %i IN:\n", bb->index);
5918                   dump_dataflow_set (&VTI (bb)->in);
5919                   fprintf (dump_file, "BB %i OUT:\n", bb->index);
5920                   dump_dataflow_set (&VTI (bb)->out);
5921                 }
5922             }
5923         }
5924     }
5925
5926   if (success && MAY_HAVE_DEBUG_INSNS)
5927     FOR_EACH_BB (bb)
5928       gcc_assert (VTI (bb)->flooded);
5929
5930   free (bb_order);
5931   fibheap_delete (worklist);
5932   fibheap_delete (pending);
5933   sbitmap_free (visited);
5934   sbitmap_free (in_worklist);
5935   sbitmap_free (in_pending);
5936
5937   return success;
5938 }
5939
5940 /* Print the content of the LIST to dump file.  */
5941
5942 static void
5943 dump_attrs_list (attrs list)
5944 {
5945   for (; list; list = list->next)
5946     {
5947       if (dv_is_decl_p (list->dv))
5948         print_mem_expr (dump_file, dv_as_decl (list->dv));
5949       else
5950         print_rtl_single (dump_file, dv_as_value (list->dv));
5951       fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
5952     }
5953   fprintf (dump_file, "\n");
5954 }
5955
5956 /* Print the information about variable *SLOT to dump file.  */
5957
5958 static int
5959 dump_var_slot (void **slot, void *data ATTRIBUTE_UNUSED)
5960 {
5961   variable var = (variable) *slot;
5962
5963   dump_var (var);
5964
5965   /* Continue traversing the hash table.  */
5966   return 1;
5967 }
5968
5969 /* Print the information about variable VAR to dump file.  */
5970
5971 static void
5972 dump_var (variable var)
5973 {
5974   int i;
5975   location_chain node;
5976
5977   if (dv_is_decl_p (var->dv))
5978     {
5979       const_tree decl = dv_as_decl (var->dv);
5980
5981       if (DECL_NAME (decl))
5982         {
5983           fprintf (dump_file, "  name: %s",
5984                    IDENTIFIER_POINTER (DECL_NAME (decl)));
5985           if (dump_flags & TDF_UID)
5986             fprintf (dump_file, "D.%u", DECL_UID (decl));
5987         }
5988       else if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
5989         fprintf (dump_file, "  name: D#%u", DEBUG_TEMP_UID (decl));
5990       else
5991         fprintf (dump_file, "  name: D.%u", DECL_UID (decl));
5992       fprintf (dump_file, "\n");
5993     }
5994   else
5995     {
5996       fputc (' ', dump_file);
5997       print_rtl_single (dump_file, dv_as_value (var->dv));
5998     }
5999
6000   for (i = 0; i < var->n_var_parts; i++)
6001     {
6002       fprintf (dump_file, "    offset %ld\n",
6003                (long) var->var_part[i].offset);
6004       for (node = var->var_part[i].loc_chain; node; node = node->next)
6005         {
6006           fprintf (dump_file, "      ");
6007           if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
6008             fprintf (dump_file, "[uninit]");
6009           print_rtl_single (dump_file, node->loc);
6010         }
6011     }
6012 }
6013
6014 /* Print the information about variables from hash table VARS to dump file.  */
6015
6016 static void
6017 dump_vars (htab_t vars)
6018 {
6019   if (htab_elements (vars) > 0)
6020     {
6021       fprintf (dump_file, "Variables:\n");
6022       htab_traverse (vars, dump_var_slot, NULL);
6023     }
6024 }
6025
6026 /* Print the dataflow set SET to dump file.  */
6027
6028 static void
6029 dump_dataflow_set (dataflow_set *set)
6030 {
6031   int i;
6032
6033   fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
6034            set->stack_adjust);
6035   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
6036     {
6037       if (set->regs[i])
6038         {
6039           fprintf (dump_file, "Reg %d:", i);
6040           dump_attrs_list (set->regs[i]);
6041         }
6042     }
6043   dump_vars (shared_hash_htab (set->vars));
6044   fprintf (dump_file, "\n");
6045 }
6046
6047 /* Print the IN and OUT sets for each basic block to dump file.  */
6048
6049 static void
6050 dump_dataflow_sets (void)
6051 {
6052   basic_block bb;
6053
6054   FOR_EACH_BB (bb)
6055     {
6056       fprintf (dump_file, "\nBasic block %d:\n", bb->index);
6057       fprintf (dump_file, "IN:\n");
6058       dump_dataflow_set (&VTI (bb)->in);
6059       fprintf (dump_file, "OUT:\n");
6060       dump_dataflow_set (&VTI (bb)->out);
6061     }
6062 }
6063
6064 /* Add variable VAR to the hash table of changed variables and
6065    if it has no locations delete it from SET's hash table.  */
6066
6067 static void
6068 variable_was_changed (variable var, dataflow_set *set)
6069 {
6070   hashval_t hash = dv_htab_hash (var->dv);
6071
6072   if (emit_notes)
6073     {
6074       void **slot;
6075       bool old_cur_loc_changed = false;
6076
6077       /* Remember this decl or VALUE has been added to changed_variables.  */
6078       set_dv_changed (var->dv, true);
6079
6080       slot = htab_find_slot_with_hash (changed_variables,
6081                                        var->dv,
6082                                        hash, INSERT);
6083
6084       if (*slot)
6085         {
6086           variable old_var = (variable) *slot;
6087           gcc_assert (old_var->in_changed_variables);
6088           old_var->in_changed_variables = false;
6089           old_cur_loc_changed = old_var->cur_loc_changed;
6090           variable_htab_free (*slot);
6091         }
6092       if (set && var->n_var_parts == 0)
6093         {
6094           variable empty_var;
6095
6096           empty_var = (variable) pool_alloc (dv_pool (var->dv));
6097           empty_var->dv = var->dv;
6098           empty_var->refcount = 1;
6099           empty_var->n_var_parts = 0;
6100           empty_var->cur_loc_changed = true;
6101           empty_var->in_changed_variables = true;
6102           *slot = empty_var;
6103           goto drop_var;
6104         }
6105       else
6106         {
6107           var->refcount++;
6108           var->in_changed_variables = true;
6109           /* If within processing one uop a variable is deleted
6110              and then readded, we need to assume it has changed.  */
6111           if (old_cur_loc_changed)
6112             var->cur_loc_changed = true;
6113           *slot = var;
6114         }
6115     }
6116   else
6117     {
6118       gcc_assert (set);
6119       if (var->n_var_parts == 0)
6120         {
6121           void **slot;
6122
6123         drop_var:
6124           slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
6125           if (slot)
6126             {
6127               if (shared_hash_shared (set->vars))
6128                 slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
6129                                                       NO_INSERT);
6130               htab_clear_slot (shared_hash_htab (set->vars), slot);
6131             }
6132         }
6133     }
6134 }
6135
6136 /* Look for the index in VAR->var_part corresponding to OFFSET.
6137    Return -1 if not found.  If INSERTION_POINT is non-NULL, the
6138    referenced int will be set to the index that the part has or should
6139    have, if it should be inserted.  */
6140
6141 static inline int
6142 find_variable_location_part (variable var, HOST_WIDE_INT offset,
6143                              int *insertion_point)
6144 {
6145   int pos, low, high;
6146
6147   /* Find the location part.  */
6148   low = 0;
6149   high = var->n_var_parts;
6150   while (low != high)
6151     {
6152       pos = (low + high) / 2;
6153       if (var->var_part[pos].offset < offset)
6154         low = pos + 1;
6155       else
6156         high = pos;
6157     }
6158   pos = low;
6159
6160   if (insertion_point)
6161     *insertion_point = pos;
6162
6163   if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
6164     return pos;
6165
6166   return -1;
6167 }
6168
6169 static void **
6170 set_slot_part (dataflow_set *set, rtx loc, void **slot,
6171                decl_or_value dv, HOST_WIDE_INT offset,
6172                enum var_init_status initialized, rtx set_src)
6173 {
6174   int pos;
6175   location_chain node, next;
6176   location_chain *nextp;
6177   variable var;
6178   bool onepart = dv_onepart_p (dv);
6179
6180   gcc_assert (offset == 0 || !onepart);
6181   gcc_assert (loc != dv_as_opaque (dv));
6182
6183   var = (variable) *slot;
6184
6185   if (! flag_var_tracking_uninit)
6186     initialized = VAR_INIT_STATUS_INITIALIZED;
6187
6188   if (!var)
6189     {
6190       /* Create new variable information.  */
6191       var = (variable) pool_alloc (dv_pool (dv));
6192       var->dv = dv;
6193       var->refcount = 1;
6194       var->n_var_parts = 1;
6195       var->cur_loc_changed = false;
6196       var->in_changed_variables = false;
6197       var->var_part[0].offset = offset;
6198       var->var_part[0].loc_chain = NULL;
6199       var->var_part[0].cur_loc = NULL;
6200       *slot = var;
6201       pos = 0;
6202       nextp = &var->var_part[0].loc_chain;
6203     }
6204   else if (onepart)
6205     {
6206       int r = -1, c = 0;
6207
6208       gcc_assert (dv_as_opaque (var->dv) == dv_as_opaque (dv));
6209
6210       pos = 0;
6211
6212       if (GET_CODE (loc) == VALUE)
6213         {
6214           for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6215                nextp = &node->next)
6216             if (GET_CODE (node->loc) == VALUE)
6217               {
6218                 if (node->loc == loc)
6219                   {
6220                     r = 0;
6221                     break;
6222                   }
6223                 if (canon_value_cmp (node->loc, loc))
6224                   c++;
6225                 else
6226                   {
6227                     r = 1;
6228                     break;
6229                   }
6230               }
6231             else if (REG_P (node->loc) || MEM_P (node->loc))
6232               c++;
6233             else
6234               {
6235                 r = 1;
6236                 break;
6237               }
6238         }
6239       else if (REG_P (loc))
6240         {
6241           for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6242                nextp = &node->next)
6243             if (REG_P (node->loc))
6244               {
6245                 if (REGNO (node->loc) < REGNO (loc))
6246                   c++;
6247                 else
6248                   {
6249                     if (REGNO (node->loc) == REGNO (loc))
6250                       r = 0;
6251                     else
6252                       r = 1;
6253                     break;
6254                   }
6255               }
6256             else
6257               {
6258                 r = 1;
6259                 break;
6260               }
6261         }
6262       else if (MEM_P (loc))
6263         {
6264           for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6265                nextp = &node->next)
6266             if (REG_P (node->loc))
6267               c++;
6268             else if (MEM_P (node->loc))
6269               {
6270                 if ((r = loc_cmp (XEXP (node->loc, 0), XEXP (loc, 0))) >= 0)
6271                   break;
6272                 else
6273                   c++;
6274               }
6275             else
6276               {
6277                 r = 1;
6278                 break;
6279               }
6280         }
6281       else
6282         for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6283              nextp = &node->next)
6284           if ((r = loc_cmp (node->loc, loc)) >= 0)
6285             break;
6286           else
6287             c++;
6288
6289       if (r == 0)
6290         return slot;
6291
6292       if (shared_var_p (var, set->vars))
6293         {
6294           slot = unshare_variable (set, slot, var, initialized);
6295           var = (variable)*slot;
6296           for (nextp = &var->var_part[0].loc_chain; c;
6297                nextp = &(*nextp)->next)
6298             c--;
6299           gcc_assert ((!node && !*nextp) || node->loc == (*nextp)->loc);
6300         }
6301     }
6302   else
6303     {
6304       int inspos = 0;
6305
6306       gcc_assert (dv_as_decl (var->dv) == dv_as_decl (dv));
6307
6308       pos = find_variable_location_part (var, offset, &inspos);
6309
6310       if (pos >= 0)
6311         {
6312           node = var->var_part[pos].loc_chain;
6313
6314           if (node
6315               && ((REG_P (node->loc) && REG_P (loc)
6316                    && REGNO (node->loc) == REGNO (loc))
6317                   || rtx_equal_p (node->loc, loc)))
6318             {
6319               /* LOC is in the beginning of the chain so we have nothing
6320                  to do.  */
6321               if (node->init < initialized)
6322                 node->init = initialized;
6323               if (set_src != NULL)
6324                 node->set_src = set_src;
6325
6326               return slot;
6327             }
6328           else
6329             {
6330               /* We have to make a copy of a shared variable.  */
6331               if (shared_var_p (var, set->vars))
6332                 {
6333                   slot = unshare_variable (set, slot, var, initialized);
6334                   var = (variable)*slot;
6335                 }
6336             }
6337         }
6338       else
6339         {
6340           /* We have not found the location part, new one will be created.  */
6341
6342           /* We have to make a copy of the shared variable.  */
6343           if (shared_var_p (var, set->vars))
6344             {
6345               slot = unshare_variable (set, slot, var, initialized);
6346               var = (variable)*slot;
6347             }
6348
6349           /* We track only variables whose size is <= MAX_VAR_PARTS bytes
6350              thus there are at most MAX_VAR_PARTS different offsets.  */
6351           gcc_assert (var->n_var_parts < MAX_VAR_PARTS
6352                       && (!var->n_var_parts || !dv_onepart_p (var->dv)));
6353
6354           /* We have to move the elements of array starting at index
6355              inspos to the next position.  */
6356           for (pos = var->n_var_parts; pos > inspos; pos--)
6357             var->var_part[pos] = var->var_part[pos - 1];
6358
6359           var->n_var_parts++;
6360           var->var_part[pos].offset = offset;
6361           var->var_part[pos].loc_chain = NULL;
6362           var->var_part[pos].cur_loc = NULL;
6363         }
6364
6365       /* Delete the location from the list.  */
6366       nextp = &var->var_part[pos].loc_chain;
6367       for (node = var->var_part[pos].loc_chain; node; node = next)
6368         {
6369           next = node->next;
6370           if ((REG_P (node->loc) && REG_P (loc)
6371                && REGNO (node->loc) == REGNO (loc))
6372               || rtx_equal_p (node->loc, loc))
6373             {
6374               /* Save these values, to assign to the new node, before
6375                  deleting this one.  */
6376               if (node->init > initialized)
6377                 initialized = node->init;
6378               if (node->set_src != NULL && set_src == NULL)
6379                 set_src = node->set_src;
6380               if (var->var_part[pos].cur_loc == node->loc)
6381                 {
6382                   var->var_part[pos].cur_loc = NULL;
6383                   var->cur_loc_changed = true;
6384                 }
6385               pool_free (loc_chain_pool, node);
6386               *nextp = next;
6387               break;
6388             }
6389           else
6390             nextp = &node->next;
6391         }
6392
6393       nextp = &var->var_part[pos].loc_chain;
6394     }
6395
6396   /* Add the location to the beginning.  */
6397   node = (location_chain) pool_alloc (loc_chain_pool);
6398   node->loc = loc;
6399   node->init = initialized;
6400   node->set_src = set_src;
6401   node->next = *nextp;
6402   *nextp = node;
6403
6404   if (onepart && emit_notes)
6405     add_value_chains (var->dv, loc);
6406
6407   /* If no location was emitted do so.  */
6408   if (var->var_part[pos].cur_loc == NULL)
6409     variable_was_changed (var, set);
6410
6411   return slot;
6412 }
6413
6414 /* Set the part of variable's location in the dataflow set SET.  The
6415    variable part is specified by variable's declaration in DV and
6416    offset OFFSET and the part's location by LOC.  IOPT should be
6417    NO_INSERT if the variable is known to be in SET already and the
6418    variable hash table must not be resized, and INSERT otherwise.  */
6419
6420 static void
6421 set_variable_part (dataflow_set *set, rtx loc,
6422                    decl_or_value dv, HOST_WIDE_INT offset,
6423                    enum var_init_status initialized, rtx set_src,
6424                    enum insert_option iopt)
6425 {
6426   void **slot;
6427
6428   if (iopt == NO_INSERT)
6429     slot = shared_hash_find_slot_noinsert (set->vars, dv);
6430   else
6431     {
6432       slot = shared_hash_find_slot (set->vars, dv);
6433       if (!slot)
6434         slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt);
6435     }
6436   slot = set_slot_part (set, loc, slot, dv, offset, initialized, set_src);
6437 }
6438
6439 /* Remove all recorded register locations for the given variable part
6440    from dataflow set SET, except for those that are identical to loc.
6441    The variable part is specified by variable's declaration or value
6442    DV and offset OFFSET.  */
6443
6444 static void **
6445 clobber_slot_part (dataflow_set *set, rtx loc, void **slot,
6446                    HOST_WIDE_INT offset, rtx set_src)
6447 {
6448   variable var = (variable) *slot;
6449   int pos = find_variable_location_part (var, offset, NULL);
6450
6451   if (pos >= 0)
6452     {
6453       location_chain node, next;
6454
6455       /* Remove the register locations from the dataflow set.  */
6456       next = var->var_part[pos].loc_chain;
6457       for (node = next; node; node = next)
6458         {
6459           next = node->next;
6460           if (node->loc != loc
6461               && (!flag_var_tracking_uninit
6462                   || !set_src
6463                   || MEM_P (set_src)
6464                   || !rtx_equal_p (set_src, node->set_src)))
6465             {
6466               if (REG_P (node->loc))
6467                 {
6468                   attrs anode, anext;
6469                   attrs *anextp;
6470
6471                   /* Remove the variable part from the register's
6472                      list, but preserve any other variable parts
6473                      that might be regarded as live in that same
6474                      register.  */
6475                   anextp = &set->regs[REGNO (node->loc)];
6476                   for (anode = *anextp; anode; anode = anext)
6477                     {
6478                       anext = anode->next;
6479                       if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
6480                           && anode->offset == offset)
6481                         {
6482                           pool_free (attrs_pool, anode);
6483                           *anextp = anext;
6484                         }
6485                       else
6486                         anextp = &anode->next;
6487                     }
6488                 }
6489
6490               slot = delete_slot_part (set, node->loc, slot, offset);
6491             }
6492         }
6493     }
6494
6495   return slot;
6496 }
6497
6498 /* Remove all recorded register locations for the given variable part
6499    from dataflow set SET, except for those that are identical to loc.
6500    The variable part is specified by variable's declaration or value
6501    DV and offset OFFSET.  */
6502
6503 static void
6504 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6505                        HOST_WIDE_INT offset, rtx set_src)
6506 {
6507   void **slot;
6508
6509   if (!dv_as_opaque (dv)
6510       || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
6511     return;
6512
6513   slot = shared_hash_find_slot_noinsert (set->vars, dv);
6514   if (!slot)
6515     return;
6516
6517   slot = clobber_slot_part (set, loc, slot, offset, set_src);
6518 }
6519
6520 /* Delete the part of variable's location from dataflow set SET.  The
6521    variable part is specified by its SET->vars slot SLOT and offset
6522    OFFSET and the part's location by LOC.  */
6523
6524 static void **
6525 delete_slot_part (dataflow_set *set, rtx loc, void **slot,
6526                   HOST_WIDE_INT offset)
6527 {
6528   variable var = (variable) *slot;
6529   int pos = find_variable_location_part (var, offset, NULL);
6530
6531   if (pos >= 0)
6532     {
6533       location_chain node, next;
6534       location_chain *nextp;
6535       bool changed;
6536
6537       if (shared_var_p (var, set->vars))
6538         {
6539           /* If the variable contains the location part we have to
6540              make a copy of the variable.  */
6541           for (node = var->var_part[pos].loc_chain; node;
6542                node = node->next)
6543             {
6544               if ((REG_P (node->loc) && REG_P (loc)
6545                    && REGNO (node->loc) == REGNO (loc))
6546                   || rtx_equal_p (node->loc, loc))
6547                 {
6548                   slot = unshare_variable (set, slot, var,
6549                                            VAR_INIT_STATUS_UNKNOWN);
6550                   var = (variable)*slot;
6551                   break;
6552                 }
6553             }
6554         }
6555
6556       /* Delete the location part.  */
6557       changed = false;
6558       nextp = &var->var_part[pos].loc_chain;
6559       for (node = *nextp; node; node = next)
6560         {
6561           next = node->next;
6562           if ((REG_P (node->loc) && REG_P (loc)
6563                && REGNO (node->loc) == REGNO (loc))
6564               || rtx_equal_p (node->loc, loc))
6565             {
6566               if (emit_notes && pos == 0 && dv_onepart_p (var->dv))
6567                 remove_value_chains (var->dv, node->loc);
6568               /* If we have deleted the location which was last emitted
6569                  we have to emit new location so add the variable to set
6570                  of changed variables.  */
6571               if (var->var_part[pos].cur_loc == node->loc)
6572                 {
6573                   changed = true;
6574                   var->var_part[pos].cur_loc = NULL;
6575                   var->cur_loc_changed = true;
6576                 }
6577               pool_free (loc_chain_pool, node);
6578               *nextp = next;
6579               break;
6580             }
6581           else
6582             nextp = &node->next;
6583         }
6584
6585       if (var->var_part[pos].loc_chain == NULL)
6586         {
6587           changed = true;
6588           var->n_var_parts--;
6589           if (emit_notes)
6590             var->cur_loc_changed = true;
6591           while (pos < var->n_var_parts)
6592             {
6593               var->var_part[pos] = var->var_part[pos + 1];
6594               pos++;
6595             }
6596         }
6597       if (changed)
6598         variable_was_changed (var, set);
6599     }
6600
6601   return slot;
6602 }
6603
6604 /* Delete the part of variable's location from dataflow set SET.  The
6605    variable part is specified by variable's declaration or value DV
6606    and offset OFFSET and the part's location by LOC.  */
6607
6608 static void
6609 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6610                       HOST_WIDE_INT offset)
6611 {
6612   void **slot = shared_hash_find_slot_noinsert (set->vars, dv);
6613   if (!slot)
6614     return;
6615
6616   slot = delete_slot_part (set, loc, slot, offset);
6617 }
6618
6619 /* Structure for passing some other parameters to function
6620    vt_expand_loc_callback.  */
6621 struct expand_loc_callback_data
6622 {
6623   /* The variables and values active at this point.  */
6624   htab_t vars;
6625
6626   /* True in vt_expand_loc_dummy calls, no rtl should be allocated.
6627      Non-NULL should be returned if vt_expand_loc would return
6628      non-NULL in that case, NULL otherwise.  cur_loc_changed should be
6629      computed and cur_loc recomputed when possible (but just once
6630      per emit_notes_for_changes call).  */
6631   bool dummy;
6632
6633   /* True if expansion of subexpressions had to recompute some
6634      VALUE/DEBUG_EXPR_DECL's cur_loc or used a VALUE/DEBUG_EXPR_DECL
6635      whose cur_loc has been already recomputed during current
6636      emit_notes_for_changes call.  */
6637   bool cur_loc_changed;
6638 };
6639
6640 /* Callback for cselib_expand_value, that looks for expressions
6641    holding the value in the var-tracking hash tables.  Return X for
6642    standard processing, anything else is to be used as-is.  */
6643
6644 static rtx
6645 vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
6646 {
6647   struct expand_loc_callback_data *elcd
6648     = (struct expand_loc_callback_data *) data;
6649   bool dummy = elcd->dummy;
6650   bool cur_loc_changed = elcd->cur_loc_changed;
6651   decl_or_value dv;
6652   variable var;
6653   location_chain loc;
6654   rtx result, subreg, xret;
6655
6656   switch (GET_CODE (x))
6657     {
6658     case SUBREG:
6659       if (dummy)
6660         {
6661           if (cselib_dummy_expand_value_rtx_cb (SUBREG_REG (x), regs,
6662                                                 max_depth - 1,
6663                                                 vt_expand_loc_callback, data))
6664             return pc_rtx;
6665           else
6666             return NULL;
6667         }
6668
6669       subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
6670                                            max_depth - 1,
6671                                            vt_expand_loc_callback, data);
6672
6673       if (!subreg)
6674         return NULL;
6675
6676       result = simplify_gen_subreg (GET_MODE (x), subreg,
6677                                     GET_MODE (SUBREG_REG (x)),
6678                                     SUBREG_BYTE (x));
6679
6680       /* Invalid SUBREGs are ok in debug info.  ??? We could try
6681          alternate expansions for the VALUE as well.  */
6682       if (!result)
6683         result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
6684
6685       return result;
6686
6687     case DEBUG_EXPR:
6688       dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
6689       xret = NULL;
6690       break;
6691
6692     case VALUE:
6693       dv = dv_from_value (x);
6694       xret = x;
6695       break;
6696
6697     default:
6698       return x;
6699     }
6700
6701   if (VALUE_RECURSED_INTO (x))
6702     return NULL;
6703
6704   var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv));
6705
6706   if (!var)
6707     {
6708       if (dummy && dv_changed_p (dv))
6709         elcd->cur_loc_changed = true;
6710       return xret;
6711     }
6712
6713   if (var->n_var_parts == 0)
6714     {
6715       if (dummy)
6716         elcd->cur_loc_changed = true;
6717       return xret;
6718     }
6719
6720   gcc_assert (var->n_var_parts == 1);
6721
6722   VALUE_RECURSED_INTO (x) = true;
6723   result = NULL;
6724
6725   if (var->var_part[0].cur_loc)
6726     {
6727       if (dummy)
6728         {
6729           if (cselib_dummy_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
6730                                                 max_depth,
6731                                                 vt_expand_loc_callback, data))
6732             result = pc_rtx;
6733         }
6734       else
6735         result = cselib_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
6736                                              max_depth,
6737                                              vt_expand_loc_callback, data);
6738       if (result)
6739         set_dv_changed (dv, false);
6740     }
6741   if (!result && dv_changed_p (dv))
6742     {
6743       set_dv_changed (dv, false);
6744       for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
6745         if (loc->loc == var->var_part[0].cur_loc)
6746           continue;
6747         else if (dummy)
6748           {
6749             elcd->cur_loc_changed = cur_loc_changed;
6750             if (cselib_dummy_expand_value_rtx_cb (loc->loc, regs, max_depth,
6751                                                   vt_expand_loc_callback,
6752                                                   data))
6753               {
6754                 result = pc_rtx;
6755                 break;
6756               }
6757             else
6758               {
6759                 result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
6760                                                      vt_expand_loc_callback,
6761                                                      data);
6762                 if (result)
6763                   break;
6764               }
6765           }
6766       if (dummy && (result || var->var_part[0].cur_loc))
6767         var->cur_loc_changed = true;
6768       var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
6769     }
6770   if (dummy)
6771     {
6772       if (var->cur_loc_changed)
6773         elcd->cur_loc_changed = true;
6774       else if (!result && var->var_part[0].cur_loc == NULL_RTX)
6775         elcd->cur_loc_changed = cur_loc_changed;
6776     }
6777
6778   VALUE_RECURSED_INTO (x) = false;
6779   if (result)
6780     return result;
6781   else
6782     return xret;
6783 }
6784
6785 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
6786    tables.  */
6787
6788 static rtx
6789 vt_expand_loc (rtx loc, htab_t vars)
6790 {
6791   struct expand_loc_callback_data data;
6792
6793   if (!MAY_HAVE_DEBUG_INSNS)
6794     return loc;
6795
6796   data.vars = vars;
6797   data.dummy = false;
6798   data.cur_loc_changed = false;
6799   loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
6800                                     vt_expand_loc_callback, &data);
6801
6802   if (loc && MEM_P (loc))
6803     loc = targetm.delegitimize_address (loc);
6804   return loc;
6805 }
6806
6807 /* Like vt_expand_loc, but only return true/false (whether vt_expand_loc
6808    would succeed or not, without actually allocating new rtxes.  */
6809
6810 static bool
6811 vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
6812 {
6813   struct expand_loc_callback_data data;
6814   bool ret;
6815
6816   gcc_assert (MAY_HAVE_DEBUG_INSNS);
6817   data.vars = vars;
6818   data.dummy = true;
6819   data.cur_loc_changed = false;
6820   ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 5,
6821                                           vt_expand_loc_callback, &data);
6822   *pcur_loc_changed = data.cur_loc_changed;
6823   return ret;
6824 }
6825
6826 #ifdef ENABLE_RTL_CHECKING
6827 /* Used to verify that cur_loc_changed updating is safe.  */
6828 static struct pointer_map_t *emitted_notes;
6829 #endif
6830
6831 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP.  DATA contains
6832    additional parameters: WHERE specifies whether the note shall be emitted
6833    before or after instruction INSN.  */
6834
6835 static int
6836 emit_note_insn_var_location (void **varp, void *data)
6837 {
6838   variable var = (variable) *varp;
6839   rtx insn = ((emit_note_data *)data)->insn;
6840   enum emit_note_where where = ((emit_note_data *)data)->where;
6841   htab_t vars = ((emit_note_data *)data)->vars;
6842   rtx note, note_vl;
6843   int i, j, n_var_parts;
6844   bool complete;
6845   enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
6846   HOST_WIDE_INT last_limit;
6847   tree type_size_unit;
6848   HOST_WIDE_INT offsets[MAX_VAR_PARTS];
6849   rtx loc[MAX_VAR_PARTS];
6850   tree decl;
6851   location_chain lc;
6852
6853   if (dv_is_value_p (var->dv))
6854     goto value_or_debug_decl;
6855
6856   decl = dv_as_decl (var->dv);
6857
6858   if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
6859     goto value_or_debug_decl;
6860
6861   complete = true;
6862   last_limit = 0;
6863   n_var_parts = 0;
6864   if (!MAY_HAVE_DEBUG_INSNS)
6865     {
6866       for (i = 0; i < var->n_var_parts; i++)
6867         if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
6868           {
6869             var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
6870             var->cur_loc_changed = true;
6871           }
6872       if (var->n_var_parts == 0)
6873         var->cur_loc_changed = true;
6874     }
6875 #ifndef ENABLE_RTL_CHECKING
6876   if (!var->cur_loc_changed)
6877     goto clear;
6878 #endif
6879   for (i = 0; i < var->n_var_parts; i++)
6880     {
6881       enum machine_mode mode, wider_mode;
6882       rtx loc2;
6883
6884       if (last_limit < var->var_part[i].offset)
6885         {
6886           complete = false;
6887           break;
6888         }
6889       else if (last_limit > var->var_part[i].offset)
6890         continue;
6891       offsets[n_var_parts] = var->var_part[i].offset;
6892       if (!var->var_part[i].cur_loc)
6893         {
6894           complete = false;
6895           continue;
6896         }
6897       loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars);
6898       if (!loc2)
6899         {
6900           complete = false;
6901           continue;
6902         }
6903       loc[n_var_parts] = loc2;
6904       mode = GET_MODE (var->var_part[i].cur_loc);
6905       for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
6906         if (var->var_part[i].cur_loc == lc->loc)
6907           {
6908             initialized = lc->init;
6909             break;
6910           }
6911       gcc_assert (lc);
6912       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
6913
6914       /* Attempt to merge adjacent registers or memory.  */
6915       wider_mode = GET_MODE_WIDER_MODE (mode);
6916       for (j = i + 1; j < var->n_var_parts; j++)
6917         if (last_limit <= var->var_part[j].offset)
6918           break;
6919       if (j < var->n_var_parts
6920           && wider_mode != VOIDmode
6921           && var->var_part[j].cur_loc
6922           && mode == GET_MODE (var->var_part[j].cur_loc)
6923           && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
6924           && last_limit == var->var_part[j].offset
6925           && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
6926           && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
6927         {
6928           rtx new_loc = NULL;
6929
6930           if (REG_P (loc[n_var_parts])
6931               && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
6932                  == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
6933               && end_hard_regno (mode, REGNO (loc[n_var_parts]))
6934                  == REGNO (loc2))
6935             {
6936               if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
6937                 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
6938                                            mode, 0);
6939               else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
6940                 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
6941               if (new_loc)
6942                 {
6943                   if (!REG_P (new_loc)
6944                       || REGNO (new_loc) != REGNO (loc[n_var_parts]))
6945                     new_loc = NULL;
6946                   else
6947                     REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
6948                 }
6949             }
6950           else if (MEM_P (loc[n_var_parts])
6951                    && GET_CODE (XEXP (loc2, 0)) == PLUS
6952                    && REG_P (XEXP (XEXP (loc2, 0), 0))
6953                    && CONST_INT_P (XEXP (XEXP (loc2, 0), 1)))
6954             {
6955               if ((REG_P (XEXP (loc[n_var_parts], 0))
6956                    && rtx_equal_p (XEXP (loc[n_var_parts], 0),
6957                                    XEXP (XEXP (loc2, 0), 0))
6958                    && INTVAL (XEXP (XEXP (loc2, 0), 1))
6959                       == GET_MODE_SIZE (mode))
6960                   || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
6961                       && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1))
6962                       && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
6963                                       XEXP (XEXP (loc2, 0), 0))
6964                       && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
6965                          + GET_MODE_SIZE (mode)
6966                          == INTVAL (XEXP (XEXP (loc2, 0), 1))))
6967                 new_loc = adjust_address_nv (loc[n_var_parts],
6968                                              wider_mode, 0);
6969             }
6970
6971           if (new_loc)
6972             {
6973               loc[n_var_parts] = new_loc;
6974               mode = wider_mode;
6975               last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
6976               i = j;
6977             }
6978         }
6979       ++n_var_parts;
6980     }
6981   type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl));
6982   if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
6983     complete = false;
6984
6985   if (! flag_var_tracking_uninit)
6986     initialized = VAR_INIT_STATUS_INITIALIZED;
6987
6988   note_vl = NULL_RTX;
6989   if (!complete)
6990     note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX,
6991                                     (int) initialized);
6992   else if (n_var_parts == 1)
6993     {
6994       rtx expr_list
6995         = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
6996
6997       note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list,
6998                                       (int) initialized);
6999     }
7000   else if (n_var_parts)
7001     {
7002       rtx parallel;
7003
7004       for (i = 0; i < n_var_parts; i++)
7005         loc[i]
7006           = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
7007
7008       parallel = gen_rtx_PARALLEL (VOIDmode,
7009                                    gen_rtvec_v (n_var_parts, loc));
7010       note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl,
7011                                       parallel, (int) initialized);
7012     }
7013
7014 #ifdef ENABLE_RTL_CHECKING
7015   if (note_vl)
7016     {
7017       void **note_slot = pointer_map_insert (emitted_notes, decl);
7018       rtx pnote = (rtx) *note_slot;
7019       if (!var->cur_loc_changed && (pnote || PAT_VAR_LOCATION_LOC (note_vl)))
7020         {
7021           gcc_assert (pnote);
7022           gcc_assert (rtx_equal_p (PAT_VAR_LOCATION_LOC (pnote),
7023                                    PAT_VAR_LOCATION_LOC (note_vl)));
7024         }
7025       *note_slot = (void *) note_vl;
7026     }
7027   if (!var->cur_loc_changed)
7028     goto clear;
7029 #endif
7030
7031   if (where != EMIT_NOTE_BEFORE_INSN)
7032     {
7033       note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
7034       if (where == EMIT_NOTE_AFTER_CALL_INSN)
7035         NOTE_DURING_CALL_P (note) = true;
7036     }
7037   else
7038     note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
7039   NOTE_VAR_LOCATION (note) = note_vl;
7040
7041  clear:
7042   set_dv_changed (var->dv, false);
7043   var->cur_loc_changed = false;
7044   gcc_assert (var->in_changed_variables);
7045   var->in_changed_variables = false;
7046   htab_clear_slot (changed_variables, varp);
7047
7048   /* Continue traversing the hash table.  */
7049   return 1;
7050
7051  value_or_debug_decl:
7052   if (dv_changed_p (var->dv) && var->n_var_parts)
7053     {
7054       location_chain lc;
7055       bool cur_loc_changed;
7056
7057       if (var->var_part[0].cur_loc
7058           && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars,
7059                                   &cur_loc_changed))
7060         goto clear;
7061       for (lc = var->var_part[0].loc_chain; lc; lc = lc->next)
7062         if (lc->loc != var->var_part[0].cur_loc
7063             && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
7064           break;
7065       var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX;
7066     }
7067   goto clear;
7068 }
7069
7070 DEF_VEC_P (variable);
7071 DEF_VEC_ALLOC_P (variable, heap);
7072
7073 /* Stack of variable_def pointers that need processing with
7074    check_changed_vars_2.  */
7075
7076 static VEC (variable, heap) *changed_variables_stack;
7077
7078 /* VALUEs with no variables that need set_dv_changed (val, false)
7079    called before check_changed_vars_3.  */
7080
7081 static VEC (rtx, heap) *changed_values_stack;
7082
7083 /* Helper function for check_changed_vars_1 and check_changed_vars_2.  */
7084
7085 static void
7086 check_changed_vars_0 (decl_or_value dv, htab_t htab)
7087 {
7088   value_chain vc
7089     = (value_chain) htab_find_with_hash (value_chains, dv, dv_htab_hash (dv));
7090
7091   if (vc == NULL)
7092     return;
7093   for (vc = vc->next; vc; vc = vc->next)
7094     if (!dv_changed_p (vc->dv))
7095       {
7096         variable vcvar
7097           = (variable) htab_find_with_hash (htab, vc->dv,
7098                                             dv_htab_hash (vc->dv));
7099         if (vcvar)
7100           {
7101             set_dv_changed (vc->dv, true);
7102             VEC_safe_push (variable, heap, changed_variables_stack, vcvar);
7103           }
7104         else if (dv_is_value_p (vc->dv))
7105           {
7106             set_dv_changed (vc->dv, true);
7107             VEC_safe_push (rtx, heap, changed_values_stack,
7108                            dv_as_value (vc->dv));
7109             check_changed_vars_0 (vc->dv, htab);
7110           }
7111       }
7112 }
7113
7114 /* Populate changed_variables_stack with variable_def pointers
7115    that need variable_was_changed called on them.  */
7116
7117 static int
7118 check_changed_vars_1 (void **slot, void *data)
7119 {
7120   variable var = (variable) *slot;
7121   htab_t htab = (htab_t) data;
7122
7123   if (dv_is_value_p (var->dv)
7124       || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7125     check_changed_vars_0 (var->dv, htab);
7126   return 1;
7127 }
7128
7129 /* Add VAR to changed_variables and also for VALUEs add recursively
7130    all DVs that aren't in changed_variables yet but reference the
7131    VALUE from its loc_chain.  */
7132
7133 static void
7134 check_changed_vars_2 (variable var, htab_t htab)
7135 {
7136   variable_was_changed (var, NULL);
7137   if (dv_is_value_p (var->dv)
7138       || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7139     check_changed_vars_0 (var->dv, htab);
7140 }
7141
7142 /* For each changed decl (except DEBUG_EXPR_DECLs) recompute
7143    cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs
7144    it needs and are also in changed variables) and track whether
7145    cur_loc (or anything it uses to compute location) had to change
7146    during the current emit_notes_for_changes call.  */
7147
7148 static int
7149 check_changed_vars_3 (void **slot, void *data)
7150 {
7151   variable var = (variable) *slot;
7152   htab_t vars = (htab_t) data;
7153   int i;
7154   location_chain lc;
7155   bool cur_loc_changed;
7156
7157   if (dv_is_value_p (var->dv)
7158       || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7159     return 1;
7160
7161   for (i = 0; i < var->n_var_parts; i++)
7162     {
7163       if (var->var_part[i].cur_loc
7164           && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars,
7165                                   &cur_loc_changed))
7166         {
7167           if (cur_loc_changed)
7168             var->cur_loc_changed = true;
7169           continue;
7170         }
7171       for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
7172         if (lc->loc != var->var_part[i].cur_loc
7173             && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
7174           break;
7175       if (lc || var->var_part[i].cur_loc)
7176         var->cur_loc_changed = true;
7177       var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX;
7178     }
7179   if (var->n_var_parts == 0)
7180     var->cur_loc_changed = true;
7181   return 1;
7182 }
7183
7184 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
7185    CHANGED_VARIABLES and delete this chain.  WHERE specifies whether the notes
7186    shall be emitted before of after instruction INSN.  */
7187
7188 static void
7189 emit_notes_for_changes (rtx insn, enum emit_note_where where,
7190                         shared_hash vars)
7191 {
7192   emit_note_data data;
7193   htab_t htab = shared_hash_htab (vars);
7194
7195   if (!htab_elements (changed_variables))
7196     return;
7197
7198   if (MAY_HAVE_DEBUG_INSNS)
7199     {
7200       /* Unfortunately this has to be done in two steps, because
7201          we can't traverse a hashtab into which we are inserting
7202          through variable_was_changed.  */
7203       htab_traverse (changed_variables, check_changed_vars_1, htab);
7204       while (VEC_length (variable, changed_variables_stack) > 0)
7205         check_changed_vars_2 (VEC_pop (variable, changed_variables_stack),
7206                               htab);
7207       while (VEC_length (rtx, changed_values_stack) > 0)
7208         set_dv_changed (dv_from_value (VEC_pop (rtx, changed_values_stack)),
7209                         false);
7210       htab_traverse (changed_variables, check_changed_vars_3, htab);
7211     }
7212
7213   data.insn = insn;
7214   data.where = where;
7215   data.vars = htab;
7216
7217   htab_traverse (changed_variables, emit_note_insn_var_location, &data);
7218 }
7219
7220 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
7221    same variable in hash table DATA or is not there at all.  */
7222
7223 static int
7224 emit_notes_for_differences_1 (void **slot, void *data)
7225 {
7226   htab_t new_vars = (htab_t) data;
7227   variable old_var, new_var;
7228
7229   old_var = (variable) *slot;
7230   new_var = (variable) htab_find_with_hash (new_vars, old_var->dv,
7231                                             dv_htab_hash (old_var->dv));
7232
7233   if (!new_var)
7234     {
7235       /* Variable has disappeared.  */
7236       variable empty_var;
7237
7238       empty_var = (variable) pool_alloc (dv_pool (old_var->dv));
7239       empty_var->dv = old_var->dv;
7240       empty_var->refcount = 0;
7241       empty_var->n_var_parts = 0;
7242       empty_var->cur_loc_changed = false;
7243       empty_var->in_changed_variables = false;
7244       if (dv_onepart_p (old_var->dv))
7245         {
7246           location_chain lc;
7247
7248           gcc_assert (old_var->n_var_parts == 1);
7249           for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next)
7250             remove_value_chains (old_var->dv, lc->loc);
7251         }
7252       variable_was_changed (empty_var, NULL);
7253       /* Continue traversing the hash table.  */
7254       return 1;
7255     }
7256   if (variable_different_p (old_var, new_var))
7257     {
7258       if (dv_onepart_p (old_var->dv))
7259         {
7260           location_chain lc1, lc2;
7261
7262           gcc_assert (old_var->n_var_parts == 1);
7263           gcc_assert (new_var->n_var_parts == 1);
7264           lc1 = old_var->var_part[0].loc_chain;
7265           lc2 = new_var->var_part[0].loc_chain;
7266           while (lc1
7267                  && lc2
7268                  && ((REG_P (lc1->loc) && REG_P (lc2->loc))
7269                      || rtx_equal_p (lc1->loc, lc2->loc)))
7270             {
7271               lc1 = lc1->next;
7272               lc2 = lc2->next;
7273             }
7274           for (; lc2; lc2 = lc2->next)
7275             add_value_chains (old_var->dv, lc2->loc);
7276           for (; lc1; lc1 = lc1->next)
7277             remove_value_chains (old_var->dv, lc1->loc);
7278         }
7279       variable_was_changed (new_var, NULL);
7280     }
7281   /* Update cur_loc.  */
7282   if (old_var != new_var)
7283     {
7284       int i;
7285       for (i = 0; i < new_var->n_var_parts; i++)
7286         {
7287           new_var->var_part[i].cur_loc = NULL;
7288           if (old_var->n_var_parts != new_var->n_var_parts
7289               || old_var->var_part[i].offset != new_var->var_part[i].offset)
7290             new_var->cur_loc_changed = true;
7291           else if (old_var->var_part[i].cur_loc != NULL)
7292             {
7293               location_chain lc;
7294               rtx cur_loc = old_var->var_part[i].cur_loc;
7295
7296               for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next)
7297                 if (lc->loc == cur_loc
7298                     || rtx_equal_p (cur_loc, lc->loc))
7299                   {
7300                     new_var->var_part[i].cur_loc = lc->loc;
7301                     break;
7302                   }
7303               if (lc == NULL)
7304                 new_var->cur_loc_changed = true;
7305             }
7306         }
7307     }
7308
7309   /* Continue traversing the hash table.  */
7310   return 1;
7311 }
7312
7313 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
7314    table DATA.  */
7315
7316 static int
7317 emit_notes_for_differences_2 (void **slot, void *data)
7318 {
7319   htab_t old_vars = (htab_t) data;
7320   variable old_var, new_var;
7321
7322   new_var = (variable) *slot;
7323   old_var = (variable) htab_find_with_hash (old_vars, new_var->dv,
7324                                             dv_htab_hash (new_var->dv));
7325   if (!old_var)
7326     {
7327       int i;
7328       /* Variable has appeared.  */
7329       if (dv_onepart_p (new_var->dv))
7330         {
7331           location_chain lc;
7332
7333           gcc_assert (new_var->n_var_parts == 1);
7334           for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next)
7335             add_value_chains (new_var->dv, lc->loc);
7336         }
7337       for (i = 0; i < new_var->n_var_parts; i++)
7338         new_var->var_part[i].cur_loc = NULL;
7339       variable_was_changed (new_var, NULL);
7340     }
7341
7342   /* Continue traversing the hash table.  */
7343   return 1;
7344 }
7345
7346 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
7347    NEW_SET.  */
7348
7349 static void
7350 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
7351                             dataflow_set *new_set)
7352 {
7353   htab_traverse (shared_hash_htab (old_set->vars),
7354                  emit_notes_for_differences_1,
7355                  shared_hash_htab (new_set->vars));
7356   htab_traverse (shared_hash_htab (new_set->vars),
7357                  emit_notes_for_differences_2,
7358                  shared_hash_htab (old_set->vars));
7359   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
7360 }
7361
7362 /* Emit the notes for changes of location parts in the basic block BB.  */
7363
7364 static void
7365 emit_notes_in_bb (basic_block bb, dataflow_set *set)
7366 {
7367   unsigned int i;
7368   micro_operation *mo;
7369
7370   dataflow_set_clear (set);
7371   dataflow_set_copy (set, &VTI (bb)->in);
7372
7373   for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
7374     {
7375       rtx insn = mo->insn;
7376
7377       switch (mo->type)
7378         {
7379           case MO_CALL:
7380             dataflow_set_clear_at_call (set);
7381             emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
7382             break;
7383
7384           case MO_USE:
7385             {
7386               rtx loc = mo->u.loc;
7387
7388               if (REG_P (loc))
7389                 var_reg_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
7390               else
7391                 var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
7392
7393               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7394             }
7395             break;
7396
7397           case MO_VAL_LOC:
7398             {
7399               rtx loc = mo->u.loc;
7400               rtx val, vloc;
7401               tree var;
7402
7403               if (GET_CODE (loc) == CONCAT)
7404                 {
7405                   val = XEXP (loc, 0);
7406                   vloc = XEXP (loc, 1);
7407                 }
7408               else
7409                 {
7410                   val = NULL_RTX;
7411                   vloc = loc;
7412                 }
7413
7414               var = PAT_VAR_LOCATION_DECL (vloc);
7415
7416               clobber_variable_part (set, NULL_RTX,
7417                                      dv_from_decl (var), 0, NULL_RTX);
7418               if (val)
7419                 {
7420                   if (VAL_NEEDS_RESOLUTION (loc))
7421                     val_resolve (set, val, PAT_VAR_LOCATION_LOC (vloc), insn);
7422                   set_variable_part (set, val, dv_from_decl (var), 0,
7423                                      VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
7424                                      INSERT);
7425                 }
7426
7427               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7428             }
7429             break;
7430
7431           case MO_VAL_USE:
7432             {
7433               rtx loc = mo->u.loc;
7434               rtx val, vloc, uloc;
7435
7436               vloc = uloc = XEXP (loc, 1);
7437               val = XEXP (loc, 0);
7438
7439               if (GET_CODE (val) == CONCAT)
7440                 {
7441                   uloc = XEXP (val, 1);
7442                   val = XEXP (val, 0);
7443                 }
7444
7445               if (VAL_NEEDS_RESOLUTION (loc))
7446                 val_resolve (set, val, vloc, insn);
7447               else
7448                 val_store (set, val, uloc, insn, false);
7449
7450               if (VAL_HOLDS_TRACK_EXPR (loc))
7451                 {
7452                   if (GET_CODE (uloc) == REG)
7453                     var_reg_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
7454                                  NULL);
7455                   else if (GET_CODE (uloc) == MEM)
7456                     var_mem_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
7457                                  NULL);
7458                 }
7459
7460               emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
7461             }
7462             break;
7463
7464           case MO_VAL_SET:
7465             {
7466               rtx loc = mo->u.loc;
7467               rtx val, vloc, uloc, reverse = NULL_RTX;
7468
7469               vloc = loc;
7470               if (VAL_EXPR_HAS_REVERSE (loc))
7471                 {
7472                   reverse = XEXP (loc, 1);
7473                   vloc = XEXP (loc, 0);
7474                 }
7475               uloc = XEXP (vloc, 1);
7476               val = XEXP (vloc, 0);
7477               vloc = uloc;
7478
7479               if (GET_CODE (val) == CONCAT)
7480                 {
7481                   vloc = XEXP (val, 1);
7482                   val = XEXP (val, 0);
7483                 }
7484
7485               if (GET_CODE (vloc) == SET)
7486                 {
7487                   rtx vsrc = SET_SRC (vloc);
7488
7489                   gcc_assert (val != vsrc);
7490                   gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
7491
7492                   vloc = SET_DEST (vloc);
7493
7494                   if (VAL_NEEDS_RESOLUTION (loc))
7495                     val_resolve (set, val, vsrc, insn);
7496                 }
7497               else if (VAL_NEEDS_RESOLUTION (loc))
7498                 {
7499                   gcc_assert (GET_CODE (uloc) == SET
7500                               && GET_CODE (SET_SRC (uloc)) == REG);
7501                   val_resolve (set, val, SET_SRC (uloc), insn);
7502                 }
7503
7504               if (VAL_HOLDS_TRACK_EXPR (loc))
7505                 {
7506                   if (VAL_EXPR_IS_CLOBBERED (loc))
7507                     {
7508                       if (REG_P (uloc))
7509                         var_reg_delete (set, uloc, true);
7510                       else if (MEM_P (uloc))
7511                         var_mem_delete (set, uloc, true);
7512                     }
7513                   else
7514                     {
7515                       bool copied_p = VAL_EXPR_IS_COPIED (loc);
7516                       rtx set_src = NULL;
7517                       enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
7518
7519                       if (GET_CODE (uloc) == SET)
7520                         {
7521                           set_src = SET_SRC (uloc);
7522                           uloc = SET_DEST (uloc);
7523                         }
7524
7525                       if (copied_p)
7526                         {
7527                           status = find_src_status (set, set_src);
7528
7529                           set_src = find_src_set_src (set, set_src);
7530                         }
7531
7532                       if (REG_P (uloc))
7533                         var_reg_delete_and_set (set, uloc, !copied_p,
7534                                                 status, set_src);
7535                       else if (MEM_P (uloc))
7536                         var_mem_delete_and_set (set, uloc, !copied_p,
7537                                                 status, set_src);
7538                     }
7539                 }
7540               else if (REG_P (uloc))
7541                 var_regno_delete (set, REGNO (uloc));
7542
7543               val_store (set, val, vloc, insn, true);
7544
7545               if (reverse)
7546                 val_store (set, XEXP (reverse, 0), XEXP (reverse, 1),
7547                            insn, false);
7548
7549               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7550                                       set->vars);
7551             }
7552             break;
7553
7554           case MO_SET:
7555             {
7556               rtx loc = mo->u.loc;
7557               rtx set_src = NULL;
7558
7559               if (GET_CODE (loc) == SET)
7560                 {
7561                   set_src = SET_SRC (loc);
7562                   loc = SET_DEST (loc);
7563                 }
7564
7565               if (REG_P (loc))
7566                 var_reg_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
7567                                         set_src);
7568               else
7569                 var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
7570                                         set_src);
7571
7572               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7573                                       set->vars);
7574             }
7575             break;
7576
7577           case MO_COPY:
7578             {
7579               rtx loc = mo->u.loc;
7580               enum var_init_status src_status;
7581               rtx set_src = NULL;
7582
7583               if (GET_CODE (loc) == SET)
7584                 {
7585                   set_src = SET_SRC (loc);
7586                   loc = SET_DEST (loc);
7587                 }
7588
7589               src_status = find_src_status (set, set_src);
7590               set_src = find_src_set_src (set, set_src);
7591
7592               if (REG_P (loc))
7593                 var_reg_delete_and_set (set, loc, false, src_status, set_src);
7594               else
7595                 var_mem_delete_and_set (set, loc, false, src_status, set_src);
7596
7597               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7598                                       set->vars);
7599             }
7600             break;
7601
7602           case MO_USE_NO_VAR:
7603             {
7604               rtx loc = mo->u.loc;
7605
7606               if (REG_P (loc))
7607                 var_reg_delete (set, loc, false);
7608               else
7609                 var_mem_delete (set, loc, false);
7610
7611               emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7612             }
7613             break;
7614
7615           case MO_CLOBBER:
7616             {
7617               rtx loc = mo->u.loc;
7618
7619               if (REG_P (loc))
7620                 var_reg_delete (set, loc, true);
7621               else
7622                 var_mem_delete (set, loc, true);
7623
7624               emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7625                                       set->vars);
7626             }
7627             break;
7628
7629           case MO_ADJUST:
7630             set->stack_adjust += mo->u.adjust;
7631             break;
7632         }
7633     }
7634 }
7635
7636 /* Emit notes for the whole function.  */
7637
7638 static void
7639 vt_emit_notes (void)
7640 {
7641   basic_block bb;
7642   dataflow_set cur;
7643
7644 #ifdef ENABLE_RTL_CHECKING
7645   emitted_notes = pointer_map_create ();
7646 #endif
7647   gcc_assert (!htab_elements (changed_variables));
7648
7649   /* Free memory occupied by the out hash tables, as they aren't used
7650      anymore.  */
7651   FOR_EACH_BB (bb)
7652     dataflow_set_clear (&VTI (bb)->out);
7653
7654   /* Enable emitting notes by functions (mainly by set_variable_part and
7655      delete_variable_part).  */
7656   emit_notes = true;
7657
7658   if (MAY_HAVE_DEBUG_INSNS)
7659     {
7660       unsigned int i;
7661       rtx val;
7662
7663       for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
7664         add_cselib_value_chains (dv_from_value (val));
7665       changed_variables_stack = VEC_alloc (variable, heap, 40);
7666       changed_values_stack = VEC_alloc (rtx, heap, 40);
7667     }
7668
7669   dataflow_set_init (&cur);
7670
7671   FOR_EACH_BB (bb)
7672     {
7673       /* Emit the notes for changes of variable locations between two
7674          subsequent basic blocks.  */
7675       emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
7676
7677       /* Emit the notes for the changes in the basic block itself.  */
7678       emit_notes_in_bb (bb, &cur);
7679
7680       /* Free memory occupied by the in hash table, we won't need it
7681          again.  */
7682       dataflow_set_clear (&VTI (bb)->in);
7683     }
7684 #ifdef ENABLE_CHECKING
7685   htab_traverse (shared_hash_htab (cur.vars),
7686                  emit_notes_for_differences_1,
7687                  shared_hash_htab (empty_shared_hash));
7688   if (MAY_HAVE_DEBUG_INSNS)
7689     {
7690       unsigned int i;
7691       rtx val;
7692
7693       for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
7694         remove_cselib_value_chains (dv_from_value (val));
7695       gcc_assert (htab_elements (value_chains) == 0);
7696     }
7697 #endif
7698   dataflow_set_destroy (&cur);
7699
7700   if (MAY_HAVE_DEBUG_INSNS)
7701     {
7702       VEC_free (variable, heap, changed_variables_stack);
7703       VEC_free (rtx, heap, changed_values_stack);
7704     }
7705
7706 #ifdef ENABLE_RTL_CHECKING
7707   pointer_map_destroy (emitted_notes);
7708 #endif
7709   emit_notes = false;
7710 }
7711
7712 /* If there is a declaration and offset associated with register/memory RTL
7713    assign declaration to *DECLP and offset to *OFFSETP, and return true.  */
7714
7715 static bool
7716 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
7717 {
7718   if (REG_P (rtl))
7719     {
7720       if (REG_ATTRS (rtl))
7721         {
7722           *declp = REG_EXPR (rtl);
7723           *offsetp = REG_OFFSET (rtl);
7724           return true;
7725         }
7726     }
7727   else if (MEM_P (rtl))
7728     {
7729       if (MEM_ATTRS (rtl))
7730         {
7731           *declp = MEM_EXPR (rtl);
7732           *offsetp = INT_MEM_OFFSET (rtl);
7733           return true;
7734         }
7735     }
7736   return false;
7737 }
7738
7739 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK.  */
7740
7741 static void
7742 vt_add_function_parameters (void)
7743 {
7744   tree parm;
7745
7746   for (parm = DECL_ARGUMENTS (current_function_decl);
7747        parm; parm = TREE_CHAIN (parm))
7748     {
7749       rtx decl_rtl = DECL_RTL_IF_SET (parm);
7750       rtx incoming = DECL_INCOMING_RTL (parm);
7751       tree decl;
7752       enum machine_mode mode;
7753       HOST_WIDE_INT offset;
7754       dataflow_set *out;
7755       decl_or_value dv;
7756
7757       if (TREE_CODE (parm) != PARM_DECL)
7758         continue;
7759
7760       if (!DECL_NAME (parm))
7761         continue;
7762
7763       if (!decl_rtl || !incoming)
7764         continue;
7765
7766       if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
7767         continue;
7768
7769       if (!vt_get_decl_and_offset (incoming, &decl, &offset))
7770         {
7771           if (REG_P (incoming) || MEM_P (incoming))
7772             {
7773               /* This means argument is passed by invisible reference.  */
7774               offset = 0;
7775               decl = parm;
7776               incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
7777             }
7778           else
7779             {
7780               if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
7781                 continue;
7782               offset += byte_lowpart_offset (GET_MODE (incoming),
7783                                              GET_MODE (decl_rtl));
7784             }
7785         }
7786
7787       if (!decl)
7788         continue;
7789
7790       if (parm != decl)
7791         {
7792           /* Assume that DECL_RTL was a pseudo that got spilled to
7793              memory.  The spill slot sharing code will force the
7794              memory to reference spill_slot_decl (%sfp), so we don't
7795              match above.  That's ok, the pseudo must have referenced
7796              the entire parameter, so just reset OFFSET.  */
7797           gcc_assert (decl == get_spill_slot_decl (false));
7798           offset = 0;
7799         }
7800
7801       if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
7802         continue;
7803
7804       out = &VTI (ENTRY_BLOCK_PTR)->out;
7805
7806       dv = dv_from_decl (parm);
7807
7808       if (target_for_debug_bind (parm)
7809           /* We can't deal with these right now, because this kind of
7810              variable is single-part.  ??? We could handle parallels
7811              that describe multiple locations for the same single
7812              value, but ATM we don't.  */
7813           && GET_CODE (incoming) != PARALLEL)
7814         {
7815           cselib_val *val;
7816
7817           /* ??? We shouldn't ever hit this, but it may happen because
7818              arguments passed by invisible reference aren't dealt with
7819              above: incoming-rtl will have Pmode rather than the
7820              expected mode for the type.  */
7821           if (offset)
7822             continue;
7823
7824           val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
7825
7826           /* ??? Float-typed values in memory are not handled by
7827              cselib.  */
7828           if (val)
7829             {
7830               preserve_value (val);
7831               set_variable_part (out, val->val_rtx, dv, offset,
7832                                  VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
7833               dv = dv_from_value (val->val_rtx);
7834             }
7835         }
7836
7837       if (REG_P (incoming))
7838         {
7839           incoming = var_lowpart (mode, incoming);
7840           gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
7841           attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
7842                              incoming);
7843           set_variable_part (out, incoming, dv, offset,
7844                              VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
7845         }
7846       else if (MEM_P (incoming))
7847         {
7848           incoming = var_lowpart (mode, incoming);
7849           set_variable_part (out, incoming, dv, offset,
7850                              VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
7851         }
7852     }
7853
7854   if (MAY_HAVE_DEBUG_INSNS)
7855     {
7856       cselib_preserve_only_values ();
7857       cselib_reset_table (cselib_get_next_uid ());
7858     }
7859
7860 }
7861
7862 /* Return true if INSN in the prologue initializes hard_frame_pointer_rtx.  */
7863
7864 static bool
7865 fp_setter (rtx insn)
7866 {
7867   rtx pat = PATTERN (insn);
7868   if (RTX_FRAME_RELATED_P (insn))
7869     {
7870       rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
7871       if (expr)
7872         pat = XEXP (expr, 0);
7873     }
7874   if (GET_CODE (pat) == SET)
7875     return SET_DEST (pat) == hard_frame_pointer_rtx;
7876   else if (GET_CODE (pat) == PARALLEL)
7877     {
7878       int i;
7879       for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
7880         if (GET_CODE (XVECEXP (pat, 0, i)) == SET
7881             && SET_DEST (XVECEXP (pat, 0, i)) == hard_frame_pointer_rtx)
7882           return true;
7883     }
7884   return false;
7885 }
7886
7887 /* Initialize cfa_base_rtx, create a preserved VALUE for it and
7888    ensure it isn't flushed during cselib_reset_table.
7889    Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
7890    has been eliminated.  */
7891
7892 static void
7893 vt_init_cfa_base (void)
7894 {
7895   cselib_val *val;
7896
7897 #ifdef FRAME_POINTER_CFA_OFFSET
7898   cfa_base_rtx = frame_pointer_rtx;
7899 #else
7900   cfa_base_rtx = arg_pointer_rtx;
7901 #endif
7902   if (!MAY_HAVE_DEBUG_INSNS)
7903     return;
7904
7905   val = cselib_lookup (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1);
7906   preserve_value (val);
7907   cselib_preserve_cfa_base_value (val);
7908   val->locs->setting_insn = get_insns ();
7909   var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx,
7910                     VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx),
7911                     0, NULL_RTX, INSERT);
7912 }
7913
7914 /* Allocate and initialize the data structures for variable tracking
7915    and parse the RTL to get the micro operations.  */
7916
7917 static bool
7918 vt_initialize (void)
7919 {
7920   basic_block bb, prologue_bb = NULL;
7921   HOST_WIDE_INT fp_cfa_offset = -1;
7922
7923   alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
7924
7925   attrs_pool = create_alloc_pool ("attrs_def pool",
7926                                   sizeof (struct attrs_def), 1024);
7927   var_pool = create_alloc_pool ("variable_def pool",
7928                                 sizeof (struct variable_def)
7929                                 + (MAX_VAR_PARTS - 1)
7930                                 * sizeof (((variable)NULL)->var_part[0]), 64);
7931   loc_chain_pool = create_alloc_pool ("location_chain_def pool",
7932                                       sizeof (struct location_chain_def),
7933                                       1024);
7934   shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
7935                                         sizeof (struct shared_hash_def), 256);
7936   empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
7937   empty_shared_hash->refcount = 1;
7938   empty_shared_hash->htab
7939     = htab_create (1, variable_htab_hash, variable_htab_eq,
7940                    variable_htab_free);
7941   changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
7942                                    variable_htab_free);
7943   if (MAY_HAVE_DEBUG_INSNS)
7944     {
7945       value_chain_pool = create_alloc_pool ("value_chain_def pool",
7946                                             sizeof (struct value_chain_def),
7947                                             1024);
7948       value_chains = htab_create (32, value_chain_htab_hash,
7949                                   value_chain_htab_eq, NULL);
7950     }
7951
7952   /* Init the IN and OUT sets.  */
7953   FOR_ALL_BB (bb)
7954     {
7955       VTI (bb)->visited = false;
7956       VTI (bb)->flooded = false;
7957       dataflow_set_init (&VTI (bb)->in);
7958       dataflow_set_init (&VTI (bb)->out);
7959       VTI (bb)->permp = NULL;
7960     }
7961
7962   if (MAY_HAVE_DEBUG_INSNS)
7963     {
7964       cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
7965       scratch_regs = BITMAP_ALLOC (NULL);
7966       valvar_pool = create_alloc_pool ("small variable_def pool",
7967                                        sizeof (struct variable_def), 256);
7968       preserved_values = VEC_alloc (rtx, heap, 256);
7969     }
7970   else
7971     {
7972       scratch_regs = NULL;
7973       valvar_pool = NULL;
7974     }
7975
7976   if (!frame_pointer_needed)
7977     {
7978       rtx reg, elim;
7979
7980       if (!vt_stack_adjustments ())
7981         return false;
7982
7983 #ifdef FRAME_POINTER_CFA_OFFSET
7984       reg = frame_pointer_rtx;
7985 #else
7986       reg = arg_pointer_rtx;
7987 #endif
7988       elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
7989       if (elim != reg)
7990         {
7991           if (GET_CODE (elim) == PLUS)
7992             elim = XEXP (elim, 0);
7993           if (elim == stack_pointer_rtx)
7994             vt_init_cfa_base ();
7995         }
7996     }
7997   else if (!crtl->stack_realign_tried)
7998     {
7999       rtx reg, elim;
8000
8001 #ifdef FRAME_POINTER_CFA_OFFSET
8002       reg = frame_pointer_rtx;
8003       fp_cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
8004 #else
8005       reg = arg_pointer_rtx;
8006       fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
8007 #endif
8008       elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
8009       if (elim != reg)
8010         {
8011           if (GET_CODE (elim) == PLUS)
8012             {
8013               fp_cfa_offset -= INTVAL (XEXP (elim, 1));
8014               elim = XEXP (elim, 0);
8015             }
8016           if (elim != hard_frame_pointer_rtx)
8017             fp_cfa_offset = -1;
8018           else
8019             prologue_bb = single_succ (ENTRY_BLOCK_PTR);
8020         }
8021     }
8022
8023   hard_frame_pointer_adjustment = -1;
8024
8025   FOR_EACH_BB (bb)
8026     {
8027       rtx insn;
8028       HOST_WIDE_INT pre, post = 0;
8029       basic_block first_bb, last_bb;
8030
8031       if (MAY_HAVE_DEBUG_INSNS)
8032         {
8033           cselib_record_sets_hook = add_with_sets;
8034           if (dump_file && (dump_flags & TDF_DETAILS))
8035             fprintf (dump_file, "first value: %i\n",
8036                      cselib_get_next_uid ());
8037         }
8038
8039       first_bb = bb;
8040       for (;;)
8041         {
8042           edge e;
8043           if (bb->next_bb == EXIT_BLOCK_PTR
8044               || ! single_pred_p (bb->next_bb))
8045             break;
8046           e = find_edge (bb, bb->next_bb);
8047           if (! e || (e->flags & EDGE_FALLTHRU) == 0)
8048             break;
8049           bb = bb->next_bb;
8050         }
8051       last_bb = bb;
8052
8053       /* Add the micro-operations to the vector.  */
8054       FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb)
8055         {
8056           HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
8057           VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
8058           for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
8059                insn = NEXT_INSN (insn))
8060             {
8061               if (INSN_P (insn))
8062                 {
8063                   if (!frame_pointer_needed)
8064                     {
8065                       insn_stack_adjust_offset_pre_post (insn, &pre, &post);
8066                       if (pre)
8067                         {
8068                           micro_operation mo;
8069                           mo.type = MO_ADJUST;
8070                           mo.u.adjust = pre;
8071                           mo.insn = insn;
8072                           if (dump_file && (dump_flags & TDF_DETAILS))
8073                             log_op_type (PATTERN (insn), bb, insn,
8074                                          MO_ADJUST, dump_file);
8075                           VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
8076                                          &mo);
8077                           VTI (bb)->out.stack_adjust += pre;
8078                         }
8079                     }
8080
8081                   cselib_hook_called = false;
8082                   adjust_insn (bb, insn);
8083                   if (MAY_HAVE_DEBUG_INSNS)
8084                     {
8085                       cselib_process_insn (insn);
8086                       if (dump_file && (dump_flags & TDF_DETAILS))
8087                         {
8088                           print_rtl_single (dump_file, insn);
8089                           dump_cselib_table (dump_file);
8090                         }
8091                     }
8092                   if (!cselib_hook_called)
8093                     add_with_sets (insn, 0, 0);
8094                   cancel_changes (0);
8095
8096                   if (!frame_pointer_needed && post)
8097                     {
8098                       micro_operation mo;
8099                       mo.type = MO_ADJUST;
8100                       mo.u.adjust = post;
8101                       mo.insn = insn;
8102                       if (dump_file && (dump_flags & TDF_DETAILS))
8103                         log_op_type (PATTERN (insn), bb, insn,
8104                                      MO_ADJUST, dump_file);
8105                       VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
8106                                      &mo);
8107                       VTI (bb)->out.stack_adjust += post;
8108                     }
8109
8110                   if (bb == prologue_bb
8111                       && hard_frame_pointer_adjustment == -1
8112                       && RTX_FRAME_RELATED_P (insn)
8113                       && fp_setter (insn))
8114                     {
8115                       vt_init_cfa_base ();
8116                       hard_frame_pointer_adjustment = fp_cfa_offset;
8117                     }
8118                 }
8119             }
8120           gcc_assert (offset == VTI (bb)->out.stack_adjust);
8121         }
8122
8123       bb = last_bb;
8124
8125       if (MAY_HAVE_DEBUG_INSNS)
8126         {
8127           cselib_preserve_only_values ();
8128           cselib_reset_table (cselib_get_next_uid ());
8129           cselib_record_sets_hook = NULL;
8130         }
8131     }
8132
8133   hard_frame_pointer_adjustment = -1;
8134   VTI (ENTRY_BLOCK_PTR)->flooded = true;
8135   vt_add_function_parameters ();
8136   cfa_base_rtx = NULL_RTX;
8137   return true;
8138 }
8139
8140 /* Get rid of all debug insns from the insn stream.  */
8141
8142 static void
8143 delete_debug_insns (void)
8144 {
8145   basic_block bb;
8146   rtx insn, next;
8147
8148   if (!MAY_HAVE_DEBUG_INSNS)
8149     return;
8150
8151   FOR_EACH_BB (bb)
8152     {
8153       FOR_BB_INSNS_SAFE (bb, insn, next)
8154         if (DEBUG_INSN_P (insn))
8155           delete_insn (insn);
8156     }
8157 }
8158
8159 /* Run a fast, BB-local only version of var tracking, to take care of
8160    information that we don't do global analysis on, such that not all
8161    information is lost.  If SKIPPED holds, we're skipping the global
8162    pass entirely, so we should try to use information it would have
8163    handled as well..  */
8164
8165 static void
8166 vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
8167 {
8168   /* ??? Just skip it all for now.  */
8169   delete_debug_insns ();
8170 }
8171
8172 /* Free the data structures needed for variable tracking.  */
8173
8174 static void
8175 vt_finalize (void)
8176 {
8177   basic_block bb;
8178
8179   FOR_EACH_BB (bb)
8180     {
8181       VEC_free (micro_operation, heap, VTI (bb)->mos);
8182     }
8183
8184   FOR_ALL_BB (bb)
8185     {
8186       dataflow_set_destroy (&VTI (bb)->in);
8187       dataflow_set_destroy (&VTI (bb)->out);
8188       if (VTI (bb)->permp)
8189         {
8190           dataflow_set_destroy (VTI (bb)->permp);
8191           XDELETE (VTI (bb)->permp);
8192         }
8193     }
8194   free_aux_for_blocks ();
8195   htab_delete (empty_shared_hash->htab);
8196   htab_delete (changed_variables);
8197   free_alloc_pool (attrs_pool);
8198   free_alloc_pool (var_pool);
8199   free_alloc_pool (loc_chain_pool);
8200   free_alloc_pool (shared_hash_pool);
8201
8202   if (MAY_HAVE_DEBUG_INSNS)
8203     {
8204       htab_delete (value_chains);
8205       free_alloc_pool (value_chain_pool);
8206       free_alloc_pool (valvar_pool);
8207       VEC_free (rtx, heap, preserved_values);
8208       cselib_finish ();
8209       BITMAP_FREE (scratch_regs);
8210       scratch_regs = NULL;
8211     }
8212
8213   if (vui_vec)
8214     XDELETEVEC (vui_vec);
8215   vui_vec = NULL;
8216   vui_allocated = 0;
8217 }
8218
8219 /* The entry point to variable tracking pass.  */
8220
8221 static inline unsigned int
8222 variable_tracking_main_1 (void)
8223 {
8224   bool success;
8225
8226   if (flag_var_tracking_assignments < 0)
8227     {
8228       delete_debug_insns ();
8229       return 0;
8230     }
8231
8232   if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
8233     {
8234       vt_debug_insns_local (true);
8235       return 0;
8236     }
8237
8238   mark_dfs_back_edges ();
8239   if (!vt_initialize ())
8240     {
8241       vt_finalize ();
8242       vt_debug_insns_local (true);
8243       return 0;
8244     }
8245
8246   success = vt_find_locations ();
8247
8248   if (!success && flag_var_tracking_assignments > 0)
8249     {
8250       vt_finalize ();
8251
8252       delete_debug_insns ();
8253
8254       /* This is later restored by our caller.  */
8255       flag_var_tracking_assignments = 0;
8256
8257       success = vt_initialize ();
8258       gcc_assert (success);
8259
8260       success = vt_find_locations ();
8261     }
8262
8263   if (!success)
8264     {
8265       vt_finalize ();
8266       vt_debug_insns_local (false);
8267       return 0;
8268     }
8269
8270   if (dump_file && (dump_flags & TDF_DETAILS))
8271     {
8272       dump_dataflow_sets ();
8273       dump_flow_info (dump_file, dump_flags);
8274     }
8275
8276   vt_emit_notes ();
8277
8278   vt_finalize ();
8279   vt_debug_insns_local (false);
8280   return 0;
8281 }
8282
8283 unsigned int
8284 variable_tracking_main (void)
8285 {
8286   unsigned int ret;
8287   int save = flag_var_tracking_assignments;
8288
8289   ret = variable_tracking_main_1 ();
8290
8291   flag_var_tracking_assignments = save;
8292
8293   return ret;
8294 }
8295 \f
8296 static bool
8297 gate_handle_var_tracking (void)
8298 {
8299   return (flag_var_tracking);
8300 }
8301
8302
8303
8304 struct rtl_opt_pass pass_variable_tracking =
8305 {
8306  {
8307   RTL_PASS,
8308   "vartrack",                           /* name */
8309   gate_handle_var_tracking,             /* gate */
8310   variable_tracking_main,               /* execute */
8311   NULL,                                 /* sub */
8312   NULL,                                 /* next */
8313   0,                                    /* static_pass_number */
8314   TV_VAR_TRACKING,                      /* tv_id */
8315   0,                                    /* properties_required */
8316   0,                                    /* properties_provided */
8317   0,                                    /* properties_destroyed */
8318   0,                                    /* todo_flags_start */
8319   TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */
8320  }
8321 };