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