xref: /netbsd-src/external/gpl3/gcc/dist/gcc/var-tracking.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Variable tracking routines for the GNU compiler.
2    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3 
4    This file is part of GCC.
5 
6    GCC is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING3.  If not see
18    <http://www.gnu.org/licenses/>.  */
19 
20 /* This file contains the variable tracking pass.  It computes where
21    variables are located (which registers or where in memory) at each position
22    in instruction stream and emits notes describing the locations.
23    Debug information (DWARF2 location lists) is finally generated from
24    these notes.
25    With this debug information, it is possible to show variables
26    even when debugging optimized code.
27 
28    How does the variable tracking pass work?
29 
30    First, it scans RTL code for uses, stores and clobbers (register/memory
31    references in instructions), for call insns and for stack adjustments
32    separately for each basic block and saves them to an array of micro
33    operations.
34    The micro operations of one instruction are ordered so that
35    pre-modifying stack adjustment < use < use with no var < call insn <
36      < clobber < set < post-modifying stack adjustment
37 
38    Then, a forward dataflow analysis is performed to find out how locations
39    of variables change through code and to propagate the variable locations
40    along control flow graph.
41    The IN set for basic block BB is computed as a union of OUT sets of BB's
42    predecessors, the OUT set for BB is copied from the IN set for BB and
43    is changed according to micro operations in BB.
44 
45    The IN and OUT sets for basic blocks consist of a current stack adjustment
46    (used for adjusting offset of variables addressed using stack pointer),
47    the table of structures describing the locations of parts of a variable
48    and for each physical register a linked list for each physical register.
49    The linked list is a list of variable parts stored in the register,
50    i.e. it is a list of triplets (reg, decl, offset) where decl is
51    REG_EXPR (reg) and offset is REG_OFFSET (reg).  The linked list is used for
52    effective deleting appropriate variable parts when we set or clobber the
53    register.
54 
55    There may be more than one variable part in a register.  The linked lists
56    should be pretty short so it is a good data structure here.
57    For example in the following code, register allocator may assign same
58    register to variables A and B, and both of them are stored in the same
59    register in CODE:
60 
61      if (cond)
62        set A;
63      else
64        set B;
65      CODE;
66      if (cond)
67        use A;
68      else
69        use B;
70 
71    Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
72    are emitted to appropriate positions in RTL code.  Each such a note describes
73    the location of one variable at the point in instruction stream where the
74    note is.  There is no need to emit a note for each variable before each
75    instruction, we only emit these notes where the location of variable changes
76    (this means that we also emit notes for changes between the OUT set of the
77    previous block and the IN set of the current block).
78 
79    The notes consist of two parts:
80    1. the declaration (from REG_EXPR or MEM_EXPR)
81    2. the location of a variable - it is either a simple register/memory
82       reference (for simple variables, for example int),
83       or a parallel of register/memory references (for a large variables
84       which consist of several parts, for example long long).
85 
86 */
87 
88 #include "config.h"
89 #include "system.h"
90 #include "coretypes.h"
91 #include "backend.h"
92 #include "target.h"
93 #include "rtl.h"
94 #include "tree.h"
95 #include "cfghooks.h"
96 #include "alloc-pool.h"
97 #include "tree-pass.h"
98 #include "memmodel.h"
99 #include "tm_p.h"
100 #include "insn-config.h"
101 #include "regs.h"
102 #include "emit-rtl.h"
103 #include "recog.h"
104 #include "diagnostic.h"
105 #include "varasm.h"
106 #include "stor-layout.h"
107 #include "cfgrtl.h"
108 #include "cfganal.h"
109 #include "reload.h"
110 #include "calls.h"
111 #include "tree-dfa.h"
112 #include "tree-ssa.h"
113 #include "cselib.h"
114 #include "tree-pretty-print.h"
115 #include "rtl-iter.h"
116 #include "fibonacci_heap.h"
117 #include "print-rtl.h"
118 #include "function-abi.h"
119 
120 typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
121 
122 /* var-tracking.cc assumes that tree code with the same value as VALUE rtx code
123    has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
124    Currently the value is the same as IDENTIFIER_NODE, which has such
125    a property.  If this compile time assertion ever fails, make sure that
126    the new tree code that equals (int) VALUE has the same property.  */
127 extern char check_value_val[(int) VALUE == (int) IDENTIFIER_NODE ? 1 : -1];
128 
129 /* Type of micro operation.  */
130 enum micro_operation_type
131 {
132   MO_USE,	/* Use location (REG or MEM).  */
133   MO_USE_NO_VAR,/* Use location which is not associated with a variable
134 		   or the variable is not trackable.  */
135   MO_VAL_USE,	/* Use location which is associated with a value.  */
136   MO_VAL_LOC,   /* Use location which appears in a debug insn.  */
137   MO_VAL_SET,	/* Set location associated with a value.  */
138   MO_SET,	/* Set location.  */
139   MO_COPY,	/* Copy the same portion of a variable from one
140 		   location to another.  */
141   MO_CLOBBER,	/* Clobber location.  */
142   MO_CALL,	/* Call insn.  */
143   MO_ADJUST	/* Adjust stack pointer.  */
144 
145 };
146 
147 static const char * const ATTRIBUTE_UNUSED
148 micro_operation_type_name[] = {
149   "MO_USE",
150   "MO_USE_NO_VAR",
151   "MO_VAL_USE",
152   "MO_VAL_LOC",
153   "MO_VAL_SET",
154   "MO_SET",
155   "MO_COPY",
156   "MO_CLOBBER",
157   "MO_CALL",
158   "MO_ADJUST"
159 };
160 
161 /* Where shall the note be emitted?  BEFORE or AFTER the instruction.
162    Notes emitted as AFTER_CALL are to take effect during the call,
163    rather than after the call.  */
164 enum emit_note_where
165 {
166   EMIT_NOTE_BEFORE_INSN,
167   EMIT_NOTE_AFTER_INSN,
168   EMIT_NOTE_AFTER_CALL_INSN
169 };
170 
171 /* Structure holding information about micro operation.  */
172 struct micro_operation
173 {
174   /* Type of micro operation.  */
175   enum micro_operation_type type;
176 
177   /* The instruction which the micro operation is in, for MO_USE,
178      MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
179      instruction or note in the original flow (before any var-tracking
180      notes are inserted, to simplify emission of notes), for MO_SET
181      and MO_CLOBBER.  */
182   rtx_insn *insn;
183 
184   union {
185     /* Location.  For MO_SET and MO_COPY, this is the SET that
186        performs the assignment, if known, otherwise it is the target
187        of the assignment.  For MO_VAL_USE and MO_VAL_SET, it is a
188        CONCAT of the VALUE and the LOC associated with it.  For
189        MO_VAL_LOC, it is a CONCAT of the VALUE and the VAR_LOCATION
190        associated with it.  */
191     rtx loc;
192 
193     /* Stack adjustment.  */
194     HOST_WIDE_INT adjust;
195   } u;
196 };
197 
198 
199 /* A declaration of a variable, or an RTL value being handled like a
200    declaration.  */
201 typedef void *decl_or_value;
202 
203 /* Return true if a decl_or_value DV is a DECL or NULL.  */
204 static inline bool
dv_is_decl_p(decl_or_value dv)205 dv_is_decl_p (decl_or_value dv)
206 {
207   return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE;
208 }
209 
210 /* Return true if a decl_or_value is a VALUE rtl.  */
211 static inline bool
dv_is_value_p(decl_or_value dv)212 dv_is_value_p (decl_or_value dv)
213 {
214   return dv && !dv_is_decl_p (dv);
215 }
216 
217 /* Return the decl in the decl_or_value.  */
218 static inline tree
dv_as_decl(decl_or_value dv)219 dv_as_decl (decl_or_value dv)
220 {
221   gcc_checking_assert (dv_is_decl_p (dv));
222   return (tree) dv;
223 }
224 
225 /* Return the value in the decl_or_value.  */
226 static inline rtx
dv_as_value(decl_or_value dv)227 dv_as_value (decl_or_value dv)
228 {
229   gcc_checking_assert (dv_is_value_p (dv));
230   return (rtx)dv;
231 }
232 
233 /* Return the opaque pointer in the decl_or_value.  */
234 static inline void *
dv_as_opaque(decl_or_value dv)235 dv_as_opaque (decl_or_value dv)
236 {
237   return dv;
238 }
239 
240 
241 /* Description of location of a part of a variable.  The content of a physical
242    register is described by a chain of these structures.
243    The chains are pretty short (usually 1 or 2 elements) and thus
244    chain is the best data structure.  */
245 struct attrs
246 {
247   /* Pointer to next member of the list.  */
248   attrs *next;
249 
250   /* The rtx of register.  */
251   rtx loc;
252 
253   /* The declaration corresponding to LOC.  */
254   decl_or_value dv;
255 
256   /* Offset from start of DECL.  */
257   HOST_WIDE_INT offset;
258 };
259 
260 /* Structure for chaining the locations.  */
261 struct location_chain
262 {
263   /* Next element in the chain.  */
264   location_chain *next;
265 
266   /* The location (REG, MEM or VALUE).  */
267   rtx loc;
268 
269   /* The "value" stored in this location.  */
270   rtx set_src;
271 
272   /* Initialized? */
273   enum var_init_status init;
274 };
275 
276 /* A vector of loc_exp_dep holds the active dependencies of a one-part
277    DV on VALUEs, i.e., the VALUEs expanded so as to form the current
278    location of DV.  Each entry is also part of VALUE' s linked-list of
279    backlinks back to DV.  */
280 struct loc_exp_dep
281 {
282   /* The dependent DV.  */
283   decl_or_value dv;
284   /* The dependency VALUE or DECL_DEBUG.  */
285   rtx value;
286   /* The next entry in VALUE's backlinks list.  */
287   struct loc_exp_dep *next;
288   /* A pointer to the pointer to this entry (head or prev's next) in
289      the doubly-linked list.  */
290   struct loc_exp_dep **pprev;
291 };
292 
293 
294 /* This data structure holds information about the depth of a variable
295    expansion.  */
296 struct expand_depth
297 {
298   /* This measures the complexity of the expanded expression.  It
299      grows by one for each level of expansion that adds more than one
300      operand.  */
301   int complexity;
302   /* This counts the number of ENTRY_VALUE expressions in an
303      expansion.  We want to minimize their use.  */
304   int entryvals;
305 };
306 
307 /* Type for dependencies actively used when expand FROM into cur_loc.  */
308 typedef vec<loc_exp_dep, va_heap, vl_embed> deps_vec;
309 
310 /* This data structure is allocated for one-part variables at the time
311    of emitting notes.  */
312 struct onepart_aux
313 {
314   /* Doubly-linked list of dependent DVs.  These are DVs whose cur_loc
315      computation used the expansion of this variable, and that ought
316      to be notified should this variable change.  If the DV's cur_loc
317      expanded to NULL, all components of the loc list are regarded as
318      active, so that any changes in them give us a chance to get a
319      location.  Otherwise, only components of the loc that expanded to
320      non-NULL are regarded as active dependencies.  */
321   loc_exp_dep *backlinks;
322   /* This holds the LOC that was expanded into cur_loc.  We need only
323      mark a one-part variable as changed if the FROM loc is removed,
324      or if it has no known location and a loc is added, or if it gets
325      a change notification from any of its active dependencies.  */
326   rtx from;
327   /* The depth of the cur_loc expression.  */
328   expand_depth depth;
329   /* Dependencies actively used when expand FROM into cur_loc.  */
330   deps_vec deps;
331 };
332 
333 /* Structure describing one part of variable.  */
334 struct variable_part
335 {
336   /* Chain of locations of the part.  */
337   location_chain *loc_chain;
338 
339   /* Location which was last emitted to location list.  */
340   rtx cur_loc;
341 
342   union variable_aux
343   {
344     /* The offset in the variable, if !var->onepart.  */
345     HOST_WIDE_INT offset;
346 
347     /* Pointer to auxiliary data, if var->onepart and emit_notes.  */
348     struct onepart_aux *onepaux;
349   } aux;
350 };
351 
352 /* Maximum number of location parts.  */
353 #define MAX_VAR_PARTS 16
354 
355 /* Enumeration type used to discriminate various types of one-part
356    variables.  */
357 enum onepart_enum
358 {
359   /* Not a one-part variable.  */
360   NOT_ONEPART = 0,
361   /* A one-part DECL that is not a DEBUG_EXPR_DECL.  */
362   ONEPART_VDECL = 1,
363   /* A DEBUG_EXPR_DECL.  */
364   ONEPART_DEXPR = 2,
365   /* A VALUE.  */
366   ONEPART_VALUE = 3
367 };
368 
369 /* Structure describing where the variable is located.  */
370 struct variable
371 {
372   /* The declaration of the variable, or an RTL value being handled
373      like a declaration.  */
374   decl_or_value dv;
375 
376   /* Reference count.  */
377   int refcount;
378 
379   /* Number of variable parts.  */
380   char n_var_parts;
381 
382   /* What type of DV this is, according to enum onepart_enum.  */
383   ENUM_BITFIELD (onepart_enum) onepart : CHAR_BIT;
384 
385   /* True if this variable_def struct is currently in the
386      changed_variables hash table.  */
387   bool in_changed_variables;
388 
389   /* The variable parts.  */
390   variable_part var_part[1];
391 };
392 
393 /* Pointer to the BB's information specific to variable tracking pass.  */
394 #define VTI(BB) ((variable_tracking_info *) (BB)->aux)
395 
396 /* Return MEM_OFFSET (MEM) as a HOST_WIDE_INT, or 0 if we can't.  */
397 
398 static inline HOST_WIDE_INT
int_mem_offset(const_rtx mem)399 int_mem_offset (const_rtx mem)
400 {
401   HOST_WIDE_INT offset;
402   if (MEM_OFFSET_KNOWN_P (mem) && MEM_OFFSET (mem).is_constant (&offset))
403     return offset;
404   return 0;
405 }
406 
407 #if CHECKING_P && (GCC_VERSION >= 2007)
408 
409 /* Access VAR's Ith part's offset, checking that it's not a one-part
410    variable.  */
411 #define VAR_PART_OFFSET(var, i) __extension__			\
412 (*({  variable *const __v = (var);				\
413       gcc_checking_assert (!__v->onepart);			\
414       &__v->var_part[(i)].aux.offset; }))
415 
416 /* Access VAR's one-part auxiliary data, checking that it is a
417    one-part variable.  */
418 #define VAR_LOC_1PAUX(var) __extension__			\
419 (*({  variable *const __v = (var);				\
420       gcc_checking_assert (__v->onepart);			\
421       &__v->var_part[0].aux.onepaux; }))
422 
423 #else
424 #define VAR_PART_OFFSET(var, i) ((var)->var_part[(i)].aux.offset)
425 #define VAR_LOC_1PAUX(var) ((var)->var_part[0].aux.onepaux)
426 #endif
427 
428 /* These are accessor macros for the one-part auxiliary data.  When
429    convenient for users, they're guarded by tests that the data was
430    allocated.  */
431 #define VAR_LOC_DEP_LST(var) (VAR_LOC_1PAUX (var)		  \
432 			      ? VAR_LOC_1PAUX (var)->backlinks	  \
433 			      : NULL)
434 #define VAR_LOC_DEP_LSTP(var) (VAR_LOC_1PAUX (var)		  \
435 			       ? &VAR_LOC_1PAUX (var)->backlinks  \
436 			       : NULL)
437 #define VAR_LOC_FROM(var) (VAR_LOC_1PAUX (var)->from)
438 #define VAR_LOC_DEPTH(var) (VAR_LOC_1PAUX (var)->depth)
439 #define VAR_LOC_DEP_VEC(var) var_loc_dep_vec (var)
440 
441 /* Implements the VAR_LOC_DEP_VEC above as a function to work around
442    a bogus -Wnonnull (PR c/95554). */
443 
444 static inline deps_vec*
var_loc_dep_vec(variable * var)445 var_loc_dep_vec (variable *var)
446 {
447   return VAR_LOC_1PAUX (var) ? &VAR_LOC_1PAUX (var)->deps : NULL;
448 }
449 
450 
451 typedef unsigned int dvuid;
452 
453 /* Return the uid of DV.  */
454 
455 static inline dvuid
dv_uid(decl_or_value dv)456 dv_uid (decl_or_value dv)
457 {
458   if (dv_is_value_p (dv))
459     return CSELIB_VAL_PTR (dv_as_value (dv))->uid;
460   else
461     return DECL_UID (dv_as_decl (dv));
462 }
463 
464 /* Compute the hash from the uid.  */
465 
466 static inline hashval_t
dv_uid2hash(dvuid uid)467 dv_uid2hash (dvuid uid)
468 {
469   return uid;
470 }
471 
472 /* The hash function for a mask table in a shared_htab chain.  */
473 
474 static inline hashval_t
dv_htab_hash(decl_or_value dv)475 dv_htab_hash (decl_or_value dv)
476 {
477   return dv_uid2hash (dv_uid (dv));
478 }
479 
480 static void variable_htab_free (void *);
481 
482 /* Variable hashtable helpers.  */
483 
484 struct variable_hasher : pointer_hash <variable>
485 {
486   typedef void *compare_type;
487   static inline hashval_t hash (const variable *);
488   static inline bool equal (const variable *, const void *);
489   static inline void remove (variable *);
490 };
491 
492 /* The hash function for variable_htab, computes the hash value
493    from the declaration of variable X.  */
494 
495 inline hashval_t
hash(const variable * v)496 variable_hasher::hash (const variable *v)
497 {
498   return dv_htab_hash (v->dv);
499 }
500 
501 /* Compare the declaration of variable X with declaration Y.  */
502 
503 inline bool
equal(const variable * v,const void * y)504 variable_hasher::equal (const variable *v, const void *y)
505 {
506   decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
507 
508   return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
509 }
510 
511 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
512 
513 inline void
remove(variable * var)514 variable_hasher::remove (variable *var)
515 {
516   variable_htab_free (var);
517 }
518 
519 typedef hash_table<variable_hasher> variable_table_type;
520 typedef variable_table_type::iterator variable_iterator_type;
521 
522 /* Structure for passing some other parameters to function
523    emit_note_insn_var_location.  */
524 struct emit_note_data
525 {
526   /* The instruction which the note will be emitted before/after.  */
527   rtx_insn *insn;
528 
529   /* Where the note will be emitted (before/after insn)?  */
530   enum emit_note_where where;
531 
532   /* The variables and values active at this point.  */
533   variable_table_type *vars;
534 };
535 
536 /* Structure holding a refcounted hash table.  If refcount > 1,
537    it must be first unshared before modified.  */
538 struct shared_hash
539 {
540   /* Reference count.  */
541   int refcount;
542 
543   /* Actual hash table.  */
544   variable_table_type *htab;
545 };
546 
547 /* Structure holding the IN or OUT set for a basic block.  */
548 struct dataflow_set
549 {
550   /* Adjustment of stack offset.  */
551   HOST_WIDE_INT stack_adjust;
552 
553   /* Attributes for registers (lists of attrs).  */
554   attrs *regs[FIRST_PSEUDO_REGISTER];
555 
556   /* Variable locations.  */
557   shared_hash *vars;
558 
559   /* Vars that is being traversed.  */
560   shared_hash *traversed_vars;
561 };
562 
563 /* The structure (one for each basic block) containing the information
564    needed for variable tracking.  */
565 struct variable_tracking_info
566 {
567   /* The vector of micro operations.  */
568   vec<micro_operation> mos;
569 
570   /* The IN and OUT set for dataflow analysis.  */
571   dataflow_set in;
572   dataflow_set out;
573 
574   /* The permanent-in dataflow set for this block.  This is used to
575      hold values for which we had to compute entry values.  ??? This
576      should probably be dynamically allocated, to avoid using more
577      memory in non-debug builds.  */
578   dataflow_set *permp;
579 
580   /* Has the block been visited in DFS?  */
581   bool visited;
582 
583   /* Has the block been flooded in VTA?  */
584   bool flooded;
585 
586 };
587 
588 /* Alloc pool for struct attrs_def.  */
589 object_allocator<attrs> attrs_pool ("attrs pool");
590 
591 /* Alloc pool for struct variable_def with MAX_VAR_PARTS entries.  */
592 
593 static pool_allocator var_pool
594   ("variable_def pool", sizeof (variable) +
595    (MAX_VAR_PARTS - 1) * sizeof (((variable *)NULL)->var_part[0]));
596 
597 /* Alloc pool for struct variable_def with a single var_part entry.  */
598 static pool_allocator valvar_pool
599   ("small variable_def pool", sizeof (variable));
600 
601 /* Alloc pool for struct location_chain.  */
602 static object_allocator<location_chain> location_chain_pool
603   ("location_chain pool");
604 
605 /* Alloc pool for struct shared_hash.  */
606 static object_allocator<shared_hash> shared_hash_pool ("shared_hash pool");
607 
608 /* Alloc pool for struct loc_exp_dep_s for NOT_ONEPART variables.  */
609 object_allocator<loc_exp_dep> loc_exp_dep_pool ("loc_exp_dep pool");
610 
611 /* Changed variables, notes will be emitted for them.  */
612 static variable_table_type *changed_variables;
613 
614 /* Shall notes be emitted?  */
615 static bool emit_notes;
616 
617 /* Values whose dynamic location lists have gone empty, but whose
618    cselib location lists are still usable.  Use this to hold the
619    current location, the backlinks, etc, during emit_notes.  */
620 static variable_table_type *dropped_values;
621 
622 /* Empty shared hashtable.  */
623 static shared_hash *empty_shared_hash;
624 
625 /* Scratch register bitmap used by cselib_expand_value_rtx.  */
626 static bitmap scratch_regs = NULL;
627 
628 #ifdef HAVE_window_save
629 struct GTY(()) parm_reg {
630   rtx outgoing;
631   rtx incoming;
632 };
633 
634 
635 /* Vector of windowed parameter registers, if any.  */
636 static vec<parm_reg, va_gc> *windowed_parm_regs = NULL;
637 #endif
638 
639 /* Variable used to tell whether cselib_process_insn called our hook.  */
640 static bool cselib_hook_called;
641 
642 /* Local function prototypes.  */
643 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
644 					  HOST_WIDE_INT *);
645 static void insn_stack_adjust_offset_pre_post (rtx_insn *, HOST_WIDE_INT *,
646 					       HOST_WIDE_INT *);
647 static bool vt_stack_adjustments (void);
648 
649 static void init_attrs_list_set (attrs **);
650 static void attrs_list_clear (attrs **);
651 static attrs *attrs_list_member (attrs *, decl_or_value, HOST_WIDE_INT);
652 static void attrs_list_insert (attrs **, decl_or_value, HOST_WIDE_INT, rtx);
653 static void attrs_list_copy (attrs **, attrs *);
654 static void attrs_list_union (attrs **, attrs *);
655 
656 static variable **unshare_variable (dataflow_set *set, variable **slot,
657 					variable *var, enum var_init_status);
658 static void vars_copy (variable_table_type *, variable_table_type *);
659 static tree var_debug_decl (tree);
660 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
661 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
662 				    enum var_init_status, rtx);
663 static void var_reg_delete (dataflow_set *, rtx, bool);
664 static void var_regno_delete (dataflow_set *, int);
665 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
666 static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
667 				    enum var_init_status, rtx);
668 static void var_mem_delete (dataflow_set *, rtx, bool);
669 
670 static void dataflow_set_init (dataflow_set *);
671 static void dataflow_set_clear (dataflow_set *);
672 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
673 static int variable_union_info_cmp_pos (const void *, const void *);
674 static void dataflow_set_union (dataflow_set *, dataflow_set *);
675 static location_chain *find_loc_in_1pdv (rtx, variable *,
676 					 variable_table_type *);
677 static bool canon_value_cmp (rtx, rtx);
678 static int loc_cmp (rtx, rtx);
679 static bool variable_part_different_p (variable_part *, variable_part *);
680 static bool onepart_variable_different_p (variable *, variable *);
681 static bool variable_different_p (variable *, variable *);
682 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
683 static void dataflow_set_destroy (dataflow_set *);
684 
685 static bool track_expr_p (tree, bool);
686 static void add_uses_1 (rtx *, void *);
687 static void add_stores (rtx, const_rtx, void *);
688 static bool compute_bb_dataflow (basic_block);
689 static bool vt_find_locations (void);
690 
691 static void dump_attrs_list (attrs *);
692 static void dump_var (variable *);
693 static void dump_vars (variable_table_type *);
694 static void dump_dataflow_set (dataflow_set *);
695 static void dump_dataflow_sets (void);
696 
697 static void set_dv_changed (decl_or_value, bool);
698 static void variable_was_changed (variable *, dataflow_set *);
699 static variable **set_slot_part (dataflow_set *, rtx, variable **,
700 				 decl_or_value, HOST_WIDE_INT,
701 				 enum var_init_status, rtx);
702 static void set_variable_part (dataflow_set *, rtx,
703 			       decl_or_value, HOST_WIDE_INT,
704 			       enum var_init_status, rtx, enum insert_option);
705 static variable **clobber_slot_part (dataflow_set *, rtx,
706 				     variable **, HOST_WIDE_INT, rtx);
707 static void clobber_variable_part (dataflow_set *, rtx,
708 				   decl_or_value, HOST_WIDE_INT, rtx);
709 static variable **delete_slot_part (dataflow_set *, rtx, variable **,
710 				    HOST_WIDE_INT);
711 static void delete_variable_part (dataflow_set *, rtx,
712 				  decl_or_value, HOST_WIDE_INT);
713 static void emit_notes_in_bb (basic_block, dataflow_set *);
714 static void vt_emit_notes (void);
715 
716 static void vt_add_function_parameters (void);
717 static bool vt_initialize (void);
718 static void vt_finalize (void);
719 
720 /* Callback for stack_adjust_offset_pre_post, called via for_each_inc_dec.  */
721 
722 static int
stack_adjust_offset_pre_post_cb(rtx,rtx op,rtx dest,rtx src,rtx srcoff,void * arg)723 stack_adjust_offset_pre_post_cb (rtx, rtx op, rtx dest, rtx src, rtx srcoff,
724 				 void *arg)
725 {
726   if (dest != stack_pointer_rtx)
727     return 0;
728 
729   switch (GET_CODE (op))
730     {
731     case PRE_INC:
732     case PRE_DEC:
733       ((HOST_WIDE_INT *)arg)[0] -= INTVAL (srcoff);
734       return 0;
735     case POST_INC:
736     case POST_DEC:
737       ((HOST_WIDE_INT *)arg)[1] -= INTVAL (srcoff);
738       return 0;
739     case PRE_MODIFY:
740     case POST_MODIFY:
741       /* We handle only adjustments by constant amount.  */
742       gcc_assert (GET_CODE (src) == PLUS
743 		  && CONST_INT_P (XEXP (src, 1))
744 		  && XEXP (src, 0) == stack_pointer_rtx);
745       ((HOST_WIDE_INT *)arg)[GET_CODE (op) == POST_MODIFY]
746 	-= INTVAL (XEXP (src, 1));
747       return 0;
748     default:
749       gcc_unreachable ();
750     }
751 }
752 
753 /* Given a SET, calculate the amount of stack adjustment it contains
754    PRE- and POST-modifying stack pointer.
755    This function is similar to stack_adjust_offset.  */
756 
757 static void
stack_adjust_offset_pre_post(rtx pattern,HOST_WIDE_INT * pre,HOST_WIDE_INT * post)758 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
759 			      HOST_WIDE_INT *post)
760 {
761   rtx src = SET_SRC (pattern);
762   rtx dest = SET_DEST (pattern);
763   enum rtx_code code;
764 
765   if (dest == stack_pointer_rtx)
766     {
767       /* (set (reg sp) (plus (reg sp) (const_int))) */
768       code = GET_CODE (src);
769       if (! (code == PLUS || code == MINUS)
770 	  || XEXP (src, 0) != stack_pointer_rtx
771 	  || !CONST_INT_P (XEXP (src, 1)))
772 	return;
773 
774       if (code == MINUS)
775 	*post += INTVAL (XEXP (src, 1));
776       else
777 	*post -= INTVAL (XEXP (src, 1));
778       return;
779     }
780   HOST_WIDE_INT res[2] = { 0, 0 };
781   for_each_inc_dec (pattern, stack_adjust_offset_pre_post_cb, res);
782   *pre += res[0];
783   *post += res[1];
784 }
785 
786 /* Given an INSN, calculate the amount of stack adjustment it contains
787    PRE- and POST-modifying stack pointer.  */
788 
789 static void
insn_stack_adjust_offset_pre_post(rtx_insn * insn,HOST_WIDE_INT * pre,HOST_WIDE_INT * post)790 insn_stack_adjust_offset_pre_post (rtx_insn *insn, HOST_WIDE_INT *pre,
791 				   HOST_WIDE_INT *post)
792 {
793   rtx pattern;
794 
795   *pre = 0;
796   *post = 0;
797 
798   pattern = PATTERN (insn);
799   if (RTX_FRAME_RELATED_P (insn))
800     {
801       rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
802       if (expr)
803 	pattern = XEXP (expr, 0);
804     }
805 
806   if (GET_CODE (pattern) == SET)
807     stack_adjust_offset_pre_post (pattern, pre, post);
808   else if (GET_CODE (pattern) == PARALLEL
809 	   || GET_CODE (pattern) == SEQUENCE)
810     {
811       int i;
812 
813       /* There may be stack adjustments inside compound insns.  Search
814 	 for them.  */
815       for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
816 	if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
817 	  stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
818     }
819 }
820 
821 /* Compute stack adjustments for all blocks by traversing DFS tree.
822    Return true when the adjustments on all incoming edges are consistent.
823    Heavily borrowed from pre_and_rev_post_order_compute.  */
824 
825 static bool
vt_stack_adjustments(void)826 vt_stack_adjustments (void)
827 {
828   edge_iterator *stack;
829   int sp;
830 
831   /* Initialize entry block.  */
832   VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->visited = true;
833   VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->in.stack_adjust
834     = INCOMING_FRAME_SP_OFFSET;
835   VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out.stack_adjust
836     = INCOMING_FRAME_SP_OFFSET;
837 
838   /* Allocate stack for back-tracking up CFG.  */
839   stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun) + 1);
840   sp = 0;
841 
842   /* Push the first edge on to the stack.  */
843   stack[sp++] = ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs);
844 
845   while (sp)
846     {
847       edge_iterator ei;
848       basic_block src;
849       basic_block dest;
850 
851       /* Look at the edge on the top of the stack.  */
852       ei = stack[sp - 1];
853       src = ei_edge (ei)->src;
854       dest = ei_edge (ei)->dest;
855 
856       /* Check if the edge destination has been visited yet.  */
857       if (!VTI (dest)->visited)
858 	{
859 	  rtx_insn *insn;
860 	  HOST_WIDE_INT pre, post, offset;
861 	  VTI (dest)->visited = true;
862 	  VTI (dest)->in.stack_adjust = offset = VTI (src)->out.stack_adjust;
863 
864 	  if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
865 	    for (insn = BB_HEAD (dest);
866 		 insn != NEXT_INSN (BB_END (dest));
867 		 insn = NEXT_INSN (insn))
868 	      if (INSN_P (insn))
869 		{
870 		  insn_stack_adjust_offset_pre_post (insn, &pre, &post);
871 		  offset += pre + post;
872 		}
873 
874 	  VTI (dest)->out.stack_adjust = offset;
875 
876 	  if (EDGE_COUNT (dest->succs) > 0)
877 	    /* Since the DEST node has been visited for the first
878 	       time, check its successors.  */
879 	    stack[sp++] = ei_start (dest->succs);
880 	}
881       else
882 	{
883 	  /* We can end up with different stack adjustments for the exit block
884 	     of a shrink-wrapped function if stack_adjust_offset_pre_post
885 	     doesn't understand the rtx pattern used to restore the stack
886 	     pointer in the epilogue.  For example, on s390(x), the stack
887 	     pointer is often restored via a load-multiple instruction
888 	     and so no stack_adjust offset is recorded for it.  This means
889 	     that the stack offset at the end of the epilogue block is the
890 	     same as the offset before the epilogue, whereas other paths
891 	     to the exit block will have the correct stack_adjust.
892 
893 	     It is safe to ignore these differences because (a) we never
894 	     use the stack_adjust for the exit block in this pass and
895 	     (b) dwarf2cfi checks whether the CFA notes in a shrink-wrapped
896 	     function are correct.
897 
898 	     We must check whether the adjustments on other edges are
899 	     the same though.  */
900 	  if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
901 	      && VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
902 	    {
903 	      free (stack);
904 	      return false;
905 	    }
906 
907 	  if (! ei_one_before_end_p (ei))
908 	    /* Go to the next edge.  */
909 	    ei_next (&stack[sp - 1]);
910 	  else
911 	    /* Return to previous level if there are no more edges.  */
912 	    sp--;
913 	}
914     }
915 
916   free (stack);
917   return true;
918 }
919 
920 /* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or
921    hard_frame_pointer_rtx is being mapped to it and offset for it.  */
922 static rtx cfa_base_rtx;
923 static HOST_WIDE_INT cfa_base_offset;
924 
925 /* Compute a CFA-based value for an ADJUSTMENT made to stack_pointer_rtx
926    or hard_frame_pointer_rtx.  */
927 
928 static inline rtx
compute_cfa_pointer(poly_int64 adjustment)929 compute_cfa_pointer (poly_int64 adjustment)
930 {
931   return plus_constant (Pmode, cfa_base_rtx, adjustment + cfa_base_offset);
932 }
933 
934 /* Adjustment for hard_frame_pointer_rtx to cfa base reg,
935    or -1 if the replacement shouldn't be done.  */
936 static poly_int64 hard_frame_pointer_adjustment = -1;
937 
938 /* Data for adjust_mems callback.  */
939 
940 class adjust_mem_data
941 {
942 public:
943   bool store;
944   machine_mode mem_mode;
945   HOST_WIDE_INT stack_adjust;
946   auto_vec<rtx> side_effects;
947 };
948 
949 /* Helper for adjust_mems.  Return true if X is suitable for
950    transformation of wider mode arithmetics to narrower mode.  */
951 
952 static bool
use_narrower_mode_test(rtx x,const_rtx subreg)953 use_narrower_mode_test (rtx x, const_rtx subreg)
954 {
955   subrtx_var_iterator::array_type array;
956   FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
957     {
958       rtx x = *iter;
959       if (CONSTANT_P (x))
960 	iter.skip_subrtxes ();
961       else
962 	switch (GET_CODE (x))
963 	  {
964 	  case REG:
965 	    if (cselib_lookup (x, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
966 	      return false;
967 	    if (!validate_subreg (GET_MODE (subreg), GET_MODE (x), x,
968 				  subreg_lowpart_offset (GET_MODE (subreg),
969 							 GET_MODE (x))))
970 	      return false;
971 	    break;
972 	  case PLUS:
973 	  case MINUS:
974 	  case MULT:
975 	    break;
976 	  case ASHIFT:
977 	    if (GET_MODE (XEXP (x, 1)) != VOIDmode)
978 	      {
979 		enum machine_mode mode = GET_MODE (subreg);
980 		rtx op1 = XEXP (x, 1);
981 		enum machine_mode op1_mode = GET_MODE (op1);
982 		if (GET_MODE_PRECISION (as_a <scalar_int_mode> (mode))
983 		    < GET_MODE_PRECISION (as_a <scalar_int_mode> (op1_mode)))
984 		  {
985 		    poly_uint64 byte = subreg_lowpart_offset (mode, op1_mode);
986 		    if (GET_CODE (op1) == SUBREG || GET_CODE (op1) == CONCAT)
987 		      {
988 			if (!simplify_subreg (mode, op1, op1_mode, byte))
989 			  return false;
990 		      }
991 		    else if (!validate_subreg (mode, op1_mode, op1, byte))
992 		      return false;
993 		  }
994 	      }
995 	    iter.substitute (XEXP (x, 0));
996 	    break;
997 	  default:
998 	    return false;
999 	  }
1000     }
1001   return true;
1002 }
1003 
1004 /* Transform X into narrower mode MODE from wider mode WMODE.  */
1005 
1006 static rtx
use_narrower_mode(rtx x,scalar_int_mode mode,scalar_int_mode wmode)1007 use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode)
1008 {
1009   rtx op0, op1;
1010   if (CONSTANT_P (x))
1011     return lowpart_subreg (mode, x, wmode);
1012   switch (GET_CODE (x))
1013     {
1014     case REG:
1015       return lowpart_subreg (mode, x, wmode);
1016     case PLUS:
1017     case MINUS:
1018     case MULT:
1019       op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
1020       op1 = use_narrower_mode (XEXP (x, 1), mode, wmode);
1021       return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
1022     case ASHIFT:
1023       op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
1024       op1 = XEXP (x, 1);
1025       /* Ensure shift amount is not wider than mode.  */
1026       if (GET_MODE (op1) == VOIDmode)
1027 	op1 = lowpart_subreg (mode, op1, wmode);
1028       else if (GET_MODE_PRECISION (mode)
1029 	       < GET_MODE_PRECISION (as_a <scalar_int_mode> (GET_MODE (op1))))
1030 	op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
1031       return simplify_gen_binary (ASHIFT, mode, op0, op1);
1032     default:
1033       gcc_unreachable ();
1034     }
1035 }
1036 
1037 /* Helper function for adjusting used MEMs.  */
1038 
1039 static rtx
adjust_mems(rtx loc,const_rtx old_rtx,void * data)1040 adjust_mems (rtx loc, const_rtx old_rtx, void *data)
1041 {
1042   class adjust_mem_data *amd = (class adjust_mem_data *) data;
1043   rtx mem, addr = loc, tem;
1044   machine_mode mem_mode_save;
1045   bool store_save;
1046   scalar_int_mode tem_mode, tem_subreg_mode;
1047   poly_int64 size;
1048   switch (GET_CODE (loc))
1049     {
1050     case REG:
1051       /* Don't do any sp or fp replacements outside of MEM addresses
1052          on the LHS.  */
1053       if (amd->mem_mode == VOIDmode && amd->store)
1054 	return loc;
1055       if (loc == stack_pointer_rtx
1056 	  && !frame_pointer_needed
1057 	  && cfa_base_rtx)
1058 	return compute_cfa_pointer (amd->stack_adjust);
1059       else if (loc == hard_frame_pointer_rtx
1060 	       && frame_pointer_needed
1061 	       && maybe_ne (hard_frame_pointer_adjustment, -1)
1062 	       && cfa_base_rtx)
1063 	return compute_cfa_pointer (hard_frame_pointer_adjustment);
1064       gcc_checking_assert (loc != virtual_incoming_args_rtx);
1065       return loc;
1066     case MEM:
1067       mem = loc;
1068       if (!amd->store)
1069 	{
1070 	  mem = targetm.delegitimize_address (mem);
1071 	  if (mem != loc && !MEM_P (mem))
1072 	    return simplify_replace_fn_rtx (mem, old_rtx, adjust_mems, data);
1073 	}
1074 
1075       addr = XEXP (mem, 0);
1076       mem_mode_save = amd->mem_mode;
1077       amd->mem_mode = GET_MODE (mem);
1078       store_save = amd->store;
1079       amd->store = false;
1080       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1081       amd->store = store_save;
1082       amd->mem_mode = mem_mode_save;
1083       if (mem == loc)
1084 	addr = targetm.delegitimize_address (addr);
1085       if (addr != XEXP (mem, 0))
1086 	mem = replace_equiv_address_nv (mem, addr);
1087       if (!amd->store)
1088 	mem = avoid_constant_pool_reference (mem);
1089       return mem;
1090     case PRE_INC:
1091     case PRE_DEC:
1092       size = GET_MODE_SIZE (amd->mem_mode);
1093       addr = plus_constant (GET_MODE (loc), XEXP (loc, 0),
1094 			    GET_CODE (loc) == PRE_INC ? size : -size);
1095       /* FALLTHRU */
1096     case POST_INC:
1097     case POST_DEC:
1098       if (addr == loc)
1099 	addr = XEXP (loc, 0);
1100       gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
1101       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1102       size = GET_MODE_SIZE (amd->mem_mode);
1103       tem = plus_constant (GET_MODE (loc), XEXP (loc, 0),
1104 			   (GET_CODE (loc) == PRE_INC
1105 			    || GET_CODE (loc) == POST_INC) ? size : -size);
1106       store_save = amd->store;
1107       amd->store = false;
1108       tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data);
1109       amd->store = store_save;
1110       amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
1111       return addr;
1112     case PRE_MODIFY:
1113       addr = XEXP (loc, 1);
1114       /* FALLTHRU */
1115     case POST_MODIFY:
1116       if (addr == loc)
1117 	addr = XEXP (loc, 0);
1118       gcc_assert (amd->mem_mode != VOIDmode);
1119       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1120       store_save = amd->store;
1121       amd->store = false;
1122       tem = simplify_replace_fn_rtx (XEXP (loc, 1), old_rtx,
1123 				     adjust_mems, data);
1124       amd->store = store_save;
1125       amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
1126       return addr;
1127     case SUBREG:
1128       /* First try without delegitimization of whole MEMs and
1129 	 avoid_constant_pool_reference, which is more likely to succeed.  */
1130       store_save = amd->store;
1131       amd->store = true;
1132       addr = simplify_replace_fn_rtx (SUBREG_REG (loc), old_rtx, adjust_mems,
1133 				      data);
1134       amd->store = store_save;
1135       mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1136       if (mem == SUBREG_REG (loc))
1137 	{
1138 	  tem = loc;
1139 	  goto finish_subreg;
1140 	}
1141       tem = simplify_gen_subreg (GET_MODE (loc), mem,
1142 				 GET_MODE (SUBREG_REG (loc)),
1143 				 SUBREG_BYTE (loc));
1144       if (tem)
1145 	goto finish_subreg;
1146       tem = simplify_gen_subreg (GET_MODE (loc), addr,
1147 				 GET_MODE (SUBREG_REG (loc)),
1148 				 SUBREG_BYTE (loc));
1149       if (tem == NULL_RTX)
1150 	tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
1151     finish_subreg:
1152       if (MAY_HAVE_DEBUG_BIND_INSNS
1153 	  && GET_CODE (tem) == SUBREG
1154 	  && (GET_CODE (SUBREG_REG (tem)) == PLUS
1155 	      || GET_CODE (SUBREG_REG (tem)) == MINUS
1156 	      || GET_CODE (SUBREG_REG (tem)) == MULT
1157 	      || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
1158 	  && is_a <scalar_int_mode> (GET_MODE (tem), &tem_mode)
1159 	  && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (tem)),
1160 				     &tem_subreg_mode)
1161 	  && (GET_MODE_PRECISION (tem_mode)
1162 	      < GET_MODE_PRECISION (tem_subreg_mode))
1163 	  && subreg_lowpart_p (tem)
1164 	  && use_narrower_mode_test (SUBREG_REG (tem), tem))
1165 	return use_narrower_mode (SUBREG_REG (tem), tem_mode, tem_subreg_mode);
1166       return tem;
1167     case ASM_OPERANDS:
1168       /* Don't do any replacements in second and following
1169 	 ASM_OPERANDS of inline-asm with multiple sets.
1170 	 ASM_OPERANDS_INPUT_VEC, ASM_OPERANDS_INPUT_CONSTRAINT_VEC
1171 	 and ASM_OPERANDS_LABEL_VEC need to be equal between
1172 	 all the ASM_OPERANDs in the insn and adjust_insn will
1173 	 fix this up.  */
1174       if (ASM_OPERANDS_OUTPUT_IDX (loc) != 0)
1175 	return loc;
1176       break;
1177     default:
1178       break;
1179     }
1180   return NULL_RTX;
1181 }
1182 
1183 /* Helper function for replacement of uses.  */
1184 
1185 static void
adjust_mem_uses(rtx * x,void * data)1186 adjust_mem_uses (rtx *x, void *data)
1187 {
1188   rtx new_x = simplify_replace_fn_rtx (*x, NULL_RTX, adjust_mems, data);
1189   if (new_x != *x)
1190     validate_change (NULL_RTX, x, new_x, true);
1191 }
1192 
1193 /* Helper function for replacement of stores.  */
1194 
1195 static void
adjust_mem_stores(rtx loc,const_rtx expr,void * data)1196 adjust_mem_stores (rtx loc, const_rtx expr, void *data)
1197 {
1198   if (MEM_P (loc))
1199     {
1200       rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr), NULL_RTX,
1201 					      adjust_mems, data);
1202       if (new_dest != SET_DEST (expr))
1203 	{
1204 	  rtx xexpr = CONST_CAST_RTX (expr);
1205 	  validate_change (NULL_RTX, &SET_DEST (xexpr), new_dest, true);
1206 	}
1207     }
1208 }
1209 
1210 /* Simplify INSN.  Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes,
1211    replace them with their value in the insn and add the side-effects
1212    as other sets to the insn.  */
1213 
1214 static void
adjust_insn(basic_block bb,rtx_insn * insn)1215 adjust_insn (basic_block bb, rtx_insn *insn)
1216 {
1217   rtx set;
1218 
1219 #ifdef HAVE_window_save
1220   /* If the target machine has an explicit window save instruction, the
1221      transformation OUTGOING_REGNO -> INCOMING_REGNO is done there.  */
1222   if (RTX_FRAME_RELATED_P (insn)
1223       && find_reg_note (insn, REG_CFA_WINDOW_SAVE, NULL_RTX))
1224     {
1225       unsigned int i, nregs = vec_safe_length (windowed_parm_regs);
1226       rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2));
1227       parm_reg *p;
1228 
1229       FOR_EACH_VEC_SAFE_ELT (windowed_parm_regs, i, p)
1230 	{
1231 	  XVECEXP (rtl, 0, i * 2)
1232 	    = gen_rtx_SET (p->incoming, p->outgoing);
1233 	  /* Do not clobber the attached DECL, but only the REG.  */
1234 	  XVECEXP (rtl, 0, i * 2 + 1)
1235 	    = gen_rtx_CLOBBER (GET_MODE (p->outgoing),
1236 			       gen_raw_REG (GET_MODE (p->outgoing),
1237 					    REGNO (p->outgoing)));
1238 	}
1239 
1240       validate_change (NULL_RTX, &PATTERN (insn), rtl, true);
1241       return;
1242     }
1243 #endif
1244 
1245   adjust_mem_data amd;
1246   amd.mem_mode = VOIDmode;
1247   amd.stack_adjust = -VTI (bb)->out.stack_adjust;
1248 
1249   amd.store = true;
1250   note_stores (insn, adjust_mem_stores, &amd);
1251 
1252   amd.store = false;
1253   if (GET_CODE (PATTERN (insn)) == PARALLEL
1254       && asm_noperands (PATTERN (insn)) > 0
1255       && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
1256     {
1257       rtx body, set0;
1258       int i;
1259 
1260       /* inline-asm with multiple sets is tiny bit more complicated,
1261 	 because the 3 vectors in ASM_OPERANDS need to be shared between
1262 	 all ASM_OPERANDS in the instruction.  adjust_mems will
1263 	 not touch ASM_OPERANDS other than the first one, asm_noperands
1264 	 test above needs to be called before that (otherwise it would fail)
1265 	 and afterwards this code fixes it up.  */
1266       note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
1267       body = PATTERN (insn);
1268       set0 = XVECEXP (body, 0, 0);
1269       gcc_checking_assert (GET_CODE (set0) == SET
1270 			   && GET_CODE (SET_SRC (set0)) == ASM_OPERANDS
1271 			   && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set0)) == 0);
1272       for (i = 1; i < XVECLEN (body, 0); i++)
1273 	if (GET_CODE (XVECEXP (body, 0, i)) != SET)
1274 	  break;
1275 	else
1276 	  {
1277 	    set = XVECEXP (body, 0, i);
1278 	    gcc_checking_assert (GET_CODE (SET_SRC (set)) == ASM_OPERANDS
1279 				 && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set))
1280 				    == i);
1281 	    if (ASM_OPERANDS_INPUT_VEC (SET_SRC (set))
1282 		!= ASM_OPERANDS_INPUT_VEC (SET_SRC (set0))
1283 		|| ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set))
1284 		   != ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0))
1285 		|| ASM_OPERANDS_LABEL_VEC (SET_SRC (set))
1286 		   != ASM_OPERANDS_LABEL_VEC (SET_SRC (set0)))
1287 	      {
1288 		rtx newsrc = shallow_copy_rtx (SET_SRC (set));
1289 		ASM_OPERANDS_INPUT_VEC (newsrc)
1290 		  = ASM_OPERANDS_INPUT_VEC (SET_SRC (set0));
1291 		ASM_OPERANDS_INPUT_CONSTRAINT_VEC (newsrc)
1292 		  = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0));
1293 		ASM_OPERANDS_LABEL_VEC (newsrc)
1294 		  = ASM_OPERANDS_LABEL_VEC (SET_SRC (set0));
1295 		validate_change (NULL_RTX, &SET_SRC (set), newsrc, true);
1296 	      }
1297 	  }
1298     }
1299   else
1300     note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
1301 
1302   /* For read-only MEMs containing some constant, prefer those
1303      constants.  */
1304   set = single_set (insn);
1305   if (set && MEM_P (SET_SRC (set)) && MEM_READONLY_P (SET_SRC (set)))
1306     {
1307       rtx note = find_reg_equal_equiv_note (insn);
1308 
1309       if (note && CONSTANT_P (XEXP (note, 0)))
1310 	validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true);
1311     }
1312 
1313   if (!amd.side_effects.is_empty ())
1314     {
1315       rtx *pat, new_pat;
1316       int i, oldn;
1317 
1318       pat = &PATTERN (insn);
1319       if (GET_CODE (*pat) == COND_EXEC)
1320 	pat = &COND_EXEC_CODE (*pat);
1321       if (GET_CODE (*pat) == PARALLEL)
1322 	oldn = XVECLEN (*pat, 0);
1323       else
1324 	oldn = 1;
1325       unsigned int newn = amd.side_effects.length ();
1326       new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn));
1327       if (GET_CODE (*pat) == PARALLEL)
1328 	for (i = 0; i < oldn; i++)
1329 	  XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i);
1330       else
1331 	XVECEXP (new_pat, 0, 0) = *pat;
1332 
1333       rtx effect;
1334       unsigned int j;
1335       FOR_EACH_VEC_ELT_REVERSE (amd.side_effects, j, effect)
1336 	XVECEXP (new_pat, 0, j + oldn) = effect;
1337       validate_change (NULL_RTX, pat, new_pat, true);
1338     }
1339 }
1340 
1341 /* Return the DEBUG_EXPR of a DEBUG_EXPR_DECL or the VALUE in DV.  */
1342 static inline rtx
dv_as_rtx(decl_or_value dv)1343 dv_as_rtx (decl_or_value dv)
1344 {
1345   tree decl;
1346 
1347   if (dv_is_value_p (dv))
1348     return dv_as_value (dv);
1349 
1350   decl = dv_as_decl (dv);
1351 
1352   gcc_checking_assert (TREE_CODE (decl) == DEBUG_EXPR_DECL);
1353   return DECL_RTL_KNOWN_SET (decl);
1354 }
1355 
1356 /* Return nonzero if a decl_or_value must not have more than one
1357    variable part.  The returned value discriminates among various
1358    kinds of one-part DVs ccording to enum onepart_enum.  */
1359 static inline onepart_enum
dv_onepart_p(decl_or_value dv)1360 dv_onepart_p (decl_or_value dv)
1361 {
1362   tree decl;
1363 
1364   if (!MAY_HAVE_DEBUG_BIND_INSNS)
1365     return NOT_ONEPART;
1366 
1367   if (dv_is_value_p (dv))
1368     return ONEPART_VALUE;
1369 
1370   decl = dv_as_decl (dv);
1371 
1372   if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
1373     return ONEPART_DEXPR;
1374 
1375   if (target_for_debug_bind (decl) != NULL_TREE)
1376     return ONEPART_VDECL;
1377 
1378   return NOT_ONEPART;
1379 }
1380 
1381 /* Return the variable pool to be used for a dv of type ONEPART.  */
1382 static inline pool_allocator &
onepart_pool(onepart_enum onepart)1383 onepart_pool (onepart_enum onepart)
1384 {
1385   return onepart ? valvar_pool : var_pool;
1386 }
1387 
1388 /* Allocate a variable_def from the corresponding variable pool.  */
1389 static inline variable *
onepart_pool_allocate(onepart_enum onepart)1390 onepart_pool_allocate (onepart_enum onepart)
1391 {
1392   return (variable*) onepart_pool (onepart).allocate ();
1393 }
1394 
1395 /* Build a decl_or_value out of a decl.  */
1396 static inline decl_or_value
dv_from_decl(tree decl)1397 dv_from_decl (tree decl)
1398 {
1399   decl_or_value dv;
1400   dv = decl;
1401   gcc_checking_assert (dv_is_decl_p (dv));
1402   return dv;
1403 }
1404 
1405 /* Build a decl_or_value out of a value.  */
1406 static inline decl_or_value
dv_from_value(rtx value)1407 dv_from_value (rtx value)
1408 {
1409   decl_or_value dv;
1410   dv = value;
1411   gcc_checking_assert (dv_is_value_p (dv));
1412   return dv;
1413 }
1414 
1415 /* Return a value or the decl of a debug_expr as a decl_or_value.  */
1416 static inline decl_or_value
dv_from_rtx(rtx x)1417 dv_from_rtx (rtx x)
1418 {
1419   decl_or_value dv;
1420 
1421   switch (GET_CODE (x))
1422     {
1423     case DEBUG_EXPR:
1424       dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
1425       gcc_checking_assert (DECL_RTL_KNOWN_SET (DEBUG_EXPR_TREE_DECL (x)) == x);
1426       break;
1427 
1428     case VALUE:
1429       dv = dv_from_value (x);
1430       break;
1431 
1432     default:
1433       gcc_unreachable ();
1434     }
1435 
1436   return dv;
1437 }
1438 
1439 extern void debug_dv (decl_or_value dv);
1440 
1441 DEBUG_FUNCTION void
debug_dv(decl_or_value dv)1442 debug_dv (decl_or_value dv)
1443 {
1444   if (dv_is_value_p (dv))
1445     debug_rtx (dv_as_value (dv));
1446   else
1447     debug_generic_stmt (dv_as_decl (dv));
1448 }
1449 
1450 static void loc_exp_dep_clear (variable *var);
1451 
1452 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
1453 
1454 static void
variable_htab_free(void * elem)1455 variable_htab_free (void *elem)
1456 {
1457   int i;
1458   variable *var = (variable *) elem;
1459   location_chain *node, *next;
1460 
1461   gcc_checking_assert (var->refcount > 0);
1462 
1463   var->refcount--;
1464   if (var->refcount > 0)
1465     return;
1466 
1467   for (i = 0; i < var->n_var_parts; i++)
1468     {
1469       for (node = var->var_part[i].loc_chain; node; node = next)
1470 	{
1471 	  next = node->next;
1472 	  delete node;
1473 	}
1474       var->var_part[i].loc_chain = NULL;
1475     }
1476   if (var->onepart && VAR_LOC_1PAUX (var))
1477     {
1478       loc_exp_dep_clear (var);
1479       if (VAR_LOC_DEP_LST (var))
1480 	VAR_LOC_DEP_LST (var)->pprev = NULL;
1481       XDELETE (VAR_LOC_1PAUX (var));
1482       /* These may be reused across functions, so reset
1483 	 e.g. NO_LOC_P.  */
1484       if (var->onepart == ONEPART_DEXPR)
1485 	set_dv_changed (var->dv, true);
1486     }
1487   onepart_pool (var->onepart).remove (var);
1488 }
1489 
1490 /* Initialize the set (array) SET of attrs to empty lists.  */
1491 
1492 static void
init_attrs_list_set(attrs ** set)1493 init_attrs_list_set (attrs **set)
1494 {
1495   int i;
1496 
1497   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1498     set[i] = NULL;
1499 }
1500 
1501 /* Make the list *LISTP empty.  */
1502 
1503 static void
attrs_list_clear(attrs ** listp)1504 attrs_list_clear (attrs **listp)
1505 {
1506   attrs *list, *next;
1507 
1508   for (list = *listp; list; list = next)
1509     {
1510       next = list->next;
1511       delete list;
1512     }
1513   *listp = NULL;
1514 }
1515 
1516 /* Return true if the pair of DECL and OFFSET is the member of the LIST.  */
1517 
1518 static attrs *
attrs_list_member(attrs * list,decl_or_value dv,HOST_WIDE_INT offset)1519 attrs_list_member (attrs *list, decl_or_value dv, HOST_WIDE_INT offset)
1520 {
1521   for (; list; list = list->next)
1522     if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
1523       return list;
1524   return NULL;
1525 }
1526 
1527 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
1528 
1529 static void
attrs_list_insert(attrs ** listp,decl_or_value dv,HOST_WIDE_INT offset,rtx loc)1530 attrs_list_insert (attrs **listp, decl_or_value dv,
1531 		   HOST_WIDE_INT offset, rtx loc)
1532 {
1533   attrs *list = new attrs;
1534   list->loc = loc;
1535   list->dv = dv;
1536   list->offset = offset;
1537   list->next = *listp;
1538   *listp = list;
1539 }
1540 
1541 /* Copy all nodes from SRC and create a list *DSTP of the copies.  */
1542 
1543 static void
attrs_list_copy(attrs ** dstp,attrs * src)1544 attrs_list_copy (attrs **dstp, attrs *src)
1545 {
1546   attrs_list_clear (dstp);
1547   for (; src; src = src->next)
1548     {
1549       attrs *n = new attrs;
1550       n->loc = src->loc;
1551       n->dv = src->dv;
1552       n->offset = src->offset;
1553       n->next = *dstp;
1554       *dstp = n;
1555     }
1556 }
1557 
1558 /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
1559 
1560 static void
attrs_list_union(attrs ** dstp,attrs * src)1561 attrs_list_union (attrs **dstp, attrs *src)
1562 {
1563   for (; src; src = src->next)
1564     {
1565       if (!attrs_list_member (*dstp, src->dv, src->offset))
1566 	attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1567     }
1568 }
1569 
1570 /* Combine nodes that are not onepart nodes from SRC and SRC2 into
1571    *DSTP.  */
1572 
1573 static void
attrs_list_mpdv_union(attrs ** dstp,attrs * src,attrs * src2)1574 attrs_list_mpdv_union (attrs **dstp, attrs *src, attrs *src2)
1575 {
1576   gcc_assert (!*dstp);
1577   for (; src; src = src->next)
1578     {
1579       if (!dv_onepart_p (src->dv))
1580 	attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1581     }
1582   for (src = src2; src; src = src->next)
1583     {
1584       if (!dv_onepart_p (src->dv)
1585 	  && !attrs_list_member (*dstp, src->dv, src->offset))
1586 	attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1587     }
1588 }
1589 
1590 /* Shared hashtable support.  */
1591 
1592 /* Return true if VARS is shared.  */
1593 
1594 static inline bool
shared_hash_shared(shared_hash * vars)1595 shared_hash_shared (shared_hash *vars)
1596 {
1597   return vars->refcount > 1;
1598 }
1599 
1600 /* Return the hash table for VARS.  */
1601 
1602 static inline variable_table_type *
shared_hash_htab(shared_hash * vars)1603 shared_hash_htab (shared_hash *vars)
1604 {
1605   return vars->htab;
1606 }
1607 
1608 /* Return true if VAR is shared, or maybe because VARS is shared.  */
1609 
1610 static inline bool
shared_var_p(variable * var,shared_hash * vars)1611 shared_var_p (variable *var, shared_hash *vars)
1612 {
1613   /* Don't count an entry in the changed_variables table as a duplicate.  */
1614   return ((var->refcount > 1 + (int) var->in_changed_variables)
1615 	  || shared_hash_shared (vars));
1616 }
1617 
1618 /* Copy variables into a new hash table.  */
1619 
1620 static shared_hash *
shared_hash_unshare(shared_hash * vars)1621 shared_hash_unshare (shared_hash *vars)
1622 {
1623   shared_hash *new_vars = new shared_hash;
1624   gcc_assert (vars->refcount > 1);
1625   new_vars->refcount = 1;
1626   new_vars->htab = new variable_table_type (vars->htab->elements () + 3);
1627   vars_copy (new_vars->htab, vars->htab);
1628   vars->refcount--;
1629   return new_vars;
1630 }
1631 
1632 /* Increment reference counter on VARS and return it.  */
1633 
1634 static inline shared_hash *
shared_hash_copy(shared_hash * vars)1635 shared_hash_copy (shared_hash *vars)
1636 {
1637   vars->refcount++;
1638   return vars;
1639 }
1640 
1641 /* Decrement reference counter and destroy hash table if not shared
1642    anymore.  */
1643 
1644 static void
shared_hash_destroy(shared_hash * vars)1645 shared_hash_destroy (shared_hash *vars)
1646 {
1647   gcc_checking_assert (vars->refcount > 0);
1648   if (--vars->refcount == 0)
1649     {
1650       delete vars->htab;
1651       delete vars;
1652     }
1653 }
1654 
1655 /* Unshare *PVARS if shared and return slot for DV.  If INS is
1656    INSERT, insert it if not already present.  */
1657 
1658 static inline variable **
shared_hash_find_slot_unshare_1(shared_hash ** pvars,decl_or_value dv,hashval_t dvhash,enum insert_option ins)1659 shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
1660 				 hashval_t dvhash, enum insert_option ins)
1661 {
1662   if (shared_hash_shared (*pvars))
1663     *pvars = shared_hash_unshare (*pvars);
1664   return shared_hash_htab (*pvars)->find_slot_with_hash (dv, dvhash, ins);
1665 }
1666 
1667 static inline variable **
shared_hash_find_slot_unshare(shared_hash ** pvars,decl_or_value dv,enum insert_option ins)1668 shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
1669 			       enum insert_option ins)
1670 {
1671   return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
1672 }
1673 
1674 /* Return slot for DV, if it is already present in the hash table.
1675    If it is not present, insert it only VARS is not shared, otherwise
1676    return NULL.  */
1677 
1678 static inline variable **
shared_hash_find_slot_1(shared_hash * vars,decl_or_value dv,hashval_t dvhash)1679 shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
1680 {
1681   return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash,
1682 						       shared_hash_shared (vars)
1683 						       ? NO_INSERT : INSERT);
1684 }
1685 
1686 static inline variable **
shared_hash_find_slot(shared_hash * vars,decl_or_value dv)1687 shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
1688 {
1689   return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
1690 }
1691 
1692 /* Return slot for DV only if it is already present in the hash table.  */
1693 
1694 static inline variable **
shared_hash_find_slot_noinsert_1(shared_hash * vars,decl_or_value dv,hashval_t dvhash)1695 shared_hash_find_slot_noinsert_1 (shared_hash *vars, decl_or_value dv,
1696 				  hashval_t dvhash)
1697 {
1698   return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash, NO_INSERT);
1699 }
1700 
1701 static inline variable **
shared_hash_find_slot_noinsert(shared_hash * vars,decl_or_value dv)1702 shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
1703 {
1704   return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
1705 }
1706 
1707 /* Return variable for DV or NULL if not already present in the hash
1708    table.  */
1709 
1710 static inline variable *
shared_hash_find_1(shared_hash * vars,decl_or_value dv,hashval_t dvhash)1711 shared_hash_find_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
1712 {
1713   return shared_hash_htab (vars)->find_with_hash (dv, dvhash);
1714 }
1715 
1716 static inline variable *
shared_hash_find(shared_hash * vars,decl_or_value dv)1717 shared_hash_find (shared_hash *vars, decl_or_value dv)
1718 {
1719   return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
1720 }
1721 
1722 /* Return true if TVAL is better than CVAL as a canonival value.  We
1723    choose lowest-numbered VALUEs, using the RTX address as a
1724    tie-breaker.  The idea is to arrange them into a star topology,
1725    such that all of them are at most one step away from the canonical
1726    value, and the canonical value has backlinks to all of them, in
1727    addition to all the actual locations.  We don't enforce this
1728    topology throughout the entire dataflow analysis, though.
1729  */
1730 
1731 static inline bool
canon_value_cmp(rtx tval,rtx cval)1732 canon_value_cmp (rtx tval, rtx cval)
1733 {
1734   return !cval
1735     || CSELIB_VAL_PTR (tval)->uid < CSELIB_VAL_PTR (cval)->uid;
1736 }
1737 
1738 static bool dst_can_be_shared;
1739 
1740 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
1741 
1742 static variable **
unshare_variable(dataflow_set * set,variable ** slot,variable * var,enum var_init_status initialized)1743 unshare_variable (dataflow_set *set, variable **slot, variable *var,
1744 		  enum var_init_status initialized)
1745 {
1746   variable *new_var;
1747   int i;
1748 
1749   new_var = onepart_pool_allocate (var->onepart);
1750   new_var->dv = var->dv;
1751   new_var->refcount = 1;
1752   var->refcount--;
1753   new_var->n_var_parts = var->n_var_parts;
1754   new_var->onepart = var->onepart;
1755   new_var->in_changed_variables = false;
1756 
1757   if (! flag_var_tracking_uninit)
1758     initialized = VAR_INIT_STATUS_INITIALIZED;
1759 
1760   for (i = 0; i < var->n_var_parts; i++)
1761     {
1762       location_chain *node;
1763       location_chain **nextp;
1764 
1765       if (i == 0 && var->onepart)
1766 	{
1767 	  /* One-part auxiliary data is only used while emitting
1768 	     notes, so propagate it to the new variable in the active
1769 	     dataflow set.  If we're not emitting notes, this will be
1770 	     a no-op.  */
1771 	  gcc_checking_assert (!VAR_LOC_1PAUX (var) || emit_notes);
1772 	  VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (var);
1773 	  VAR_LOC_1PAUX (var) = NULL;
1774 	}
1775       else
1776 	VAR_PART_OFFSET (new_var, i) = VAR_PART_OFFSET (var, i);
1777       nextp = &new_var->var_part[i].loc_chain;
1778       for (node = var->var_part[i].loc_chain; node; node = node->next)
1779 	{
1780 	  location_chain *new_lc;
1781 
1782 	  new_lc = new location_chain;
1783 	  new_lc->next = NULL;
1784 	  if (node->init > initialized)
1785 	    new_lc->init = node->init;
1786 	  else
1787 	    new_lc->init = initialized;
1788 	  if (node->set_src && !(MEM_P (node->set_src)))
1789 	    new_lc->set_src = node->set_src;
1790 	  else
1791 	    new_lc->set_src = NULL;
1792 	  new_lc->loc = node->loc;
1793 
1794 	  *nextp = new_lc;
1795 	  nextp = &new_lc->next;
1796 	}
1797 
1798       new_var->var_part[i].cur_loc = var->var_part[i].cur_loc;
1799     }
1800 
1801   dst_can_be_shared = false;
1802   if (shared_hash_shared (set->vars))
1803     slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT);
1804   else if (set->traversed_vars && set->vars != set->traversed_vars)
1805     slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
1806   *slot = new_var;
1807   if (var->in_changed_variables)
1808     {
1809       variable **cslot
1810 	= changed_variables->find_slot_with_hash (var->dv,
1811 						  dv_htab_hash (var->dv),
1812 						  NO_INSERT);
1813       gcc_assert (*cslot == (void *) var);
1814       var->in_changed_variables = false;
1815       variable_htab_free (var);
1816       *cslot = new_var;
1817       new_var->in_changed_variables = true;
1818     }
1819   return slot;
1820 }
1821 
1822 /* Copy all variables from hash table SRC to hash table DST.  */
1823 
1824 static void
vars_copy(variable_table_type * dst,variable_table_type * src)1825 vars_copy (variable_table_type *dst, variable_table_type *src)
1826 {
1827   variable_iterator_type hi;
1828   variable *var;
1829 
1830   FOR_EACH_HASH_TABLE_ELEMENT (*src, var, variable, hi)
1831     {
1832       variable **dstp;
1833       var->refcount++;
1834       dstp = dst->find_slot_with_hash (var->dv, dv_htab_hash (var->dv),
1835 				       INSERT);
1836       *dstp = var;
1837     }
1838 }
1839 
1840 /* Map a decl to its main debug decl.  */
1841 
1842 static inline tree
var_debug_decl(tree decl)1843 var_debug_decl (tree decl)
1844 {
1845   if (decl && VAR_P (decl) && DECL_HAS_DEBUG_EXPR_P (decl))
1846     {
1847       tree debugdecl = DECL_DEBUG_EXPR (decl);
1848       if (DECL_P (debugdecl))
1849 	decl = debugdecl;
1850     }
1851 
1852   return decl;
1853 }
1854 
1855 /* Set the register LOC to contain DV, OFFSET.  */
1856 
1857 static void
var_reg_decl_set(dataflow_set * set,rtx loc,enum var_init_status initialized,decl_or_value dv,HOST_WIDE_INT offset,rtx set_src,enum insert_option iopt)1858 var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1859 		  decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1860 		  enum insert_option iopt)
1861 {
1862   attrs *node;
1863   bool decl_p = dv_is_decl_p (dv);
1864 
1865   if (decl_p)
1866     dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1867 
1868   for (node = set->regs[REGNO (loc)]; node; node = node->next)
1869     if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
1870 	&& node->offset == offset)
1871       break;
1872   if (!node)
1873     attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc);
1874   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1875 }
1876 
1877 /* Return true if we should track a location that is OFFSET bytes from
1878    a variable.  Store the constant offset in *OFFSET_OUT if so.  */
1879 
1880 static bool
track_offset_p(poly_int64 offset,HOST_WIDE_INT * offset_out)1881 track_offset_p (poly_int64 offset, HOST_WIDE_INT *offset_out)
1882 {
1883   HOST_WIDE_INT const_offset;
1884   if (!offset.is_constant (&const_offset)
1885       || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1))
1886     return false;
1887   *offset_out = const_offset;
1888   return true;
1889 }
1890 
1891 /* Return the offset of a register that track_offset_p says we
1892    should track.  */
1893 
1894 static HOST_WIDE_INT
get_tracked_reg_offset(rtx loc)1895 get_tracked_reg_offset (rtx loc)
1896 {
1897   HOST_WIDE_INT offset;
1898   if (!track_offset_p (REG_OFFSET (loc), &offset))
1899     gcc_unreachable ();
1900   return offset;
1901 }
1902 
1903 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  */
1904 
1905 static void
var_reg_set(dataflow_set * set,rtx loc,enum var_init_status initialized,rtx set_src)1906 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1907 	     rtx set_src)
1908 {
1909   tree decl = REG_EXPR (loc);
1910   HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
1911 
1912   var_reg_decl_set (set, loc, initialized,
1913 		    dv_from_decl (decl), offset, set_src, INSERT);
1914 }
1915 
1916 static enum var_init_status
get_init_value(dataflow_set * set,rtx loc,decl_or_value dv)1917 get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
1918 {
1919   variable *var;
1920   int i;
1921   enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
1922 
1923   if (! flag_var_tracking_uninit)
1924     return VAR_INIT_STATUS_INITIALIZED;
1925 
1926   var = shared_hash_find (set->vars, dv);
1927   if (var)
1928     {
1929       for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
1930 	{
1931 	  location_chain *nextp;
1932 	  for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1933 	    if (rtx_equal_p (nextp->loc, loc))
1934 	      {
1935 		ret_val = nextp->init;
1936 		break;
1937 	      }
1938 	}
1939     }
1940 
1941   return ret_val;
1942 }
1943 
1944 /* Delete current content of register LOC in dataflow set SET and set
1945    the register to contain REG_EXPR (LOC), REG_OFFSET (LOC).  If
1946    MODIFY is true, any other live copies of the same variable part are
1947    also deleted from the dataflow set, otherwise the variable part is
1948    assumed to be copied from another location holding the same
1949    part.  */
1950 
1951 static void
var_reg_delete_and_set(dataflow_set * set,rtx loc,bool modify,enum var_init_status initialized,rtx set_src)1952 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1953 			enum var_init_status initialized, rtx set_src)
1954 {
1955   tree decl = REG_EXPR (loc);
1956   HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
1957   attrs *node, *next;
1958   attrs **nextp;
1959 
1960   decl = var_debug_decl (decl);
1961 
1962   if (initialized == VAR_INIT_STATUS_UNKNOWN)
1963     initialized = get_init_value (set, loc, dv_from_decl (decl));
1964 
1965   nextp = &set->regs[REGNO (loc)];
1966   for (node = *nextp; node; node = next)
1967     {
1968       next = node->next;
1969       if (dv_as_opaque (node->dv) != decl || node->offset != offset)
1970 	{
1971 	  delete_variable_part (set, node->loc, node->dv, node->offset);
1972 	  delete node;
1973 	  *nextp = next;
1974 	}
1975       else
1976 	{
1977 	  node->loc = loc;
1978 	  nextp = &node->next;
1979 	}
1980     }
1981   if (modify)
1982     clobber_variable_part (set, loc, dv_from_decl (decl), offset, set_src);
1983   var_reg_set (set, loc, initialized, set_src);
1984 }
1985 
1986 /* Delete the association of register LOC in dataflow set SET with any
1987    variables that aren't onepart.  If CLOBBER is true, also delete any
1988    other live copies of the same variable part, and delete the
1989    association with onepart dvs too.  */
1990 
1991 static void
var_reg_delete(dataflow_set * set,rtx loc,bool clobber)1992 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
1993 {
1994   attrs **nextp = &set->regs[REGNO (loc)];
1995   attrs *node, *next;
1996 
1997   HOST_WIDE_INT offset;
1998   if (clobber && track_offset_p (REG_OFFSET (loc), &offset))
1999     {
2000       tree decl = REG_EXPR (loc);
2001 
2002       decl = var_debug_decl (decl);
2003 
2004       clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
2005     }
2006 
2007   for (node = *nextp; node; node = next)
2008     {
2009       next = node->next;
2010       if (clobber || !dv_onepart_p (node->dv))
2011 	{
2012 	  delete_variable_part (set, node->loc, node->dv, node->offset);
2013 	  delete node;
2014 	  *nextp = next;
2015 	}
2016       else
2017 	nextp = &node->next;
2018     }
2019 }
2020 
2021 /* Delete content of register with number REGNO in dataflow set SET.  */
2022 
2023 static void
var_regno_delete(dataflow_set * set,int regno)2024 var_regno_delete (dataflow_set *set, int regno)
2025 {
2026   attrs **reg = &set->regs[regno];
2027   attrs *node, *next;
2028 
2029   for (node = *reg; node; node = next)
2030     {
2031       next = node->next;
2032       delete_variable_part (set, node->loc, node->dv, node->offset);
2033       delete node;
2034     }
2035   *reg = NULL;
2036 }
2037 
2038 /* Return true if I is the negated value of a power of two.  */
2039 static bool
negative_power_of_two_p(HOST_WIDE_INT i)2040 negative_power_of_two_p (HOST_WIDE_INT i)
2041 {
2042   unsigned HOST_WIDE_INT x = -(unsigned HOST_WIDE_INT)i;
2043   return pow2_or_zerop (x);
2044 }
2045 
2046 /* Strip constant offsets and alignments off of LOC.  Return the base
2047    expression.  */
2048 
2049 static rtx
vt_get_canonicalize_base(rtx loc)2050 vt_get_canonicalize_base (rtx loc)
2051 {
2052   while ((GET_CODE (loc) == PLUS
2053 	  || GET_CODE (loc) == AND)
2054 	 && GET_CODE (XEXP (loc, 1)) == CONST_INT
2055 	 && (GET_CODE (loc) != AND
2056 	     || negative_power_of_two_p (INTVAL (XEXP (loc, 1)))))
2057     loc = XEXP (loc, 0);
2058 
2059   return loc;
2060 }
2061 
2062 /* This caches canonicalized addresses for VALUEs, computed using
2063    information in the global cselib table.  */
2064 static hash_map<rtx, rtx> *global_get_addr_cache;
2065 
2066 /* This caches canonicalized addresses for VALUEs, computed using
2067    information from the global cache and information pertaining to a
2068    basic block being analyzed.  */
2069 static hash_map<rtx, rtx> *local_get_addr_cache;
2070 
2071 static rtx vt_canonicalize_addr (dataflow_set *, rtx);
2072 
2073 /* Return the canonical address for LOC, that must be a VALUE, using a
2074    cached global equivalence or computing it and storing it in the
2075    global cache.  */
2076 
2077 static rtx
get_addr_from_global_cache(rtx const loc)2078 get_addr_from_global_cache (rtx const loc)
2079 {
2080   rtx x;
2081 
2082   gcc_checking_assert (GET_CODE (loc) == VALUE);
2083 
2084   bool existed;
2085   rtx *slot = &global_get_addr_cache->get_or_insert (loc, &existed);
2086   if (existed)
2087     return *slot;
2088 
2089   x = canon_rtx (get_addr (loc));
2090 
2091   /* Tentative, avoiding infinite recursion.  */
2092   *slot = x;
2093 
2094   if (x != loc)
2095     {
2096       rtx nx = vt_canonicalize_addr (NULL, x);
2097       if (nx != x)
2098 	{
2099 	  /* The table may have moved during recursion, recompute
2100 	     SLOT.  */
2101 	  *global_get_addr_cache->get (loc) = x = nx;
2102 	}
2103     }
2104 
2105   return x;
2106 }
2107 
2108 /* Return the canonical address for LOC, that must be a VALUE, using a
2109    cached local equivalence or computing it and storing it in the
2110    local cache.  */
2111 
2112 static rtx
get_addr_from_local_cache(dataflow_set * set,rtx const loc)2113 get_addr_from_local_cache (dataflow_set *set, rtx const loc)
2114 {
2115   rtx x;
2116   decl_or_value dv;
2117   variable *var;
2118   location_chain *l;
2119 
2120   gcc_checking_assert (GET_CODE (loc) == VALUE);
2121 
2122   bool existed;
2123   rtx *slot = &local_get_addr_cache->get_or_insert (loc, &existed);
2124   if (existed)
2125     return *slot;
2126 
2127   x = get_addr_from_global_cache (loc);
2128 
2129   /* Tentative, avoiding infinite recursion.  */
2130   *slot = x;
2131 
2132   /* Recurse to cache local expansion of X, or if we need to search
2133      for a VALUE in the expansion.  */
2134   if (x != loc)
2135     {
2136       rtx nx = vt_canonicalize_addr (set, x);
2137       if (nx != x)
2138 	{
2139 	  slot = local_get_addr_cache->get (loc);
2140 	  *slot = x = nx;
2141 	}
2142       return x;
2143     }
2144 
2145   dv = dv_from_rtx (x);
2146   var = shared_hash_find (set->vars, dv);
2147   if (!var)
2148     return x;
2149 
2150   /* Look for an improved equivalent expression.  */
2151   for (l = var->var_part[0].loc_chain; l; l = l->next)
2152     {
2153       rtx base = vt_get_canonicalize_base (l->loc);
2154       if (GET_CODE (base) == VALUE
2155 	  && canon_value_cmp (base, loc))
2156 	{
2157 	  rtx nx = vt_canonicalize_addr (set, l->loc);
2158 	  if (x != nx)
2159 	    {
2160 	      slot = local_get_addr_cache->get (loc);
2161 	      *slot = x = nx;
2162 	    }
2163 	  break;
2164 	}
2165     }
2166 
2167   return x;
2168 }
2169 
2170 /* Canonicalize LOC using equivalences from SET in addition to those
2171    in the cselib static table.  It expects a VALUE-based expression,
2172    and it will only substitute VALUEs with other VALUEs or
2173    function-global equivalences, so that, if two addresses have base
2174    VALUEs that are locally or globally related in ways that
2175    memrefs_conflict_p cares about, they will both canonicalize to
2176    expressions that have the same base VALUE.
2177 
2178    The use of VALUEs as canonical base addresses enables the canonical
2179    RTXs to remain unchanged globally, if they resolve to a constant,
2180    or throughout a basic block otherwise, so that they can be cached
2181    and the cache needs not be invalidated when REGs, MEMs or such
2182    change.  */
2183 
2184 static rtx
vt_canonicalize_addr(dataflow_set * set,rtx oloc)2185 vt_canonicalize_addr (dataflow_set *set, rtx oloc)
2186 {
2187   poly_int64 ofst = 0, term;
2188   machine_mode mode = GET_MODE (oloc);
2189   rtx loc = oloc;
2190   rtx x;
2191   bool retry = true;
2192 
2193   while (retry)
2194     {
2195       while (GET_CODE (loc) == PLUS
2196 	     && poly_int_rtx_p (XEXP (loc, 1), &term))
2197 	{
2198 	  ofst += term;
2199 	  loc = XEXP (loc, 0);
2200 	}
2201 
2202       /* Alignment operations can't normally be combined, so just
2203 	 canonicalize the base and we're done.  We'll normally have
2204 	 only one stack alignment anyway.  */
2205       if (GET_CODE (loc) == AND
2206 	  && GET_CODE (XEXP (loc, 1)) == CONST_INT
2207 	  && negative_power_of_two_p (INTVAL (XEXP (loc, 1))))
2208 	{
2209 	  x = vt_canonicalize_addr (set, XEXP (loc, 0));
2210 	  if (x != XEXP (loc, 0))
2211 	    loc = gen_rtx_AND (mode, x, XEXP (loc, 1));
2212 	  retry = false;
2213 	}
2214 
2215       if (GET_CODE (loc) == VALUE)
2216 	{
2217 	  if (set)
2218 	    loc = get_addr_from_local_cache (set, loc);
2219 	  else
2220 	    loc = get_addr_from_global_cache (loc);
2221 
2222 	  /* Consolidate plus_constants.  */
2223 	  while (maybe_ne (ofst, 0)
2224 		 && GET_CODE (loc) == PLUS
2225 		 && poly_int_rtx_p (XEXP (loc, 1), &term))
2226 	    {
2227 	      ofst += term;
2228 	      loc = XEXP (loc, 0);
2229 	    }
2230 
2231 	  retry = false;
2232 	}
2233       else
2234 	{
2235 	  x = canon_rtx (loc);
2236 	  if (retry)
2237 	    retry = (x != loc);
2238 	  loc = x;
2239 	}
2240     }
2241 
2242   /* Add OFST back in.  */
2243   if (maybe_ne (ofst, 0))
2244     {
2245       /* Don't build new RTL if we can help it.  */
2246       if (strip_offset (oloc, &term) == loc && known_eq (term, ofst))
2247 	return oloc;
2248 
2249       loc = plus_constant (mode, loc, ofst);
2250     }
2251 
2252   return loc;
2253 }
2254 
2255 /* Return true iff there's a true dependence between MLOC and LOC.
2256    MADDR must be a canonicalized version of MLOC's address.  */
2257 
2258 static inline bool
vt_canon_true_dep(dataflow_set * set,rtx mloc,rtx maddr,rtx loc)2259 vt_canon_true_dep (dataflow_set *set, rtx mloc, rtx maddr, rtx loc)
2260 {
2261   if (GET_CODE (loc) != MEM)
2262     return false;
2263 
2264   rtx addr = vt_canonicalize_addr (set, XEXP (loc, 0));
2265   if (!canon_true_dependence (mloc, GET_MODE (mloc), maddr, loc, addr))
2266     return false;
2267 
2268   return true;
2269 }
2270 
2271 /* Hold parameters for the hashtab traversal function
2272    drop_overlapping_mem_locs, see below.  */
2273 
2274 struct overlapping_mems
2275 {
2276   dataflow_set *set;
2277   rtx loc, addr;
2278 };
2279 
2280 /* Remove all MEMs that overlap with COMS->LOC from the location list
2281    of a hash table entry for a onepart variable.  COMS->ADDR must be a
2282    canonicalized form of COMS->LOC's address, and COMS->LOC must be
2283    canonicalized itself.  */
2284 
2285 int
drop_overlapping_mem_locs(variable ** slot,overlapping_mems * coms)2286 drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
2287 {
2288   dataflow_set *set = coms->set;
2289   rtx mloc = coms->loc, addr = coms->addr;
2290   variable *var = *slot;
2291 
2292   if (var->onepart != NOT_ONEPART)
2293     {
2294       location_chain *loc, **locp;
2295       bool changed = false;
2296       rtx cur_loc;
2297 
2298       gcc_assert (var->n_var_parts == 1);
2299 
2300       if (shared_var_p (var, set->vars))
2301 	{
2302 	  for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
2303 	    if (vt_canon_true_dep (set, mloc, addr, loc->loc))
2304 	      break;
2305 
2306 	  if (!loc)
2307 	    return 1;
2308 
2309 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
2310 	  var = *slot;
2311 	  gcc_assert (var->n_var_parts == 1);
2312 	}
2313 
2314       if (VAR_LOC_1PAUX (var))
2315 	cur_loc = VAR_LOC_FROM (var);
2316       else
2317 	cur_loc = var->var_part[0].cur_loc;
2318 
2319       for (locp = &var->var_part[0].loc_chain, loc = *locp;
2320 	   loc; loc = *locp)
2321 	{
2322 	  if (!vt_canon_true_dep (set, mloc, addr, loc->loc))
2323 	    {
2324 	      locp = &loc->next;
2325 	      continue;
2326 	    }
2327 
2328 	  *locp = loc->next;
2329 	  /* If we have deleted the location which was last emitted
2330 	     we have to emit new location so add the variable to set
2331 	     of changed variables.  */
2332 	  if (cur_loc == loc->loc)
2333 	    {
2334 	      changed = true;
2335 	      var->var_part[0].cur_loc = NULL;
2336 	      if (VAR_LOC_1PAUX (var))
2337 		VAR_LOC_FROM (var) = NULL;
2338 	    }
2339 	  delete loc;
2340 	}
2341 
2342       if (!var->var_part[0].loc_chain)
2343 	{
2344 	  var->n_var_parts--;
2345 	  changed = true;
2346 	}
2347       if (changed)
2348 	variable_was_changed (var, set);
2349     }
2350 
2351   return 1;
2352 }
2353 
2354 /* Remove from SET all VALUE bindings to MEMs that overlap with LOC.  */
2355 
2356 static void
clobber_overlapping_mems(dataflow_set * set,rtx loc)2357 clobber_overlapping_mems (dataflow_set *set, rtx loc)
2358 {
2359   struct overlapping_mems coms;
2360 
2361   gcc_checking_assert (GET_CODE (loc) == MEM);
2362 
2363   coms.set = set;
2364   coms.loc = canon_rtx (loc);
2365   coms.addr = vt_canonicalize_addr (set, XEXP (loc, 0));
2366 
2367   set->traversed_vars = set->vars;
2368   shared_hash_htab (set->vars)
2369     ->traverse <overlapping_mems*, drop_overlapping_mem_locs> (&coms);
2370   set->traversed_vars = NULL;
2371 }
2372 
2373 /* Set the location of DV, OFFSET as the MEM LOC.  */
2374 
2375 static void
var_mem_decl_set(dataflow_set * set,rtx loc,enum var_init_status initialized,decl_or_value dv,HOST_WIDE_INT offset,rtx set_src,enum insert_option iopt)2376 var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
2377 		  decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
2378 		  enum insert_option iopt)
2379 {
2380   if (dv_is_decl_p (dv))
2381     dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
2382 
2383   set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
2384 }
2385 
2386 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
2387    SET to LOC.
2388    Adjust the address first if it is stack pointer based.  */
2389 
2390 static void
var_mem_set(dataflow_set * set,rtx loc,enum var_init_status initialized,rtx set_src)2391 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
2392 	     rtx set_src)
2393 {
2394   tree decl = MEM_EXPR (loc);
2395   HOST_WIDE_INT offset = int_mem_offset (loc);
2396 
2397   var_mem_decl_set (set, loc, initialized,
2398 		    dv_from_decl (decl), offset, set_src, INSERT);
2399 }
2400 
2401 /* Delete and set the location part of variable MEM_EXPR (LOC) in
2402    dataflow set SET to LOC.  If MODIFY is true, any other live copies
2403    of the same variable part are also deleted from the dataflow set,
2404    otherwise the variable part is assumed to be copied from another
2405    location holding the same part.
2406    Adjust the address first if it is stack pointer based.  */
2407 
2408 static void
var_mem_delete_and_set(dataflow_set * set,rtx loc,bool modify,enum var_init_status initialized,rtx set_src)2409 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
2410 			enum var_init_status initialized, rtx set_src)
2411 {
2412   tree decl = MEM_EXPR (loc);
2413   HOST_WIDE_INT offset = int_mem_offset (loc);
2414 
2415   clobber_overlapping_mems (set, loc);
2416   decl = var_debug_decl (decl);
2417 
2418   if (initialized == VAR_INIT_STATUS_UNKNOWN)
2419     initialized = get_init_value (set, loc, dv_from_decl (decl));
2420 
2421   if (modify)
2422     clobber_variable_part (set, NULL, dv_from_decl (decl), offset, set_src);
2423   var_mem_set (set, loc, initialized, set_src);
2424 }
2425 
2426 /* Delete the location part LOC from dataflow set SET.  If CLOBBER is
2427    true, also delete any other live copies of the same variable part.
2428    Adjust the address first if it is stack pointer based.  */
2429 
2430 static void
var_mem_delete(dataflow_set * set,rtx loc,bool clobber)2431 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
2432 {
2433   tree decl = MEM_EXPR (loc);
2434   HOST_WIDE_INT offset = int_mem_offset (loc);
2435 
2436   clobber_overlapping_mems (set, loc);
2437   decl = var_debug_decl (decl);
2438   if (clobber)
2439     clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
2440   delete_variable_part (set, loc, dv_from_decl (decl), offset);
2441 }
2442 
2443 /* Return true if LOC should not be expanded for location expressions,
2444    or used in them.  */
2445 
2446 static inline bool
unsuitable_loc(rtx loc)2447 unsuitable_loc (rtx loc)
2448 {
2449   switch (GET_CODE (loc))
2450     {
2451     case PC:
2452     case SCRATCH:
2453     case ASM_INPUT:
2454     case ASM_OPERANDS:
2455       return true;
2456 
2457     default:
2458       return false;
2459     }
2460 }
2461 
2462 /* Bind VAL to LOC in SET.  If MODIFIED, detach LOC from any values
2463    bound to it.  */
2464 
2465 static inline void
val_bind(dataflow_set * set,rtx val,rtx loc,bool modified)2466 val_bind (dataflow_set *set, rtx val, rtx loc, bool modified)
2467 {
2468   if (REG_P (loc))
2469     {
2470       if (modified)
2471 	var_regno_delete (set, REGNO (loc));
2472       var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2473 			dv_from_value (val), 0, NULL_RTX, INSERT);
2474     }
2475   else if (MEM_P (loc))
2476     {
2477       struct elt_loc_list *l = CSELIB_VAL_PTR (val)->locs;
2478 
2479       if (modified)
2480 	clobber_overlapping_mems (set, loc);
2481 
2482       if (l && GET_CODE (l->loc) == VALUE)
2483 	l = canonical_cselib_val (CSELIB_VAL_PTR (l->loc))->locs;
2484 
2485       /* If this MEM is a global constant, we don't need it in the
2486 	 dynamic tables.  ??? We should test this before emitting the
2487 	 micro-op in the first place.  */
2488       while (l)
2489 	if (GET_CODE (l->loc) == MEM && XEXP (l->loc, 0) == XEXP (loc, 0))
2490 	  break;
2491 	else
2492 	  l = l->next;
2493 
2494       if (!l)
2495 	var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2496 			  dv_from_value (val), 0, NULL_RTX, INSERT);
2497     }
2498   else
2499     {
2500       /* Other kinds of equivalences are necessarily static, at least
2501 	 so long as we do not perform substitutions while merging
2502 	 expressions.  */
2503       gcc_unreachable ();
2504       set_variable_part (set, loc, dv_from_value (val), 0,
2505 			 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2506     }
2507 }
2508 
2509 /* Bind a value to a location it was just stored in.  If MODIFIED
2510    holds, assume the location was modified, detaching it from any
2511    values bound to it.  */
2512 
2513 static void
val_store(dataflow_set * set,rtx val,rtx loc,rtx_insn * insn,bool modified)2514 val_store (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn,
2515 	   bool modified)
2516 {
2517   cselib_val *v = CSELIB_VAL_PTR (val);
2518 
2519   gcc_assert (cselib_preserved_value_p (v));
2520 
2521   if (dump_file)
2522     {
2523       fprintf (dump_file, "%i: ", insn ? INSN_UID (insn) : 0);
2524       print_inline_rtx (dump_file, loc, 0);
2525       fprintf (dump_file, " evaluates to ");
2526       print_inline_rtx (dump_file, val, 0);
2527       if (v->locs)
2528 	{
2529 	  struct elt_loc_list *l;
2530 	  for (l = v->locs; l; l = l->next)
2531 	    {
2532 	      fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn));
2533 	      print_inline_rtx (dump_file, l->loc, 0);
2534 	    }
2535 	}
2536       fprintf (dump_file, "\n");
2537     }
2538 
2539   gcc_checking_assert (!unsuitable_loc (loc));
2540 
2541   val_bind (set, val, loc, modified);
2542 }
2543 
2544 /* Clear (canonical address) slots that reference X.  */
2545 
2546 bool
local_get_addr_clear_given_value(rtx const &,rtx * slot,rtx x)2547 local_get_addr_clear_given_value (rtx const &, rtx *slot, rtx x)
2548 {
2549   if (vt_get_canonicalize_base (*slot) == x)
2550     *slot = NULL;
2551   return true;
2552 }
2553 
2554 /* Reset this node, detaching all its equivalences.  Return the slot
2555    in the variable hash table that holds dv, if there is one.  */
2556 
2557 static void
val_reset(dataflow_set * set,decl_or_value dv)2558 val_reset (dataflow_set *set, decl_or_value dv)
2559 {
2560   variable *var = shared_hash_find (set->vars, dv) ;
2561   location_chain *node;
2562   rtx cval;
2563 
2564   if (!var || !var->n_var_parts)
2565     return;
2566 
2567   gcc_assert (var->n_var_parts == 1);
2568 
2569   if (var->onepart == ONEPART_VALUE)
2570     {
2571       rtx x = dv_as_value (dv);
2572 
2573       /* Relationships in the global cache don't change, so reset the
2574 	 local cache entry only.  */
2575       rtx *slot = local_get_addr_cache->get (x);
2576       if (slot)
2577 	{
2578 	  /* If the value resolved back to itself, odds are that other
2579 	     values may have cached it too.  These entries now refer
2580 	     to the old X, so detach them too.  Entries that used the
2581 	     old X but resolved to something else remain ok as long as
2582 	     that something else isn't also reset.  */
2583 	  if (*slot == x)
2584 	    local_get_addr_cache
2585 	      ->traverse<rtx, local_get_addr_clear_given_value> (x);
2586 	  *slot = NULL;
2587 	}
2588     }
2589 
2590   cval = NULL;
2591   for (node = var->var_part[0].loc_chain; node; node = node->next)
2592     if (GET_CODE (node->loc) == VALUE
2593 	&& canon_value_cmp (node->loc, cval))
2594       cval = node->loc;
2595 
2596   for (node = var->var_part[0].loc_chain; node; node = node->next)
2597     if (GET_CODE (node->loc) == VALUE && cval != node->loc)
2598       {
2599 	/* Redirect the equivalence link to the new canonical
2600 	   value, or simply remove it if it would point at
2601 	   itself.  */
2602 	if (cval)
2603 	  set_variable_part (set, cval, dv_from_value (node->loc),
2604 			     0, node->init, node->set_src, NO_INSERT);
2605 	delete_variable_part (set, dv_as_value (dv),
2606 			      dv_from_value (node->loc), 0);
2607       }
2608 
2609   if (cval)
2610     {
2611       decl_or_value cdv = dv_from_value (cval);
2612 
2613       /* Keep the remaining values connected, accumulating links
2614 	 in the canonical value.  */
2615       for (node = var->var_part[0].loc_chain; node; node = node->next)
2616 	{
2617 	  if (node->loc == cval)
2618 	    continue;
2619 	  else if (GET_CODE (node->loc) == REG)
2620 	    var_reg_decl_set (set, node->loc, node->init, cdv, 0,
2621 			      node->set_src, NO_INSERT);
2622 	  else if (GET_CODE (node->loc) == MEM)
2623 	    var_mem_decl_set (set, node->loc, node->init, cdv, 0,
2624 			      node->set_src, NO_INSERT);
2625 	  else
2626 	    set_variable_part (set, node->loc, cdv, 0,
2627 			       node->init, node->set_src, NO_INSERT);
2628 	}
2629     }
2630 
2631   /* We remove this last, to make sure that the canonical value is not
2632      removed to the point of requiring reinsertion.  */
2633   if (cval)
2634     delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
2635 
2636   clobber_variable_part (set, NULL, dv, 0, NULL);
2637 }
2638 
2639 /* Find the values in a given location and map the val to another
2640    value, if it is unique, or add the location as one holding the
2641    value.  */
2642 
2643 static void
val_resolve(dataflow_set * set,rtx val,rtx loc,rtx_insn * insn)2644 val_resolve (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn)
2645 {
2646   decl_or_value dv = dv_from_value (val);
2647 
2648   if (dump_file && (dump_flags & TDF_DETAILS))
2649     {
2650       if (insn)
2651 	fprintf (dump_file, "%i: ", INSN_UID (insn));
2652       else
2653 	fprintf (dump_file, "head: ");
2654       print_inline_rtx (dump_file, val, 0);
2655       fputs (" is at ", dump_file);
2656       print_inline_rtx (dump_file, loc, 0);
2657       fputc ('\n', dump_file);
2658     }
2659 
2660   val_reset (set, dv);
2661 
2662   gcc_checking_assert (!unsuitable_loc (loc));
2663 
2664   if (REG_P (loc))
2665     {
2666       attrs *node, *found = NULL;
2667 
2668       for (node = set->regs[REGNO (loc)]; node; node = node->next)
2669 	if (dv_is_value_p (node->dv)
2670 	    && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc))
2671 	  {
2672 	    found = node;
2673 
2674 	    /* Map incoming equivalences.  ??? Wouldn't it be nice if
2675 	     we just started sharing the location lists?  Maybe a
2676 	     circular list ending at the value itself or some
2677 	     such.  */
2678 	    set_variable_part (set, dv_as_value (node->dv),
2679 			       dv_from_value (val), node->offset,
2680 			       VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2681 	    set_variable_part (set, val, node->dv, node->offset,
2682 			       VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2683 	  }
2684 
2685       /* If we didn't find any equivalence, we need to remember that
2686 	 this value is held in the named register.  */
2687       if (found)
2688 	return;
2689     }
2690   /* ??? Attempt to find and merge equivalent MEMs or other
2691      expressions too.  */
2692 
2693   val_bind (set, val, loc, false);
2694 }
2695 
2696 /* Initialize dataflow set SET to be empty.
2697    VARS_SIZE is the initial size of hash table VARS.  */
2698 
2699 static void
dataflow_set_init(dataflow_set * set)2700 dataflow_set_init (dataflow_set *set)
2701 {
2702   init_attrs_list_set (set->regs);
2703   set->vars = shared_hash_copy (empty_shared_hash);
2704   set->stack_adjust = 0;
2705   set->traversed_vars = NULL;
2706 }
2707 
2708 /* Delete the contents of dataflow set SET.  */
2709 
2710 static void
dataflow_set_clear(dataflow_set * set)2711 dataflow_set_clear (dataflow_set *set)
2712 {
2713   int i;
2714 
2715   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2716     attrs_list_clear (&set->regs[i]);
2717 
2718   shared_hash_destroy (set->vars);
2719   set->vars = shared_hash_copy (empty_shared_hash);
2720 }
2721 
2722 /* Copy the contents of dataflow set SRC to DST.  */
2723 
2724 static void
dataflow_set_copy(dataflow_set * dst,dataflow_set * src)2725 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
2726 {
2727   int i;
2728 
2729   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2730     attrs_list_copy (&dst->regs[i], src->regs[i]);
2731 
2732   shared_hash_destroy (dst->vars);
2733   dst->vars = shared_hash_copy (src->vars);
2734   dst->stack_adjust = src->stack_adjust;
2735 }
2736 
2737 /* Information for merging lists of locations for a given offset of variable.
2738  */
2739 struct variable_union_info
2740 {
2741   /* Node of the location chain.  */
2742   location_chain *lc;
2743 
2744   /* The sum of positions in the input chains.  */
2745   int pos;
2746 
2747   /* The position in the chain of DST dataflow set.  */
2748   int pos_dst;
2749 };
2750 
2751 /* Buffer for location list sorting and its allocated size.  */
2752 static struct variable_union_info *vui_vec;
2753 static int vui_allocated;
2754 
2755 /* Compare function for qsort, order the structures by POS element.  */
2756 
2757 static int
variable_union_info_cmp_pos(const void * n1,const void * n2)2758 variable_union_info_cmp_pos (const void *n1, const void *n2)
2759 {
2760   const struct variable_union_info *const i1 =
2761     (const struct variable_union_info *) n1;
2762   const struct variable_union_info *const i2 =
2763     ( const struct variable_union_info *) n2;
2764 
2765   if (i1->pos != i2->pos)
2766     return i1->pos - i2->pos;
2767 
2768   return (i1->pos_dst - i2->pos_dst);
2769 }
2770 
2771 /* Compute union of location parts of variable *SLOT and the same variable
2772    from hash table DATA.  Compute "sorted" union of the location chains
2773    for common offsets, i.e. the locations of a variable part are sorted by
2774    a priority where the priority is the sum of the positions in the 2 chains
2775    (if a location is only in one list the position in the second list is
2776    defined to be larger than the length of the chains).
2777    When we are updating the location parts the newest location is in the
2778    beginning of the chain, so when we do the described "sorted" union
2779    we keep the newest locations in the beginning.  */
2780 
2781 static int
variable_union(variable * src,dataflow_set * set)2782 variable_union (variable *src, dataflow_set *set)
2783 {
2784   variable *dst;
2785   variable **dstp;
2786   int i, j, k;
2787 
2788   dstp = shared_hash_find_slot (set->vars, src->dv);
2789   if (!dstp || !*dstp)
2790     {
2791       src->refcount++;
2792 
2793       dst_can_be_shared = false;
2794       if (!dstp)
2795 	dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT);
2796 
2797       *dstp = src;
2798 
2799       /* Continue traversing the hash table.  */
2800       return 1;
2801     }
2802   else
2803     dst = *dstp;
2804 
2805   gcc_assert (src->n_var_parts);
2806   gcc_checking_assert (src->onepart == dst->onepart);
2807 
2808   /* We can combine one-part variables very efficiently, because their
2809      entries are in canonical order.  */
2810   if (src->onepart)
2811     {
2812       location_chain **nodep, *dnode, *snode;
2813 
2814       gcc_assert (src->n_var_parts == 1
2815 		  && dst->n_var_parts == 1);
2816 
2817       snode = src->var_part[0].loc_chain;
2818       gcc_assert (snode);
2819 
2820     restart_onepart_unshared:
2821       nodep = &dst->var_part[0].loc_chain;
2822       dnode = *nodep;
2823       gcc_assert (dnode);
2824 
2825       while (snode)
2826 	{
2827 	  int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1;
2828 
2829 	  if (r > 0)
2830 	    {
2831 	      location_chain *nnode;
2832 
2833 	      if (shared_var_p (dst, set->vars))
2834 		{
2835 		  dstp = unshare_variable (set, dstp, dst,
2836 					   VAR_INIT_STATUS_INITIALIZED);
2837 		  dst = *dstp;
2838 		  goto restart_onepart_unshared;
2839 		}
2840 
2841 	      *nodep = nnode = new location_chain;
2842 	      nnode->loc = snode->loc;
2843 	      nnode->init = snode->init;
2844 	      if (!snode->set_src || MEM_P (snode->set_src))
2845 		nnode->set_src = NULL;
2846 	      else
2847 		nnode->set_src = snode->set_src;
2848 	      nnode->next = dnode;
2849 	      dnode = nnode;
2850 	    }
2851 	  else if (r == 0)
2852 	    gcc_checking_assert (rtx_equal_p (dnode->loc, snode->loc));
2853 
2854 	  if (r >= 0)
2855 	    snode = snode->next;
2856 
2857 	  nodep = &dnode->next;
2858 	  dnode = *nodep;
2859 	}
2860 
2861       return 1;
2862     }
2863 
2864   gcc_checking_assert (!src->onepart);
2865 
2866   /* Count the number of location parts, result is K.  */
2867   for (i = 0, j = 0, k = 0;
2868        i < src->n_var_parts && j < dst->n_var_parts; k++)
2869     {
2870       if (VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
2871 	{
2872 	  i++;
2873 	  j++;
2874 	}
2875       else if (VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
2876 	i++;
2877       else
2878 	j++;
2879     }
2880   k += src->n_var_parts - i;
2881   k += dst->n_var_parts - j;
2882 
2883   /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2884      thus there are at most MAX_VAR_PARTS different offsets.  */
2885   gcc_checking_assert (dst->onepart ? k == 1 : k <= MAX_VAR_PARTS);
2886 
2887   if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
2888     {
2889       dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
2890       dst = *dstp;
2891     }
2892 
2893   i = src->n_var_parts - 1;
2894   j = dst->n_var_parts - 1;
2895   dst->n_var_parts = k;
2896 
2897   for (k--; k >= 0; k--)
2898     {
2899       location_chain *node, *node2;
2900 
2901       if (i >= 0 && j >= 0
2902 	  && VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
2903 	{
2904 	  /* Compute the "sorted" union of the chains, i.e. the locations which
2905 	     are in both chains go first, they are sorted by the sum of
2906 	     positions in the chains.  */
2907 	  int dst_l, src_l;
2908 	  int ii, jj, n;
2909 	  struct variable_union_info *vui;
2910 
2911 	  /* If DST is shared compare the location chains.
2912 	     If they are different we will modify the chain in DST with
2913 	     high probability so make a copy of DST.  */
2914 	  if (shared_var_p (dst, set->vars))
2915 	    {
2916 	      for (node = src->var_part[i].loc_chain,
2917 		   node2 = dst->var_part[j].loc_chain; node && node2;
2918 		   node = node->next, node2 = node2->next)
2919 		{
2920 		  if (!((REG_P (node2->loc)
2921 			 && REG_P (node->loc)
2922 			 && REGNO (node2->loc) == REGNO (node->loc))
2923 			|| rtx_equal_p (node2->loc, node->loc)))
2924 		    {
2925 		      if (node2->init < node->init)
2926 		        node2->init = node->init;
2927 		      break;
2928 		    }
2929 		}
2930 	      if (node || node2)
2931 		{
2932 		  dstp = unshare_variable (set, dstp, dst,
2933 					   VAR_INIT_STATUS_UNKNOWN);
2934 		  dst = (variable *)*dstp;
2935 		}
2936 	    }
2937 
2938 	  src_l = 0;
2939 	  for (node = src->var_part[i].loc_chain; node; node = node->next)
2940 	    src_l++;
2941 	  dst_l = 0;
2942 	  for (node = dst->var_part[j].loc_chain; node; node = node->next)
2943 	    dst_l++;
2944 
2945 	  if (dst_l == 1)
2946 	    {
2947 	      /* The most common case, much simpler, no qsort is needed.  */
2948 	      location_chain *dstnode = dst->var_part[j].loc_chain;
2949 	      dst->var_part[k].loc_chain = dstnode;
2950 	      VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
2951 	      node2 = dstnode;
2952 	      for (node = src->var_part[i].loc_chain; node; node = node->next)
2953 		if (!((REG_P (dstnode->loc)
2954 		       && REG_P (node->loc)
2955 		       && REGNO (dstnode->loc) == REGNO (node->loc))
2956 		      || rtx_equal_p (dstnode->loc, node->loc)))
2957 		  {
2958 		    location_chain *new_node;
2959 
2960 		    /* Copy the location from SRC.  */
2961 		    new_node = new location_chain;
2962 		    new_node->loc = node->loc;
2963 		    new_node->init = node->init;
2964 		    if (!node->set_src || MEM_P (node->set_src))
2965 		      new_node->set_src = NULL;
2966 		    else
2967 		      new_node->set_src = node->set_src;
2968 		    node2->next = new_node;
2969 		    node2 = new_node;
2970 		  }
2971 	      node2->next = NULL;
2972 	    }
2973 	  else
2974 	    {
2975 	      if (src_l + dst_l > vui_allocated)
2976 		{
2977 		  vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
2978 		  vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
2979 					vui_allocated);
2980 		}
2981 	      vui = vui_vec;
2982 
2983 	      /* Fill in the locations from DST.  */
2984 	      for (node = dst->var_part[j].loc_chain, jj = 0; node;
2985 		   node = node->next, jj++)
2986 		{
2987 		  vui[jj].lc = node;
2988 		  vui[jj].pos_dst = jj;
2989 
2990 		  /* Pos plus value larger than a sum of 2 valid positions.  */
2991 		  vui[jj].pos = jj + src_l + dst_l;
2992 		}
2993 
2994 	      /* Fill in the locations from SRC.  */
2995 	      n = dst_l;
2996 	      for (node = src->var_part[i].loc_chain, ii = 0; node;
2997 		   node = node->next, ii++)
2998 		{
2999 		  /* Find location from NODE.  */
3000 		  for (jj = 0; jj < dst_l; jj++)
3001 		    {
3002 		      if ((REG_P (vui[jj].lc->loc)
3003 			   && REG_P (node->loc)
3004 			   && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
3005 			  || rtx_equal_p (vui[jj].lc->loc, node->loc))
3006 			{
3007 			  vui[jj].pos = jj + ii;
3008 			  break;
3009 			}
3010 		    }
3011 		  if (jj >= dst_l)	/* The location has not been found.  */
3012 		    {
3013 		      location_chain *new_node;
3014 
3015 		      /* Copy the location from SRC.  */
3016 		      new_node = new location_chain;
3017 		      new_node->loc = node->loc;
3018 		      new_node->init = node->init;
3019 		      if (!node->set_src || MEM_P (node->set_src))
3020 			new_node->set_src = NULL;
3021 		      else
3022 			new_node->set_src = node->set_src;
3023 		      vui[n].lc = new_node;
3024 		      vui[n].pos_dst = src_l + dst_l;
3025 		      vui[n].pos = ii + src_l + dst_l;
3026 		      n++;
3027 		    }
3028 		}
3029 
3030 	      if (dst_l == 2)
3031 		{
3032 		  /* Special case still very common case.  For dst_l == 2
3033 		     all entries dst_l ... n-1 are sorted, with for i >= dst_l
3034 		     vui[i].pos == i + src_l + dst_l.  */
3035 		  if (vui[0].pos > vui[1].pos)
3036 		    {
3037 		      /* Order should be 1, 0, 2... */
3038 		      dst->var_part[k].loc_chain = vui[1].lc;
3039 		      vui[1].lc->next = vui[0].lc;
3040 		      if (n >= 3)
3041 			{
3042 			  vui[0].lc->next = vui[2].lc;
3043 			  vui[n - 1].lc->next = NULL;
3044 			}
3045 		      else
3046 			vui[0].lc->next = NULL;
3047 		      ii = 3;
3048 		    }
3049 		  else
3050 		    {
3051 		      dst->var_part[k].loc_chain = vui[0].lc;
3052 		      if (n >= 3 && vui[2].pos < vui[1].pos)
3053 			{
3054 			  /* Order should be 0, 2, 1, 3... */
3055 			  vui[0].lc->next = vui[2].lc;
3056 			  vui[2].lc->next = vui[1].lc;
3057 			  if (n >= 4)
3058 			    {
3059 			      vui[1].lc->next = vui[3].lc;
3060 			      vui[n - 1].lc->next = NULL;
3061 			    }
3062 			  else
3063 			    vui[1].lc->next = NULL;
3064 			  ii = 4;
3065 			}
3066 		      else
3067 			{
3068 			  /* Order should be 0, 1, 2... */
3069 			  ii = 1;
3070 			  vui[n - 1].lc->next = NULL;
3071 			}
3072 		    }
3073 		  for (; ii < n; ii++)
3074 		    vui[ii - 1].lc->next = vui[ii].lc;
3075 		}
3076 	      else
3077 		{
3078 		  qsort (vui, n, sizeof (struct variable_union_info),
3079 			 variable_union_info_cmp_pos);
3080 
3081 		  /* Reconnect the nodes in sorted order.  */
3082 		  for (ii = 1; ii < n; ii++)
3083 		    vui[ii - 1].lc->next = vui[ii].lc;
3084 		  vui[n - 1].lc->next = NULL;
3085 		  dst->var_part[k].loc_chain = vui[0].lc;
3086 		}
3087 
3088 	      VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
3089 	    }
3090 	  i--;
3091 	  j--;
3092 	}
3093       else if ((i >= 0 && j >= 0
3094 		&& VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
3095 	       || i < 0)
3096 	{
3097 	  dst->var_part[k] = dst->var_part[j];
3098 	  j--;
3099 	}
3100       else if ((i >= 0 && j >= 0
3101 		&& VAR_PART_OFFSET (src, i) > VAR_PART_OFFSET (dst, j))
3102 	       || j < 0)
3103 	{
3104 	  location_chain **nextp;
3105 
3106 	  /* Copy the chain from SRC.  */
3107 	  nextp = &dst->var_part[k].loc_chain;
3108 	  for (node = src->var_part[i].loc_chain; node; node = node->next)
3109 	    {
3110 	      location_chain *new_lc;
3111 
3112 	      new_lc = new location_chain;
3113 	      new_lc->next = NULL;
3114 	      new_lc->init = node->init;
3115 	      if (!node->set_src || MEM_P (node->set_src))
3116 		new_lc->set_src = NULL;
3117 	      else
3118 		new_lc->set_src = node->set_src;
3119 	      new_lc->loc = node->loc;
3120 
3121 	      *nextp = new_lc;
3122 	      nextp = &new_lc->next;
3123 	    }
3124 
3125 	  VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (src, i);
3126 	  i--;
3127 	}
3128       dst->var_part[k].cur_loc = NULL;
3129     }
3130 
3131   if (flag_var_tracking_uninit)
3132     for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
3133       {
3134 	location_chain *node, *node2;
3135 	for (node = src->var_part[i].loc_chain; node; node = node->next)
3136 	  for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
3137 	    if (rtx_equal_p (node->loc, node2->loc))
3138 	      {
3139 		if (node->init > node2->init)
3140 		  node2->init = node->init;
3141 	      }
3142       }
3143 
3144   /* Continue traversing the hash table.  */
3145   return 1;
3146 }
3147 
3148 /* Compute union of dataflow sets SRC and DST and store it to DST.  */
3149 
3150 static void
dataflow_set_union(dataflow_set * dst,dataflow_set * src)3151 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
3152 {
3153   int i;
3154 
3155   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3156     attrs_list_union (&dst->regs[i], src->regs[i]);
3157 
3158   if (dst->vars == empty_shared_hash)
3159     {
3160       shared_hash_destroy (dst->vars);
3161       dst->vars = shared_hash_copy (src->vars);
3162     }
3163   else
3164     {
3165       variable_iterator_type hi;
3166       variable *var;
3167 
3168       FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (src->vars),
3169 				   var, variable, hi)
3170 	variable_union (var, dst);
3171     }
3172 }
3173 
3174 /* Whether the value is currently being expanded.  */
3175 #define VALUE_RECURSED_INTO(x) \
3176   (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
3177 
3178 /* Whether no expansion was found, saving useless lookups.
3179    It must only be set when VALUE_CHANGED is clear.  */
3180 #define NO_LOC_P(x) \
3181   (RTL_FLAG_CHECK2 ("NO_LOC_P", (x), VALUE, DEBUG_EXPR)->return_val)
3182 
3183 /* Whether cur_loc in the value needs to be (re)computed.  */
3184 #define VALUE_CHANGED(x) \
3185   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
3186 /* Whether cur_loc in the decl needs to be (re)computed.  */
3187 #define DECL_CHANGED(x) TREE_VISITED (x)
3188 
3189 /* Record (if NEWV) that DV needs to have its cur_loc recomputed.  For
3190    user DECLs, this means they're in changed_variables.  Values and
3191    debug exprs may be left with this flag set if no user variable
3192    requires them to be evaluated.  */
3193 
3194 static inline void
set_dv_changed(decl_or_value dv,bool newv)3195 set_dv_changed (decl_or_value dv, bool newv)
3196 {
3197   switch (dv_onepart_p (dv))
3198     {
3199     case ONEPART_VALUE:
3200       if (newv)
3201 	NO_LOC_P (dv_as_value (dv)) = false;
3202       VALUE_CHANGED (dv_as_value (dv)) = newv;
3203       break;
3204 
3205     case ONEPART_DEXPR:
3206       if (newv)
3207 	NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv))) = false;
3208       /* Fall through.  */
3209 
3210     default:
3211       DECL_CHANGED (dv_as_decl (dv)) = newv;
3212       break;
3213     }
3214 }
3215 
3216 /* Return true if DV needs to have its cur_loc recomputed.  */
3217 
3218 static inline bool
dv_changed_p(decl_or_value dv)3219 dv_changed_p (decl_or_value dv)
3220 {
3221   return (dv_is_value_p (dv)
3222 	  ? VALUE_CHANGED (dv_as_value (dv))
3223 	  : DECL_CHANGED (dv_as_decl (dv)));
3224 }
3225 
3226 /* Return a location list node whose loc is rtx_equal to LOC, in the
3227    location list of a one-part variable or value VAR, or in that of
3228    any values recursively mentioned in the location lists.  VARS must
3229    be in star-canonical form.  */
3230 
3231 static location_chain *
find_loc_in_1pdv(rtx loc,variable * var,variable_table_type * vars)3232 find_loc_in_1pdv (rtx loc, variable *var, variable_table_type *vars)
3233 {
3234   location_chain *node;
3235   enum rtx_code loc_code;
3236 
3237   if (!var)
3238     return NULL;
3239 
3240   gcc_checking_assert (var->onepart);
3241 
3242   if (!var->n_var_parts)
3243     return NULL;
3244 
3245   gcc_checking_assert (loc != dv_as_opaque (var->dv));
3246 
3247   loc_code = GET_CODE (loc);
3248   for (node = var->var_part[0].loc_chain; node; node = node->next)
3249     {
3250       decl_or_value dv;
3251       variable *rvar;
3252 
3253       if (GET_CODE (node->loc) != loc_code)
3254 	{
3255 	  if (GET_CODE (node->loc) != VALUE)
3256 	    continue;
3257 	}
3258       else if (loc == node->loc)
3259 	return node;
3260       else if (loc_code != VALUE)
3261 	{
3262 	  if (rtx_equal_p (loc, node->loc))
3263 	    return node;
3264 	  continue;
3265 	}
3266 
3267       /* Since we're in star-canonical form, we don't need to visit
3268 	 non-canonical nodes: one-part variables and non-canonical
3269 	 values would only point back to the canonical node.  */
3270       if (dv_is_value_p (var->dv)
3271 	  && !canon_value_cmp (node->loc, dv_as_value (var->dv)))
3272 	{
3273 	  /* Skip all subsequent VALUEs.  */
3274 	  while (node->next && GET_CODE (node->next->loc) == VALUE)
3275 	    {
3276 	      node = node->next;
3277 	      gcc_checking_assert (!canon_value_cmp (node->loc,
3278 						     dv_as_value (var->dv)));
3279 	      if (loc == node->loc)
3280 		return node;
3281 	    }
3282 	  continue;
3283 	}
3284 
3285       gcc_checking_assert (node == var->var_part[0].loc_chain);
3286       gcc_checking_assert (!node->next);
3287 
3288       dv = dv_from_value (node->loc);
3289       rvar = vars->find_with_hash (dv, dv_htab_hash (dv));
3290       return find_loc_in_1pdv (loc, rvar, vars);
3291     }
3292 
3293   /* ??? Gotta look in cselib_val locations too.  */
3294 
3295   return NULL;
3296 }
3297 
3298 /* Hash table iteration argument passed to variable_merge.  */
3299 struct dfset_merge
3300 {
3301   /* The set in which the merge is to be inserted.  */
3302   dataflow_set *dst;
3303   /* The set that we're iterating in.  */
3304   dataflow_set *cur;
3305   /* The set that may contain the other dv we are to merge with.  */
3306   dataflow_set *src;
3307   /* Number of onepart dvs in src.  */
3308   int src_onepart_cnt;
3309 };
3310 
3311 /* Insert LOC in *DNODE, if it's not there yet.  The list must be in
3312    loc_cmp order, and it is maintained as such.  */
3313 
3314 static void
insert_into_intersection(location_chain ** nodep,rtx loc,enum var_init_status status)3315 insert_into_intersection (location_chain **nodep, rtx loc,
3316 			  enum var_init_status status)
3317 {
3318   location_chain *node;
3319   int r;
3320 
3321   for (node = *nodep; node; nodep = &node->next, node = *nodep)
3322     if ((r = loc_cmp (node->loc, loc)) == 0)
3323       {
3324 	node->init = MIN (node->init, status);
3325 	return;
3326       }
3327     else if (r > 0)
3328       break;
3329 
3330   node = new location_chain;
3331 
3332   node->loc = loc;
3333   node->set_src = NULL;
3334   node->init = status;
3335   node->next = *nodep;
3336   *nodep = node;
3337 }
3338 
3339 /* Insert in DEST the intersection of the locations present in both
3340    S1NODE and S2VAR, directly or indirectly.  S1NODE is from a
3341    variable in DSM->cur, whereas S2VAR is from DSM->src.  dvar is in
3342    DSM->dst.  */
3343 
3344 static void
intersect_loc_chains(rtx val,location_chain ** dest,struct dfset_merge * dsm,location_chain * s1node,variable * s2var)3345 intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
3346 		      location_chain *s1node, variable *s2var)
3347 {
3348   dataflow_set *s1set = dsm->cur;
3349   dataflow_set *s2set = dsm->src;
3350   location_chain *found;
3351 
3352   if (s2var)
3353     {
3354       location_chain *s2node;
3355 
3356       gcc_checking_assert (s2var->onepart);
3357 
3358       if (s2var->n_var_parts)
3359 	{
3360 	  s2node = s2var->var_part[0].loc_chain;
3361 
3362 	  for (; s1node && s2node;
3363 	       s1node = s1node->next, s2node = s2node->next)
3364 	    if (s1node->loc != s2node->loc)
3365 	      break;
3366 	    else if (s1node->loc == val)
3367 	      continue;
3368 	    else
3369 	      insert_into_intersection (dest, s1node->loc,
3370 					MIN (s1node->init, s2node->init));
3371 	}
3372     }
3373 
3374   for (; s1node; s1node = s1node->next)
3375     {
3376       if (s1node->loc == val)
3377 	continue;
3378 
3379       if ((found = find_loc_in_1pdv (s1node->loc, s2var,
3380 				     shared_hash_htab (s2set->vars))))
3381 	{
3382 	  insert_into_intersection (dest, s1node->loc,
3383 				    MIN (s1node->init, found->init));
3384 	  continue;
3385 	}
3386 
3387       if (GET_CODE (s1node->loc) == VALUE
3388 	  && !VALUE_RECURSED_INTO (s1node->loc))
3389 	{
3390 	  decl_or_value dv = dv_from_value (s1node->loc);
3391 	  variable *svar = shared_hash_find (s1set->vars, dv);
3392 	  if (svar)
3393 	    {
3394 	      if (svar->n_var_parts == 1)
3395 		{
3396 		  VALUE_RECURSED_INTO (s1node->loc) = true;
3397 		  intersect_loc_chains (val, dest, dsm,
3398 					svar->var_part[0].loc_chain,
3399 					s2var);
3400 		  VALUE_RECURSED_INTO (s1node->loc) = false;
3401 		}
3402 	    }
3403 	}
3404 
3405       /* ??? gotta look in cselib_val locations too.  */
3406 
3407       /* ??? if the location is equivalent to any location in src,
3408 	 searched recursively
3409 
3410 	   add to dst the values needed to represent the equivalence
3411 
3412      telling whether locations S is equivalent to another dv's
3413      location list:
3414 
3415        for each location D in the list
3416 
3417          if S and D satisfy rtx_equal_p, then it is present
3418 
3419 	 else if D is a value, recurse without cycles
3420 
3421 	 else if S and D have the same CODE and MODE
3422 
3423 	   for each operand oS and the corresponding oD
3424 
3425 	     if oS and oD are not equivalent, then S an D are not equivalent
3426 
3427 	     else if they are RTX vectors
3428 
3429 	       if any vector oS element is not equivalent to its respective oD,
3430 	       then S and D are not equivalent
3431 
3432    */
3433 
3434 
3435     }
3436 }
3437 
3438 /* Return -1 if X should be before Y in a location list for a 1-part
3439    variable, 1 if Y should be before X, and 0 if they're equivalent
3440    and should not appear in the list.  */
3441 
3442 static int
loc_cmp(rtx x,rtx y)3443 loc_cmp (rtx x, rtx y)
3444 {
3445   int i, j, r;
3446   RTX_CODE code = GET_CODE (x);
3447   const char *fmt;
3448 
3449   if (x == y)
3450     return 0;
3451 
3452   if (REG_P (x))
3453     {
3454       if (!REG_P (y))
3455 	return -1;
3456       gcc_assert (GET_MODE (x) == GET_MODE (y));
3457       if (REGNO (x) == REGNO (y))
3458 	return 0;
3459       else if (REGNO (x) < REGNO (y))
3460 	return -1;
3461       else
3462 	return 1;
3463     }
3464 
3465   if (REG_P (y))
3466     return 1;
3467 
3468   if (MEM_P (x))
3469     {
3470       if (!MEM_P (y))
3471 	return -1;
3472       gcc_assert (GET_MODE (x) == GET_MODE (y));
3473       return loc_cmp (XEXP (x, 0), XEXP (y, 0));
3474     }
3475 
3476   if (MEM_P (y))
3477     return 1;
3478 
3479   if (GET_CODE (x) == VALUE)
3480     {
3481       if (GET_CODE (y) != VALUE)
3482 	return -1;
3483       /* Don't assert the modes are the same, that is true only
3484 	 when not recursing.  (subreg:QI (value:SI 1:1) 0)
3485 	 and (subreg:QI (value:DI 2:2) 0) can be compared,
3486 	 even when the modes are different.  */
3487       if (canon_value_cmp (x, y))
3488 	return -1;
3489       else
3490 	return 1;
3491     }
3492 
3493   if (GET_CODE (y) == VALUE)
3494     return 1;
3495 
3496   /* Entry value is the least preferable kind of expression.  */
3497   if (GET_CODE (x) == ENTRY_VALUE)
3498     {
3499       if (GET_CODE (y) != ENTRY_VALUE)
3500 	return 1;
3501       gcc_assert (GET_MODE (x) == GET_MODE (y));
3502       return loc_cmp (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
3503     }
3504 
3505   if (GET_CODE (y) == ENTRY_VALUE)
3506     return -1;
3507 
3508   if (GET_CODE (x) == GET_CODE (y))
3509     /* Compare operands below.  */;
3510   else if (GET_CODE (x) < GET_CODE (y))
3511     return -1;
3512   else
3513     return 1;
3514 
3515   gcc_assert (GET_MODE (x) == GET_MODE (y));
3516 
3517   if (GET_CODE (x) == DEBUG_EXPR)
3518     {
3519       if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
3520 	  < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)))
3521 	return -1;
3522       gcc_checking_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
3523 			   > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)));
3524       return 1;
3525     }
3526 
3527   fmt = GET_RTX_FORMAT (code);
3528   for (i = 0; i < GET_RTX_LENGTH (code); i++)
3529     switch (fmt[i])
3530       {
3531       case 'w':
3532 	if (XWINT (x, i) == XWINT (y, i))
3533 	  break;
3534 	else if (XWINT (x, i) < XWINT (y, i))
3535 	  return -1;
3536 	else
3537 	  return 1;
3538 
3539       case 'n':
3540       case 'i':
3541 	if (XINT (x, i) == XINT (y, i))
3542 	  break;
3543 	else if (XINT (x, i) < XINT (y, i))
3544 	  return -1;
3545 	else
3546 	  return 1;
3547 
3548       case 'p':
3549 	r = compare_sizes_for_sort (SUBREG_BYTE (x), SUBREG_BYTE (y));
3550 	if (r != 0)
3551 	  return r;
3552 	break;
3553 
3554       case 'V':
3555       case 'E':
3556 	/* Compare the vector length first.  */
3557 	if (XVECLEN (x, i) == XVECLEN (y, i))
3558 	  /* Compare the vectors elements.  */;
3559 	else if (XVECLEN (x, i) < XVECLEN (y, i))
3560 	  return -1;
3561 	else
3562 	  return 1;
3563 
3564 	for (j = 0; j < XVECLEN (x, i); j++)
3565 	  if ((r = loc_cmp (XVECEXP (x, i, j),
3566 			    XVECEXP (y, i, j))))
3567 	    return r;
3568 	break;
3569 
3570       case 'e':
3571 	if ((r = loc_cmp (XEXP (x, i), XEXP (y, i))))
3572 	  return r;
3573 	break;
3574 
3575       case 'S':
3576       case 's':
3577 	if (XSTR (x, i) == XSTR (y, i))
3578 	  break;
3579 	if (!XSTR (x, i))
3580 	  return -1;
3581 	if (!XSTR (y, i))
3582 	  return 1;
3583 	if ((r = strcmp (XSTR (x, i), XSTR (y, i))) == 0)
3584 	  break;
3585 	else if (r < 0)
3586 	  return -1;
3587 	else
3588 	  return 1;
3589 
3590       case 'u':
3591 	/* These are just backpointers, so they don't matter.  */
3592 	break;
3593 
3594       case '0':
3595       case 't':
3596 	break;
3597 
3598 	/* It is believed that rtx's at this level will never
3599 	   contain anything but integers and other rtx's,
3600 	   except for within LABEL_REFs and SYMBOL_REFs.  */
3601       default:
3602 	gcc_unreachable ();
3603       }
3604   if (CONST_WIDE_INT_P (x))
3605     {
3606       /* Compare the vector length first.  */
3607       if (CONST_WIDE_INT_NUNITS (x) >= CONST_WIDE_INT_NUNITS (y))
3608 	return 1;
3609       else if (CONST_WIDE_INT_NUNITS (x) < CONST_WIDE_INT_NUNITS (y))
3610 	return -1;
3611 
3612       /* Compare the vectors elements.  */;
3613       for (j = CONST_WIDE_INT_NUNITS (x) - 1; j >= 0 ; j--)
3614 	{
3615 	  if (CONST_WIDE_INT_ELT (x, j) < CONST_WIDE_INT_ELT (y, j))
3616 	    return -1;
3617 	  if (CONST_WIDE_INT_ELT (x, j) > CONST_WIDE_INT_ELT (y, j))
3618 	    return 1;
3619 	}
3620     }
3621 
3622   return 0;
3623 }
3624 
3625 /* Check the order of entries in one-part variables.   */
3626 
3627 int
canonicalize_loc_order_check(variable ** slot,dataflow_set * data ATTRIBUTE_UNUSED)3628 canonicalize_loc_order_check (variable **slot,
3629 			      dataflow_set *data ATTRIBUTE_UNUSED)
3630 {
3631   variable *var = *slot;
3632   location_chain *node, *next;
3633 
3634 #ifdef ENABLE_RTL_CHECKING
3635   int i;
3636   for (i = 0; i < var->n_var_parts; i++)
3637     gcc_assert (var->var_part[0].cur_loc == NULL);
3638   gcc_assert (!var->in_changed_variables);
3639 #endif
3640 
3641   if (!var->onepart)
3642     return 1;
3643 
3644   gcc_assert (var->n_var_parts == 1);
3645   node = var->var_part[0].loc_chain;
3646   gcc_assert (node);
3647 
3648   while ((next = node->next))
3649     {
3650       gcc_assert (loc_cmp (node->loc, next->loc) < 0);
3651       node = next;
3652     }
3653 
3654   return 1;
3655 }
3656 
3657 /* Mark with VALUE_RECURSED_INTO values that have neighbors that are
3658    more likely to be chosen as canonical for an equivalence set.
3659    Ensure less likely values can reach more likely neighbors, making
3660    the connections bidirectional.  */
3661 
3662 int
canonicalize_values_mark(variable ** slot,dataflow_set * set)3663 canonicalize_values_mark (variable **slot, dataflow_set *set)
3664 {
3665   variable *var = *slot;
3666   decl_or_value dv = var->dv;
3667   rtx val;
3668   location_chain *node;
3669 
3670   if (!dv_is_value_p (dv))
3671     return 1;
3672 
3673   gcc_checking_assert (var->n_var_parts == 1);
3674 
3675   val = dv_as_value (dv);
3676 
3677   for (node = var->var_part[0].loc_chain; node; node = node->next)
3678     if (GET_CODE (node->loc) == VALUE)
3679       {
3680 	if (canon_value_cmp (node->loc, val))
3681 	  VALUE_RECURSED_INTO (val) = true;
3682 	else
3683 	  {
3684 	    decl_or_value odv = dv_from_value (node->loc);
3685 	    variable **oslot;
3686 	    oslot = shared_hash_find_slot_noinsert (set->vars, odv);
3687 
3688 	    set_slot_part (set, val, oslot, odv, 0,
3689 			   node->init, NULL_RTX);
3690 
3691 	    VALUE_RECURSED_INTO (node->loc) = true;
3692 	  }
3693       }
3694 
3695   return 1;
3696 }
3697 
3698 /* Remove redundant entries from equivalence lists in onepart
3699    variables, canonicalizing equivalence sets into star shapes.  */
3700 
3701 int
canonicalize_values_star(variable ** slot,dataflow_set * set)3702 canonicalize_values_star (variable **slot, dataflow_set *set)
3703 {
3704   variable *var = *slot;
3705   decl_or_value dv = var->dv;
3706   location_chain *node;
3707   decl_or_value cdv;
3708   rtx val, cval;
3709   variable **cslot;
3710   bool has_value;
3711   bool has_marks;
3712 
3713   if (!var->onepart)
3714     return 1;
3715 
3716   gcc_checking_assert (var->n_var_parts == 1);
3717 
3718   if (dv_is_value_p (dv))
3719     {
3720       cval = dv_as_value (dv);
3721       if (!VALUE_RECURSED_INTO (cval))
3722 	return 1;
3723       VALUE_RECURSED_INTO (cval) = false;
3724     }
3725   else
3726     cval = NULL_RTX;
3727 
3728  restart:
3729   val = cval;
3730   has_value = false;
3731   has_marks = false;
3732 
3733   gcc_assert (var->n_var_parts == 1);
3734 
3735   for (node = var->var_part[0].loc_chain; node; node = node->next)
3736     if (GET_CODE (node->loc) == VALUE)
3737       {
3738 	has_value = true;
3739 	if (VALUE_RECURSED_INTO (node->loc))
3740 	  has_marks = true;
3741 	if (canon_value_cmp (node->loc, cval))
3742 	  cval = node->loc;
3743       }
3744 
3745   if (!has_value)
3746     return 1;
3747 
3748   if (cval == val)
3749     {
3750       if (!has_marks || dv_is_decl_p (dv))
3751 	return 1;
3752 
3753       /* Keep it marked so that we revisit it, either after visiting a
3754 	 child node, or after visiting a new parent that might be
3755 	 found out.  */
3756       VALUE_RECURSED_INTO (val) = true;
3757 
3758       for (node = var->var_part[0].loc_chain; node; node = node->next)
3759 	if (GET_CODE (node->loc) == VALUE
3760 	    && VALUE_RECURSED_INTO (node->loc))
3761 	  {
3762 	    cval = node->loc;
3763 	  restart_with_cval:
3764 	    VALUE_RECURSED_INTO (cval) = false;
3765 	    dv = dv_from_value (cval);
3766 	    slot = shared_hash_find_slot_noinsert (set->vars, dv);
3767 	    if (!slot)
3768 	      {
3769 		gcc_assert (dv_is_decl_p (var->dv));
3770 		/* The canonical value was reset and dropped.
3771 		   Remove it.  */
3772 		clobber_variable_part (set, NULL, var->dv, 0, NULL);
3773 		return 1;
3774 	      }
3775 	    var = *slot;
3776 	    gcc_assert (dv_is_value_p (var->dv));
3777 	    if (var->n_var_parts == 0)
3778 	      return 1;
3779 	    gcc_assert (var->n_var_parts == 1);
3780 	    goto restart;
3781 	  }
3782 
3783       VALUE_RECURSED_INTO (val) = false;
3784 
3785       return 1;
3786     }
3787 
3788   /* Push values to the canonical one.  */
3789   cdv = dv_from_value (cval);
3790   cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3791 
3792   for (node = var->var_part[0].loc_chain; node; node = node->next)
3793     if (node->loc != cval)
3794       {
3795 	cslot = set_slot_part (set, node->loc, cslot, cdv, 0,
3796 			       node->init, NULL_RTX);
3797 	if (GET_CODE (node->loc) == VALUE)
3798 	  {
3799 	    decl_or_value ndv = dv_from_value (node->loc);
3800 
3801 	    set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX,
3802 			       NO_INSERT);
3803 
3804 	    if (canon_value_cmp (node->loc, val))
3805 	      {
3806 		/* If it could have been a local minimum, it's not any more,
3807 		   since it's now neighbor to cval, so it may have to push
3808 		   to it.  Conversely, if it wouldn't have prevailed over
3809 		   val, then whatever mark it has is fine: if it was to
3810 		   push, it will now push to a more canonical node, but if
3811 		   it wasn't, then it has already pushed any values it might
3812 		   have to.  */
3813 		VALUE_RECURSED_INTO (node->loc) = true;
3814 		/* Make sure we visit node->loc by ensuring we cval is
3815 		   visited too.  */
3816 		VALUE_RECURSED_INTO (cval) = true;
3817 	      }
3818 	    else if (!VALUE_RECURSED_INTO (node->loc))
3819 	      /* If we have no need to "recurse" into this node, it's
3820 		 already "canonicalized", so drop the link to the old
3821 		 parent.  */
3822 	      clobber_variable_part (set, cval, ndv, 0, NULL);
3823 	  }
3824 	else if (GET_CODE (node->loc) == REG)
3825 	  {
3826 	    attrs *list = set->regs[REGNO (node->loc)], **listp;
3827 
3828 	    /* Change an existing attribute referring to dv so that it
3829 	       refers to cdv, removing any duplicate this might
3830 	       introduce, and checking that no previous duplicates
3831 	       existed, all in a single pass.  */
3832 
3833 	    while (list)
3834 	      {
3835 		if (list->offset == 0
3836 		    && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3837 			|| dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3838 		  break;
3839 
3840 		list = list->next;
3841 	      }
3842 
3843 	    gcc_assert (list);
3844 	    if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3845 	      {
3846 		list->dv = cdv;
3847 		for (listp = &list->next; (list = *listp); listp = &list->next)
3848 		  {
3849 		    if (list->offset)
3850 		      continue;
3851 
3852 		    if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3853 		      {
3854 			*listp = list->next;
3855 			delete list;
3856 			list = *listp;
3857 			break;
3858 		      }
3859 
3860 		    gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv));
3861 		  }
3862 	      }
3863 	    else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3864 	      {
3865 		for (listp = &list->next; (list = *listp); listp = &list->next)
3866 		  {
3867 		    if (list->offset)
3868 		      continue;
3869 
3870 		    if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3871 		      {
3872 			*listp = list->next;
3873 			delete list;
3874 			list = *listp;
3875 			break;
3876 		      }
3877 
3878 		    gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv));
3879 		  }
3880 	      }
3881 	    else
3882 	      gcc_unreachable ();
3883 
3884 	    if (flag_checking)
3885 	      while (list)
3886 		{
3887 		  if (list->offset == 0
3888 		      && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3889 			  || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3890 		    gcc_unreachable ();
3891 
3892 		  list = list->next;
3893 		}
3894 	  }
3895       }
3896 
3897   if (val)
3898     set_slot_part (set, val, cslot, cdv, 0,
3899 		   VAR_INIT_STATUS_INITIALIZED, NULL_RTX);
3900 
3901   slot = clobber_slot_part (set, cval, slot, 0, NULL);
3902 
3903   /* Variable may have been unshared.  */
3904   var = *slot;
3905   gcc_checking_assert (var->n_var_parts && var->var_part[0].loc_chain->loc == cval
3906 		       && var->var_part[0].loc_chain->next == NULL);
3907 
3908   if (VALUE_RECURSED_INTO (cval))
3909     goto restart_with_cval;
3910 
3911   return 1;
3912 }
3913 
3914 /* Bind one-part variables to the canonical value in an equivalence
3915    set.  Not doing this causes dataflow convergence failure in rare
3916    circumstances, see PR42873.  Unfortunately we can't do this
3917    efficiently as part of canonicalize_values_star, since we may not
3918    have determined or even seen the canonical value of a set when we
3919    get to a variable that references another member of the set.  */
3920 
3921 int
canonicalize_vars_star(variable ** slot,dataflow_set * set)3922 canonicalize_vars_star (variable **slot, dataflow_set *set)
3923 {
3924   variable *var = *slot;
3925   decl_or_value dv = var->dv;
3926   location_chain *node;
3927   rtx cval;
3928   decl_or_value cdv;
3929   variable **cslot;
3930   variable *cvar;
3931   location_chain *cnode;
3932 
3933   if (!var->onepart || var->onepart == ONEPART_VALUE)
3934     return 1;
3935 
3936   gcc_assert (var->n_var_parts == 1);
3937 
3938   node = var->var_part[0].loc_chain;
3939 
3940   if (GET_CODE (node->loc) != VALUE)
3941     return 1;
3942 
3943   gcc_assert (!node->next);
3944   cval = node->loc;
3945 
3946   /* Push values to the canonical one.  */
3947   cdv = dv_from_value (cval);
3948   cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3949   if (!cslot)
3950     return 1;
3951   cvar = *cslot;
3952   gcc_assert (cvar->n_var_parts == 1);
3953 
3954   cnode = cvar->var_part[0].loc_chain;
3955 
3956   /* CVAL is canonical if its value list contains non-VALUEs or VALUEs
3957      that are not “more canonical” than it.  */
3958   if (GET_CODE (cnode->loc) != VALUE
3959       || !canon_value_cmp (cnode->loc, cval))
3960     return 1;
3961 
3962   /* CVAL was found to be non-canonical.  Change the variable to point
3963      to the canonical VALUE.  */
3964   gcc_assert (!cnode->next);
3965   cval = cnode->loc;
3966 
3967   slot = set_slot_part (set, cval, slot, dv, 0,
3968 			node->init, node->set_src);
3969   clobber_slot_part (set, cval, slot, 0, node->set_src);
3970 
3971   return 1;
3972 }
3973 
3974 /* Combine variable or value in *S1SLOT (in DSM->cur) with the
3975    corresponding entry in DSM->src.  Multi-part variables are combined
3976    with variable_union, whereas onepart dvs are combined with
3977    intersection.  */
3978 
3979 static int
variable_merge_over_cur(variable * s1var,struct dfset_merge * dsm)3980 variable_merge_over_cur (variable *s1var, struct dfset_merge *dsm)
3981 {
3982   dataflow_set *dst = dsm->dst;
3983   variable **dstslot;
3984   variable *s2var, *dvar = NULL;
3985   decl_or_value dv = s1var->dv;
3986   onepart_enum onepart = s1var->onepart;
3987   rtx val;
3988   hashval_t dvhash;
3989   location_chain *node, **nodep;
3990 
3991   /* If the incoming onepart variable has an empty location list, then
3992      the intersection will be just as empty.  For other variables,
3993      it's always union.  */
3994   gcc_checking_assert (s1var->n_var_parts
3995 		       && s1var->var_part[0].loc_chain);
3996 
3997   if (!onepart)
3998     return variable_union (s1var, dst);
3999 
4000   gcc_checking_assert (s1var->n_var_parts == 1);
4001 
4002   dvhash = dv_htab_hash (dv);
4003   if (dv_is_value_p (dv))
4004     val = dv_as_value (dv);
4005   else
4006     val = NULL;
4007 
4008   s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash);
4009   if (!s2var)
4010     {
4011       dst_can_be_shared = false;
4012       return 1;
4013     }
4014 
4015   dsm->src_onepart_cnt--;
4016   gcc_assert (s2var->var_part[0].loc_chain
4017 	      && s2var->onepart == onepart
4018 	      && s2var->n_var_parts == 1);
4019 
4020   dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4021   if (dstslot)
4022     {
4023       dvar = *dstslot;
4024       gcc_assert (dvar->refcount == 1
4025 		  && dvar->onepart == onepart
4026 		  && dvar->n_var_parts == 1);
4027       nodep = &dvar->var_part[0].loc_chain;
4028     }
4029   else
4030     {
4031       nodep = &node;
4032       node = NULL;
4033     }
4034 
4035   if (!dstslot && !onepart_variable_different_p (s1var, s2var))
4036     {
4037       dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv,
4038 						 dvhash, INSERT);
4039       *dstslot = dvar = s2var;
4040       dvar->refcount++;
4041     }
4042   else
4043     {
4044       dst_can_be_shared = false;
4045 
4046       intersect_loc_chains (val, nodep, dsm,
4047 			    s1var->var_part[0].loc_chain, s2var);
4048 
4049       if (!dstslot)
4050 	{
4051 	  if (node)
4052 	    {
4053 	      dvar = onepart_pool_allocate (onepart);
4054 	      dvar->dv = dv;
4055 	      dvar->refcount = 1;
4056 	      dvar->n_var_parts = 1;
4057 	      dvar->onepart = onepart;
4058 	      dvar->in_changed_variables = false;
4059 	      dvar->var_part[0].loc_chain = node;
4060 	      dvar->var_part[0].cur_loc = NULL;
4061 	      if (onepart)
4062 		VAR_LOC_1PAUX (dvar) = NULL;
4063 	      else
4064 		VAR_PART_OFFSET (dvar, 0) = 0;
4065 
4066 	      dstslot
4067 		= shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
4068 						   INSERT);
4069 	      gcc_assert (!*dstslot);
4070 	      *dstslot = dvar;
4071 	    }
4072 	  else
4073 	    return 1;
4074 	}
4075     }
4076 
4077   nodep = &dvar->var_part[0].loc_chain;
4078   while ((node = *nodep))
4079     {
4080       location_chain **nextp = &node->next;
4081 
4082       if (GET_CODE (node->loc) == REG)
4083 	{
4084 	  attrs *list;
4085 
4086 	  for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
4087 	    if (GET_MODE (node->loc) == GET_MODE (list->loc)
4088 		&& dv_is_value_p (list->dv))
4089 	      break;
4090 
4091 	  if (!list)
4092 	    attrs_list_insert (&dst->regs[REGNO (node->loc)],
4093 			       dv, 0, node->loc);
4094 	  /* If this value became canonical for another value that had
4095 	     this register, we want to leave it alone.  */
4096 	  else if (dv_as_value (list->dv) != val)
4097 	    {
4098 	      dstslot = set_slot_part (dst, dv_as_value (list->dv),
4099 				       dstslot, dv, 0,
4100 				       node->init, NULL_RTX);
4101 	      dstslot = delete_slot_part (dst, node->loc, dstslot, 0);
4102 
4103 	      /* Since nextp points into the removed node, we can't
4104 		 use it.  The pointer to the next node moved to nodep.
4105 		 However, if the variable we're walking is unshared
4106 		 during our walk, we'll keep walking the location list
4107 		 of the previously-shared variable, in which case the
4108 		 node won't have been removed, and we'll want to skip
4109 		 it.  That's why we test *nodep here.  */
4110 	      if (*nodep != node)
4111 		nextp = nodep;
4112 	    }
4113 	}
4114       else
4115 	/* Canonicalization puts registers first, so we don't have to
4116 	   walk it all.  */
4117 	break;
4118       nodep = nextp;
4119     }
4120 
4121   if (dvar != *dstslot)
4122     dvar = *dstslot;
4123   nodep = &dvar->var_part[0].loc_chain;
4124 
4125   if (val)
4126     {
4127       /* Mark all referenced nodes for canonicalization, and make sure
4128 	 we have mutual equivalence links.  */
4129       VALUE_RECURSED_INTO (val) = true;
4130       for (node = *nodep; node; node = node->next)
4131 	if (GET_CODE (node->loc) == VALUE)
4132 	  {
4133 	    VALUE_RECURSED_INTO (node->loc) = true;
4134 	    set_variable_part (dst, val, dv_from_value (node->loc), 0,
4135 			       node->init, NULL, INSERT);
4136 	  }
4137 
4138       dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4139       gcc_assert (*dstslot == dvar);
4140       canonicalize_values_star (dstslot, dst);
4141       gcc_checking_assert (dstslot
4142 			   == shared_hash_find_slot_noinsert_1 (dst->vars,
4143 								dv, dvhash));
4144       dvar = *dstslot;
4145     }
4146   else
4147     {
4148       bool has_value = false, has_other = false;
4149 
4150       /* If we have one value and anything else, we're going to
4151 	 canonicalize this, so make sure all values have an entry in
4152 	 the table and are marked for canonicalization.  */
4153       for (node = *nodep; node; node = node->next)
4154 	{
4155 	  if (GET_CODE (node->loc) == VALUE)
4156 	    {
4157 	      /* If this was marked during register canonicalization,
4158 		 we know we have to canonicalize values.  */
4159 	      if (has_value)
4160 		has_other = true;
4161 	      has_value = true;
4162 	      if (has_other)
4163 		break;
4164 	    }
4165 	  else
4166 	    {
4167 	      has_other = true;
4168 	      if (has_value)
4169 		break;
4170 	    }
4171 	}
4172 
4173       if (has_value && has_other)
4174 	{
4175 	  for (node = *nodep; node; node = node->next)
4176 	    {
4177 	      if (GET_CODE (node->loc) == VALUE)
4178 		{
4179 		  decl_or_value dv = dv_from_value (node->loc);
4180 		  variable **slot = NULL;
4181 
4182 		  if (shared_hash_shared (dst->vars))
4183 		    slot = shared_hash_find_slot_noinsert (dst->vars, dv);
4184 		  if (!slot)
4185 		    slot = shared_hash_find_slot_unshare (&dst->vars, dv,
4186 							  INSERT);
4187 		  if (!*slot)
4188 		    {
4189 		      variable *var = onepart_pool_allocate (ONEPART_VALUE);
4190 		      var->dv = dv;
4191 		      var->refcount = 1;
4192 		      var->n_var_parts = 1;
4193 		      var->onepart = ONEPART_VALUE;
4194 		      var->in_changed_variables = false;
4195 		      var->var_part[0].loc_chain = NULL;
4196 		      var->var_part[0].cur_loc = NULL;
4197 		      VAR_LOC_1PAUX (var) = NULL;
4198 		      *slot = var;
4199 		    }
4200 
4201 		  VALUE_RECURSED_INTO (node->loc) = true;
4202 		}
4203 	    }
4204 
4205 	  dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4206 	  gcc_assert (*dstslot == dvar);
4207 	  canonicalize_values_star (dstslot, dst);
4208 	  gcc_checking_assert (dstslot
4209 			       == shared_hash_find_slot_noinsert_1 (dst->vars,
4210 								    dv, dvhash));
4211 	  dvar = *dstslot;
4212 	}
4213     }
4214 
4215   if (!onepart_variable_different_p (dvar, s2var))
4216     {
4217       variable_htab_free (dvar);
4218       *dstslot = dvar = s2var;
4219       dvar->refcount++;
4220     }
4221   else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var))
4222     {
4223       variable_htab_free (dvar);
4224       *dstslot = dvar = s1var;
4225       dvar->refcount++;
4226       dst_can_be_shared = false;
4227     }
4228   else
4229     dst_can_be_shared = false;
4230 
4231   return 1;
4232 }
4233 
4234 /* Copy s2slot (in DSM->src) to DSM->dst if the variable is a
4235    multi-part variable.  Unions of multi-part variables and
4236    intersections of one-part ones will be handled in
4237    variable_merge_over_cur().  */
4238 
4239 static int
variable_merge_over_src(variable * s2var,struct dfset_merge * dsm)4240 variable_merge_over_src (variable *s2var, struct dfset_merge *dsm)
4241 {
4242   dataflow_set *dst = dsm->dst;
4243   decl_or_value dv = s2var->dv;
4244 
4245   if (!s2var->onepart)
4246     {
4247       variable **dstp = shared_hash_find_slot (dst->vars, dv);
4248       *dstp = s2var;
4249       s2var->refcount++;
4250       return 1;
4251     }
4252 
4253   dsm->src_onepart_cnt++;
4254   return 1;
4255 }
4256 
4257 /* Combine dataflow set information from SRC2 into DST, using PDST
4258    to carry over information across passes.  */
4259 
4260 static void
dataflow_set_merge(dataflow_set * dst,dataflow_set * src2)4261 dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
4262 {
4263   dataflow_set cur = *dst;
4264   dataflow_set *src1 = &cur;
4265   struct dfset_merge dsm;
4266   int i;
4267   size_t src1_elems, src2_elems;
4268   variable_iterator_type hi;
4269   variable *var;
4270 
4271   src1_elems = shared_hash_htab (src1->vars)->elements ();
4272   src2_elems = shared_hash_htab (src2->vars)->elements ();
4273   dataflow_set_init (dst);
4274   dst->stack_adjust = cur.stack_adjust;
4275   shared_hash_destroy (dst->vars);
4276   dst->vars = new shared_hash;
4277   dst->vars->refcount = 1;
4278   dst->vars->htab = new variable_table_type (MAX (src1_elems, src2_elems));
4279 
4280   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4281     attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
4282 
4283   dsm.dst = dst;
4284   dsm.src = src2;
4285   dsm.cur = src1;
4286   dsm.src_onepart_cnt = 0;
4287 
4288   FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.src->vars),
4289 			       var, variable, hi)
4290     variable_merge_over_src (var, &dsm);
4291   FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.cur->vars),
4292 			       var, variable, hi)
4293     variable_merge_over_cur (var, &dsm);
4294 
4295   if (dsm.src_onepart_cnt)
4296     dst_can_be_shared = false;
4297 
4298   dataflow_set_destroy (src1);
4299 }
4300 
4301 /* Mark register equivalences.  */
4302 
4303 static void
dataflow_set_equiv_regs(dataflow_set * set)4304 dataflow_set_equiv_regs (dataflow_set *set)
4305 {
4306   int i;
4307   attrs *list, **listp;
4308 
4309   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4310     {
4311       rtx canon[NUM_MACHINE_MODES];
4312 
4313       /* If the list is empty or one entry, no need to canonicalize
4314 	 anything.  */
4315       if (set->regs[i] == NULL || set->regs[i]->next == NULL)
4316 	continue;
4317 
4318       memset (canon, 0, sizeof (canon));
4319 
4320       for (list = set->regs[i]; list; list = list->next)
4321 	if (list->offset == 0 && dv_is_value_p (list->dv))
4322 	  {
4323 	    rtx val = dv_as_value (list->dv);
4324 	    rtx *cvalp = &canon[(int)GET_MODE (val)];
4325 	    rtx cval = *cvalp;
4326 
4327 	    if (canon_value_cmp (val, cval))
4328 	      *cvalp = val;
4329 	  }
4330 
4331       for (list = set->regs[i]; list; list = list->next)
4332 	if (list->offset == 0 && dv_onepart_p (list->dv))
4333 	  {
4334 	    rtx cval = canon[(int)GET_MODE (list->loc)];
4335 
4336 	    if (!cval)
4337 	      continue;
4338 
4339 	    if (dv_is_value_p (list->dv))
4340 	      {
4341 		rtx val = dv_as_value (list->dv);
4342 
4343 		if (val == cval)
4344 		  continue;
4345 
4346 		VALUE_RECURSED_INTO (val) = true;
4347 		set_variable_part (set, val, dv_from_value (cval), 0,
4348 				   VAR_INIT_STATUS_INITIALIZED,
4349 				   NULL, NO_INSERT);
4350 	      }
4351 
4352 	    VALUE_RECURSED_INTO (cval) = true;
4353 	    set_variable_part (set, cval, list->dv, 0,
4354 			       VAR_INIT_STATUS_INITIALIZED, NULL, NO_INSERT);
4355 	  }
4356 
4357       for (listp = &set->regs[i]; (list = *listp);
4358 	   listp = list ? &list->next : listp)
4359 	if (list->offset == 0 && dv_onepart_p (list->dv))
4360 	  {
4361 	    rtx cval = canon[(int)GET_MODE (list->loc)];
4362 	    variable **slot;
4363 
4364 	    if (!cval)
4365 	      continue;
4366 
4367 	    if (dv_is_value_p (list->dv))
4368 	      {
4369 		rtx val = dv_as_value (list->dv);
4370 		if (!VALUE_RECURSED_INTO (val))
4371 		  continue;
4372 	      }
4373 
4374 	    slot = shared_hash_find_slot_noinsert (set->vars, list->dv);
4375 	    canonicalize_values_star (slot, set);
4376 	    if (*listp != list)
4377 	      list = NULL;
4378 	  }
4379     }
4380 }
4381 
4382 /* Remove any redundant values in the location list of VAR, which must
4383    be unshared and 1-part.  */
4384 
4385 static void
remove_duplicate_values(variable * var)4386 remove_duplicate_values (variable *var)
4387 {
4388   location_chain *node, **nodep;
4389 
4390   gcc_assert (var->onepart);
4391   gcc_assert (var->n_var_parts == 1);
4392   gcc_assert (var->refcount == 1);
4393 
4394   for (nodep = &var->var_part[0].loc_chain; (node = *nodep); )
4395     {
4396       if (GET_CODE (node->loc) == VALUE)
4397 	{
4398 	  if (VALUE_RECURSED_INTO (node->loc))
4399 	    {
4400 	      /* Remove duplicate value node.  */
4401 	      *nodep = node->next;
4402 	      delete node;
4403 	      continue;
4404 	    }
4405 	  else
4406 	    VALUE_RECURSED_INTO (node->loc) = true;
4407 	}
4408       nodep = &node->next;
4409     }
4410 
4411   for (node = var->var_part[0].loc_chain; node; node = node->next)
4412     if (GET_CODE (node->loc) == VALUE)
4413       {
4414 	gcc_assert (VALUE_RECURSED_INTO (node->loc));
4415 	VALUE_RECURSED_INTO (node->loc) = false;
4416       }
4417 }
4418 
4419 
4420 /* Hash table iteration argument passed to variable_post_merge.  */
4421 struct dfset_post_merge
4422 {
4423   /* The new input set for the current block.  */
4424   dataflow_set *set;
4425   /* Pointer to the permanent input set for the current block, or
4426      NULL.  */
4427   dataflow_set **permp;
4428 };
4429 
4430 /* Create values for incoming expressions associated with one-part
4431    variables that don't have value numbers for them.  */
4432 
4433 int
variable_post_merge_new_vals(variable ** slot,dfset_post_merge * dfpm)4434 variable_post_merge_new_vals (variable **slot, dfset_post_merge *dfpm)
4435 {
4436   dataflow_set *set = dfpm->set;
4437   variable *var = *slot;
4438   location_chain *node;
4439 
4440   if (!var->onepart || !var->n_var_parts)
4441     return 1;
4442 
4443   gcc_assert (var->n_var_parts == 1);
4444 
4445   if (dv_is_decl_p (var->dv))
4446     {
4447       bool check_dupes = false;
4448 
4449     restart:
4450       for (node = var->var_part[0].loc_chain; node; node = node->next)
4451 	{
4452 	  if (GET_CODE (node->loc) == VALUE)
4453 	    gcc_assert (!VALUE_RECURSED_INTO (node->loc));
4454 	  else if (GET_CODE (node->loc) == REG)
4455 	    {
4456 	      attrs *att, **attp, **curp = NULL;
4457 
4458 	      if (var->refcount != 1)
4459 		{
4460 		  slot = unshare_variable (set, slot, var,
4461 					   VAR_INIT_STATUS_INITIALIZED);
4462 		  var = *slot;
4463 		  goto restart;
4464 		}
4465 
4466 	      for (attp = &set->regs[REGNO (node->loc)]; (att = *attp);
4467 		   attp = &att->next)
4468 		if (att->offset == 0
4469 		    && GET_MODE (att->loc) == GET_MODE (node->loc))
4470 		  {
4471 		    if (dv_is_value_p (att->dv))
4472 		      {
4473 			rtx cval = dv_as_value (att->dv);
4474 			node->loc = cval;
4475 			check_dupes = true;
4476 			break;
4477 		      }
4478 		    else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv))
4479 		      curp = attp;
4480 		  }
4481 
4482 	      if (!curp)
4483 		{
4484 		  curp = attp;
4485 		  while (*curp)
4486 		    if ((*curp)->offset == 0
4487 			&& GET_MODE ((*curp)->loc) == GET_MODE (node->loc)
4488 			&& dv_as_opaque ((*curp)->dv) == dv_as_opaque (var->dv))
4489 		      break;
4490 		    else
4491 		      curp = &(*curp)->next;
4492 		  gcc_assert (*curp);
4493 		}
4494 
4495 	      if (!att)
4496 		{
4497 		  decl_or_value cdv;
4498 		  rtx cval;
4499 
4500 		  if (!*dfpm->permp)
4501 		    {
4502 		      *dfpm->permp = XNEW (dataflow_set);
4503 		      dataflow_set_init (*dfpm->permp);
4504 		    }
4505 
4506 		  for (att = (*dfpm->permp)->regs[REGNO (node->loc)];
4507 		       att; att = att->next)
4508 		    if (GET_MODE (att->loc) == GET_MODE (node->loc))
4509 		      {
4510 			gcc_assert (att->offset == 0
4511 				    && dv_is_value_p (att->dv));
4512 			val_reset (set, att->dv);
4513 			break;
4514 		      }
4515 
4516 		  if (att)
4517 		    {
4518 		      cdv = att->dv;
4519 		      cval = dv_as_value (cdv);
4520 		    }
4521 		  else
4522 		    {
4523 		      /* Create a unique value to hold this register,
4524 			 that ought to be found and reused in
4525 			 subsequent rounds.  */
4526 		      cselib_val *v;
4527 		      gcc_assert (!cselib_lookup (node->loc,
4528 						  GET_MODE (node->loc), 0,
4529 						  VOIDmode));
4530 		      v = cselib_lookup (node->loc, GET_MODE (node->loc), 1,
4531 					 VOIDmode);
4532 		      cselib_preserve_value (v);
4533 		      cselib_invalidate_rtx (node->loc);
4534 		      cval = v->val_rtx;
4535 		      cdv = dv_from_value (cval);
4536 		      if (dump_file)
4537 			fprintf (dump_file,
4538 				 "Created new value %u:%u for reg %i\n",
4539 				 v->uid, v->hash, REGNO (node->loc));
4540 		    }
4541 
4542 		  var_reg_decl_set (*dfpm->permp, node->loc,
4543 				    VAR_INIT_STATUS_INITIALIZED,
4544 				    cdv, 0, NULL, INSERT);
4545 
4546 		  node->loc = cval;
4547 		  check_dupes = true;
4548 		}
4549 
4550 	      /* Remove attribute referring to the decl, which now
4551 		 uses the value for the register, already existing or
4552 		 to be added when we bring perm in.  */
4553 	      att = *curp;
4554 	      *curp = att->next;
4555 	      delete att;
4556 	    }
4557 	}
4558 
4559       if (check_dupes)
4560 	remove_duplicate_values (var);
4561     }
4562 
4563   return 1;
4564 }
4565 
4566 /* Reset values in the permanent set that are not associated with the
4567    chosen expression.  */
4568 
4569 int
variable_post_merge_perm_vals(variable ** pslot,dfset_post_merge * dfpm)4570 variable_post_merge_perm_vals (variable **pslot, dfset_post_merge *dfpm)
4571 {
4572   dataflow_set *set = dfpm->set;
4573   variable *pvar = *pslot, *var;
4574   location_chain *pnode;
4575   decl_or_value dv;
4576   attrs *att;
4577 
4578   gcc_assert (dv_is_value_p (pvar->dv)
4579 	      && pvar->n_var_parts == 1);
4580   pnode = pvar->var_part[0].loc_chain;
4581   gcc_assert (pnode
4582 	      && !pnode->next
4583 	      && REG_P (pnode->loc));
4584 
4585   dv = pvar->dv;
4586 
4587   var = shared_hash_find (set->vars, dv);
4588   if (var)
4589     {
4590       /* Although variable_post_merge_new_vals may have made decls
4591 	 non-star-canonical, values that pre-existed in canonical form
4592 	 remain canonical, and newly-created values reference a single
4593 	 REG, so they are canonical as well.  Since VAR has the
4594 	 location list for a VALUE, using find_loc_in_1pdv for it is
4595 	 fine, since VALUEs don't map back to DECLs.  */
4596       if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
4597 	return 1;
4598       val_reset (set, dv);
4599     }
4600 
4601   for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next)
4602     if (att->offset == 0
4603 	&& GET_MODE (att->loc) == GET_MODE (pnode->loc)
4604 	&& dv_is_value_p (att->dv))
4605       break;
4606 
4607   /* If there is a value associated with this register already, create
4608      an equivalence.  */
4609   if (att && dv_as_value (att->dv) != dv_as_value (dv))
4610     {
4611       rtx cval = dv_as_value (att->dv);
4612       set_variable_part (set, cval, dv, 0, pnode->init, NULL, INSERT);
4613       set_variable_part (set, dv_as_value (dv), att->dv, 0, pnode->init,
4614 			 NULL, INSERT);
4615     }
4616   else if (!att)
4617     {
4618       attrs_list_insert (&set->regs[REGNO (pnode->loc)],
4619 			 dv, 0, pnode->loc);
4620       variable_union (pvar, set);
4621     }
4622 
4623   return 1;
4624 }
4625 
4626 /* Just checking stuff and registering register attributes for
4627    now.  */
4628 
4629 static void
dataflow_post_merge_adjust(dataflow_set * set,dataflow_set ** permp)4630 dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
4631 {
4632   struct dfset_post_merge dfpm;
4633 
4634   dfpm.set = set;
4635   dfpm.permp = permp;
4636 
4637   shared_hash_htab (set->vars)
4638     ->traverse <dfset_post_merge*, variable_post_merge_new_vals> (&dfpm);
4639   if (*permp)
4640     shared_hash_htab ((*permp)->vars)
4641       ->traverse <dfset_post_merge*, variable_post_merge_perm_vals> (&dfpm);
4642   shared_hash_htab (set->vars)
4643     ->traverse <dataflow_set *, canonicalize_values_star> (set);
4644   shared_hash_htab (set->vars)
4645     ->traverse <dataflow_set *, canonicalize_vars_star> (set);
4646 }
4647 
4648 /* Return a node whose loc is a MEM that refers to EXPR in the
4649    location list of a one-part variable or value VAR, or in that of
4650    any values recursively mentioned in the location lists.  */
4651 
4652 static location_chain *
find_mem_expr_in_1pdv(tree expr,rtx val,variable_table_type * vars)4653 find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
4654 {
4655   location_chain *node;
4656   decl_or_value dv;
4657   variable *var;
4658   location_chain *where = NULL;
4659 
4660   if (!val)
4661     return NULL;
4662 
4663   gcc_assert (GET_CODE (val) == VALUE
4664 	      && !VALUE_RECURSED_INTO (val));
4665 
4666   dv = dv_from_value (val);
4667   var = vars->find_with_hash (dv, dv_htab_hash (dv));
4668 
4669   if (!var)
4670     return NULL;
4671 
4672   gcc_assert (var->onepart);
4673 
4674   if (!var->n_var_parts)
4675     return NULL;
4676 
4677   VALUE_RECURSED_INTO (val) = true;
4678 
4679   for (node = var->var_part[0].loc_chain; node; node = node->next)
4680     if (MEM_P (node->loc)
4681 	&& MEM_EXPR (node->loc) == expr
4682 	&& int_mem_offset (node->loc) == 0)
4683       {
4684 	where = node;
4685 	break;
4686       }
4687     else if (GET_CODE (node->loc) == VALUE
4688 	     && !VALUE_RECURSED_INTO (node->loc)
4689 	     && (where = find_mem_expr_in_1pdv (expr, node->loc, vars)))
4690       break;
4691 
4692   VALUE_RECURSED_INTO (val) = false;
4693 
4694   return where;
4695 }
4696 
4697 /* Return TRUE if the value of MEM may vary across a call.  */
4698 
4699 static bool
mem_dies_at_call(rtx mem)4700 mem_dies_at_call (rtx mem)
4701 {
4702   tree expr = MEM_EXPR (mem);
4703   tree decl;
4704 
4705   if (!expr)
4706     return true;
4707 
4708   decl = get_base_address (expr);
4709 
4710   if (!decl)
4711     return true;
4712 
4713   if (!DECL_P (decl))
4714     return true;
4715 
4716   return (may_be_aliased (decl)
4717 	  || (!TREE_READONLY (decl) && is_global_var (decl)));
4718 }
4719 
4720 /* Remove all MEMs from the location list of a hash table entry for a
4721    one-part variable, except those whose MEM attributes map back to
4722    the variable itself, directly or within a VALUE.  */
4723 
4724 int
dataflow_set_preserve_mem_locs(variable ** slot,dataflow_set * set)4725 dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
4726 {
4727   variable *var = *slot;
4728 
4729   if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
4730     {
4731       tree decl = dv_as_decl (var->dv);
4732       location_chain *loc, **locp;
4733       bool changed = false;
4734 
4735       if (!var->n_var_parts)
4736 	return 1;
4737 
4738       gcc_assert (var->n_var_parts == 1);
4739 
4740       if (shared_var_p (var, set->vars))
4741 	{
4742 	  for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4743 	    {
4744 	      /* We want to remove dying MEMs that don't refer to DECL.  */
4745 	      if (GET_CODE (loc->loc) == MEM
4746 		  && (MEM_EXPR (loc->loc) != decl
4747 		      || int_mem_offset (loc->loc) != 0)
4748 		  && mem_dies_at_call (loc->loc))
4749 		break;
4750 	      /* We want to move here MEMs that do refer to DECL.  */
4751 	      else if (GET_CODE (loc->loc) == VALUE
4752 		       && find_mem_expr_in_1pdv (decl, loc->loc,
4753 						 shared_hash_htab (set->vars)))
4754 		break;
4755 	    }
4756 
4757 	  if (!loc)
4758 	    return 1;
4759 
4760 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4761 	  var = *slot;
4762 	  gcc_assert (var->n_var_parts == 1);
4763 	}
4764 
4765       for (locp = &var->var_part[0].loc_chain, loc = *locp;
4766 	   loc; loc = *locp)
4767 	{
4768 	  rtx old_loc = loc->loc;
4769 	  if (GET_CODE (old_loc) == VALUE)
4770 	    {
4771 	      location_chain *mem_node
4772 		= find_mem_expr_in_1pdv (decl, loc->loc,
4773 					 shared_hash_htab (set->vars));
4774 
4775 	      /* ??? This picks up only one out of multiple MEMs that
4776 		 refer to the same variable.  Do we ever need to be
4777 		 concerned about dealing with more than one, or, given
4778 		 that they should all map to the same variable
4779 		 location, their addresses will have been merged and
4780 		 they will be regarded as equivalent?  */
4781 	      if (mem_node)
4782 		{
4783 		  loc->loc = mem_node->loc;
4784 		  loc->set_src = mem_node->set_src;
4785 		  loc->init = MIN (loc->init, mem_node->init);
4786 		}
4787 	    }
4788 
4789 	  if (GET_CODE (loc->loc) != MEM
4790 	      || (MEM_EXPR (loc->loc) == decl
4791 		  && int_mem_offset (loc->loc) == 0)
4792 	      || !mem_dies_at_call (loc->loc))
4793 	    {
4794 	      if (old_loc != loc->loc && emit_notes)
4795 		{
4796 		  if (old_loc == var->var_part[0].cur_loc)
4797 		    {
4798 		      changed = true;
4799 		      var->var_part[0].cur_loc = NULL;
4800 		    }
4801 		}
4802 	      locp = &loc->next;
4803 	      continue;
4804 	    }
4805 
4806 	  if (emit_notes)
4807 	    {
4808 	      if (old_loc == var->var_part[0].cur_loc)
4809 		{
4810 		  changed = true;
4811 		  var->var_part[0].cur_loc = NULL;
4812 		}
4813 	    }
4814 	  *locp = loc->next;
4815 	  delete loc;
4816 	}
4817 
4818       if (!var->var_part[0].loc_chain)
4819 	{
4820 	  var->n_var_parts--;
4821 	  changed = true;
4822 	}
4823       if (changed)
4824 	variable_was_changed (var, set);
4825     }
4826 
4827   return 1;
4828 }
4829 
4830 /* Remove all MEMs from the location list of a hash table entry for a
4831    onepart variable.  */
4832 
4833 int
dataflow_set_remove_mem_locs(variable ** slot,dataflow_set * set)4834 dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
4835 {
4836   variable *var = *slot;
4837 
4838   if (var->onepart != NOT_ONEPART)
4839     {
4840       location_chain *loc, **locp;
4841       bool changed = false;
4842       rtx cur_loc;
4843 
4844       gcc_assert (var->n_var_parts == 1);
4845 
4846       if (shared_var_p (var, set->vars))
4847 	{
4848 	  for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4849 	    if (GET_CODE (loc->loc) == MEM
4850 		&& mem_dies_at_call (loc->loc))
4851 	      break;
4852 
4853 	  if (!loc)
4854 	    return 1;
4855 
4856 	  slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4857 	  var = *slot;
4858 	  gcc_assert (var->n_var_parts == 1);
4859 	}
4860 
4861       if (VAR_LOC_1PAUX (var))
4862 	cur_loc = VAR_LOC_FROM (var);
4863       else
4864 	cur_loc = var->var_part[0].cur_loc;
4865 
4866       for (locp = &var->var_part[0].loc_chain, loc = *locp;
4867 	   loc; loc = *locp)
4868 	{
4869 	  if (GET_CODE (loc->loc) != MEM
4870 	      || !mem_dies_at_call (loc->loc))
4871 	    {
4872 	      locp = &loc->next;
4873 	      continue;
4874 	    }
4875 
4876 	  *locp = loc->next;
4877 	  /* If we have deleted the location which was last emitted
4878 	     we have to emit new location so add the variable to set
4879 	     of changed variables.  */
4880 	  if (cur_loc == loc->loc)
4881 	    {
4882 	      changed = true;
4883 	      var->var_part[0].cur_loc = NULL;
4884 	      if (VAR_LOC_1PAUX (var))
4885 		VAR_LOC_FROM (var) = NULL;
4886 	    }
4887 	  delete loc;
4888 	}
4889 
4890       if (!var->var_part[0].loc_chain)
4891 	{
4892 	  var->n_var_parts--;
4893 	  changed = true;
4894 	}
4895       if (changed)
4896 	variable_was_changed (var, set);
4897     }
4898 
4899   return 1;
4900 }
4901 
4902 /* Remove all variable-location information about call-clobbered
4903    registers, as well as associations between MEMs and VALUEs.  */
4904 
4905 static void
dataflow_set_clear_at_call(dataflow_set * set,rtx_insn * call_insn)4906 dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
4907 {
4908   unsigned int r;
4909   hard_reg_set_iterator hrsi;
4910 
4911   HARD_REG_SET callee_clobbers
4912     = insn_callee_abi (call_insn).full_reg_clobbers ();
4913 
4914   EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, r, hrsi)
4915     var_regno_delete (set, r);
4916 
4917   if (MAY_HAVE_DEBUG_BIND_INSNS)
4918     {
4919       set->traversed_vars = set->vars;
4920       shared_hash_htab (set->vars)
4921 	->traverse <dataflow_set *, dataflow_set_preserve_mem_locs> (set);
4922       set->traversed_vars = set->vars;
4923       shared_hash_htab (set->vars)
4924 	->traverse <dataflow_set *, dataflow_set_remove_mem_locs> (set);
4925       set->traversed_vars = NULL;
4926     }
4927 }
4928 
4929 static bool
variable_part_different_p(variable_part * vp1,variable_part * vp2)4930 variable_part_different_p (variable_part *vp1, variable_part *vp2)
4931 {
4932   location_chain *lc1, *lc2;
4933 
4934   for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
4935     {
4936       for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
4937 	{
4938 	  if (REG_P (lc1->loc) && REG_P (lc2->loc))
4939 	    {
4940 	      if (REGNO (lc1->loc) == REGNO (lc2->loc))
4941 		break;
4942 	    }
4943 	  if (rtx_equal_p (lc1->loc, lc2->loc))
4944 	    break;
4945 	}
4946       if (!lc2)
4947 	return true;
4948     }
4949   return false;
4950 }
4951 
4952 /* Return true if one-part variables VAR1 and VAR2 are different.
4953    They must be in canonical order.  */
4954 
4955 static bool
onepart_variable_different_p(variable * var1,variable * var2)4956 onepart_variable_different_p (variable *var1, variable *var2)
4957 {
4958   location_chain *lc1, *lc2;
4959 
4960   if (var1 == var2)
4961     return false;
4962 
4963   gcc_assert (var1->n_var_parts == 1
4964 	      && var2->n_var_parts == 1);
4965 
4966   lc1 = var1->var_part[0].loc_chain;
4967   lc2 = var2->var_part[0].loc_chain;
4968 
4969   gcc_assert (lc1 && lc2);
4970 
4971   while (lc1 && lc2)
4972     {
4973       if (loc_cmp (lc1->loc, lc2->loc))
4974 	return true;
4975       lc1 = lc1->next;
4976       lc2 = lc2->next;
4977     }
4978 
4979   return lc1 != lc2;
4980 }
4981 
4982 /* Return true if one-part variables VAR1 and VAR2 are different.
4983    They must be in canonical order.  */
4984 
4985 static void
dump_onepart_variable_differences(variable * var1,variable * var2)4986 dump_onepart_variable_differences (variable *var1, variable *var2)
4987 {
4988   location_chain *lc1, *lc2;
4989 
4990   gcc_assert (var1 != var2);
4991   gcc_assert (dump_file);
4992   gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
4993   gcc_assert (var1->n_var_parts == 1
4994 	      && var2->n_var_parts == 1);
4995 
4996   lc1 = var1->var_part[0].loc_chain;
4997   lc2 = var2->var_part[0].loc_chain;
4998 
4999   gcc_assert (lc1 && lc2);
5000 
5001   while (lc1 && lc2)
5002     {
5003       switch (loc_cmp (lc1->loc, lc2->loc))
5004 	{
5005 	case -1:
5006 	  fprintf (dump_file, "removed: ");
5007 	  print_rtl_single (dump_file, lc1->loc);
5008 	  lc1 = lc1->next;
5009 	  continue;
5010 	case 0:
5011 	  break;
5012 	case 1:
5013 	  fprintf (dump_file, "added: ");
5014 	  print_rtl_single (dump_file, lc2->loc);
5015 	  lc2 = lc2->next;
5016 	  continue;
5017 	default:
5018 	  gcc_unreachable ();
5019 	}
5020       lc1 = lc1->next;
5021       lc2 = lc2->next;
5022     }
5023 
5024   while (lc1)
5025     {
5026       fprintf (dump_file, "removed: ");
5027       print_rtl_single (dump_file, lc1->loc);
5028       lc1 = lc1->next;
5029     }
5030 
5031   while (lc2)
5032     {
5033       fprintf (dump_file, "added: ");
5034       print_rtl_single (dump_file, lc2->loc);
5035       lc2 = lc2->next;
5036     }
5037 }
5038 
5039 /* Return true if variables VAR1 and VAR2 are different.  */
5040 
5041 static bool
variable_different_p(variable * var1,variable * var2)5042 variable_different_p (variable *var1, variable *var2)
5043 {
5044   int i;
5045 
5046   if (var1 == var2)
5047     return false;
5048 
5049   if (var1->onepart != var2->onepart)
5050     return true;
5051 
5052   if (var1->n_var_parts != var2->n_var_parts)
5053     return true;
5054 
5055   if (var1->onepart && var1->n_var_parts)
5056     {
5057       gcc_checking_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv)
5058 			   && var1->n_var_parts == 1);
5059       /* One-part values have locations in a canonical order.  */
5060       return onepart_variable_different_p (var1, var2);
5061     }
5062 
5063   for (i = 0; i < var1->n_var_parts; i++)
5064     {
5065       if (VAR_PART_OFFSET (var1, i) != VAR_PART_OFFSET (var2, i))
5066 	return true;
5067       if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
5068 	return true;
5069       if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
5070 	return true;
5071     }
5072   return false;
5073 }
5074 
5075 /* Return true if dataflow sets OLD_SET and NEW_SET differ.  */
5076 
5077 static bool
dataflow_set_different(dataflow_set * old_set,dataflow_set * new_set)5078 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
5079 {
5080   variable_iterator_type hi;
5081   variable *var1;
5082   bool diffound = false;
5083   bool details = (dump_file && (dump_flags & TDF_DETAILS));
5084 
5085 #define RETRUE					\
5086   do						\
5087     {						\
5088       if (!details)				\
5089 	return true;				\
5090       else					\
5091 	diffound = true;			\
5092     }						\
5093   while (0)
5094 
5095   if (old_set->vars == new_set->vars)
5096     return false;
5097 
5098   if (shared_hash_htab (old_set->vars)->elements ()
5099       != shared_hash_htab (new_set->vars)->elements ())
5100     RETRUE;
5101 
5102   FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (old_set->vars),
5103 			       var1, variable, hi)
5104     {
5105       variable_table_type *htab = shared_hash_htab (new_set->vars);
5106       variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
5107 
5108       if (!var2)
5109 	{
5110 	  if (dump_file && (dump_flags & TDF_DETAILS))
5111 	    {
5112 	      fprintf (dump_file, "dataflow difference found: removal of:\n");
5113 	      dump_var (var1);
5114 	    }
5115 	  RETRUE;
5116 	}
5117       else if (variable_different_p (var1, var2))
5118 	{
5119 	  if (details)
5120 	    {
5121 	      fprintf (dump_file, "dataflow difference found: "
5122 		       "old and new follow:\n");
5123 	      dump_var (var1);
5124 	      if (dv_onepart_p (var1->dv))
5125 		dump_onepart_variable_differences (var1, var2);
5126 	      dump_var (var2);
5127 	    }
5128 	  RETRUE;
5129 	}
5130     }
5131 
5132   /* There's no need to traverse the second hashtab unless we want to
5133      print the details.  If both have the same number of elements and
5134      the second one had all entries found in the first one, then the
5135      second can't have any extra entries.  */
5136   if (!details)
5137     return diffound;
5138 
5139   FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (new_set->vars),
5140 			       var1, variable, hi)
5141     {
5142       variable_table_type *htab = shared_hash_htab (old_set->vars);
5143       variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
5144       if (!var2)
5145 	{
5146 	  if (details)
5147 	    {
5148 	      fprintf (dump_file, "dataflow difference found: addition of:\n");
5149 	      dump_var (var1);
5150 	    }
5151 	  RETRUE;
5152 	}
5153     }
5154 
5155 #undef RETRUE
5156 
5157   return diffound;
5158 }
5159 
5160 /* Free the contents of dataflow set SET.  */
5161 
5162 static void
dataflow_set_destroy(dataflow_set * set)5163 dataflow_set_destroy (dataflow_set *set)
5164 {
5165   int i;
5166 
5167   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
5168     attrs_list_clear (&set->regs[i]);
5169 
5170   shared_hash_destroy (set->vars);
5171   set->vars = NULL;
5172 }
5173 
5174 /* Return true if T is a tracked parameter with non-degenerate record type.  */
5175 
5176 static bool
tracked_record_parameter_p(tree t)5177 tracked_record_parameter_p (tree t)
5178 {
5179   if (TREE_CODE (t) != PARM_DECL)
5180     return false;
5181 
5182   if (DECL_MODE (t) == BLKmode)
5183     return false;
5184 
5185   tree type = TREE_TYPE (t);
5186   if (TREE_CODE (type) != RECORD_TYPE)
5187     return false;
5188 
5189   if (TYPE_FIELDS (type) == NULL_TREE
5190       || DECL_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
5191     return false;
5192 
5193   return true;
5194 }
5195 
5196 /* Shall EXPR be tracked?  */
5197 
5198 static bool
track_expr_p(tree expr,bool need_rtl)5199 track_expr_p (tree expr, bool need_rtl)
5200 {
5201   rtx decl_rtl;
5202   tree realdecl;
5203 
5204   if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
5205     return DECL_RTL_SET_P (expr);
5206 
5207   /* If EXPR is not a parameter or a variable do not track it.  */
5208   if (!VAR_P (expr) && TREE_CODE (expr) != PARM_DECL)
5209     return 0;
5210 
5211   /* It also must have a name...  */
5212   if (!DECL_NAME (expr) && need_rtl)
5213     return 0;
5214 
5215   /* ... and a RTL assigned to it.  */
5216   decl_rtl = DECL_RTL_IF_SET (expr);
5217   if (!decl_rtl && need_rtl)
5218     return 0;
5219 
5220   /* If this expression is really a debug alias of some other declaration, we
5221      don't need to track this expression if the ultimate declaration is
5222      ignored.  */
5223   realdecl = expr;
5224   if (VAR_P (realdecl) && DECL_HAS_DEBUG_EXPR_P (realdecl))
5225     {
5226       realdecl = DECL_DEBUG_EXPR (realdecl);
5227       if (!DECL_P (realdecl))
5228 	{
5229 	  if (handled_component_p (realdecl)
5230 	      || (TREE_CODE (realdecl) == MEM_REF
5231 		  && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
5232 	    {
5233 	      HOST_WIDE_INT bitsize, bitpos;
5234 	      bool reverse;
5235 	      tree innerdecl
5236 		= get_ref_base_and_extent_hwi (realdecl, &bitpos,
5237 					       &bitsize, &reverse);
5238 	      if (!innerdecl
5239 		  || !DECL_P (innerdecl)
5240 		  || DECL_IGNORED_P (innerdecl)
5241 		  /* Do not track declarations for parts of tracked record
5242 		     parameters since we want to track them as a whole.  */
5243 		  || tracked_record_parameter_p (innerdecl)
5244 		  || TREE_STATIC (innerdecl)
5245 		  || bitsize == 0
5246 		  || bitpos + bitsize > 256)
5247 		return 0;
5248 	      else
5249 		realdecl = expr;
5250 	    }
5251 	  else
5252 	    return 0;
5253 	}
5254     }
5255 
5256   /* Do not track EXPR if REALDECL it should be ignored for debugging
5257      purposes.  */
5258   if (DECL_IGNORED_P (realdecl))
5259     return 0;
5260 
5261   /* Do not track global variables until we are able to emit correct location
5262      list for them.  */
5263   if (TREE_STATIC (realdecl))
5264     return 0;
5265 
5266   /* When the EXPR is a DECL for alias of some variable (see example)
5267      the TREE_STATIC flag is not used.  Disable tracking all DECLs whose
5268      DECL_RTL contains SYMBOL_REF.
5269 
5270      Example:
5271      extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
5272      char **_dl_argv;
5273   */
5274   if (decl_rtl && MEM_P (decl_rtl)
5275       && contains_symbol_ref_p (XEXP (decl_rtl, 0)))
5276     return 0;
5277 
5278   /* If RTX is a memory it should not be very large (because it would be
5279      an array or struct).  */
5280   if (decl_rtl && MEM_P (decl_rtl))
5281     {
5282       /* Do not track structures and arrays.  */
5283       if ((GET_MODE (decl_rtl) == BLKmode
5284 	   || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
5285 	  && !tracked_record_parameter_p (realdecl))
5286 	return 0;
5287       if (MEM_SIZE_KNOWN_P (decl_rtl)
5288 	  && maybe_gt (MEM_SIZE (decl_rtl), MAX_VAR_PARTS))
5289 	return 0;
5290     }
5291 
5292   DECL_CHANGED (expr) = 0;
5293   DECL_CHANGED (realdecl) = 0;
5294   return 1;
5295 }
5296 
5297 /* Determine whether a given LOC refers to the same variable part as
5298    EXPR+OFFSET.  */
5299 
5300 static bool
same_variable_part_p(rtx loc,tree expr,poly_int64 offset)5301 same_variable_part_p (rtx loc, tree expr, poly_int64 offset)
5302 {
5303   tree expr2;
5304   poly_int64 offset2;
5305 
5306   if (! DECL_P (expr))
5307     return false;
5308 
5309   if (REG_P (loc))
5310     {
5311       expr2 = REG_EXPR (loc);
5312       offset2 = REG_OFFSET (loc);
5313     }
5314   else if (MEM_P (loc))
5315     {
5316       expr2 = MEM_EXPR (loc);
5317       offset2 = int_mem_offset (loc);
5318     }
5319   else
5320     return false;
5321 
5322   if (! expr2 || ! DECL_P (expr2))
5323     return false;
5324 
5325   expr = var_debug_decl (expr);
5326   expr2 = var_debug_decl (expr2);
5327 
5328   return (expr == expr2 && known_eq (offset, offset2));
5329 }
5330 
5331 /* LOC is a REG or MEM that we would like to track if possible.
5332    If EXPR is null, we don't know what expression LOC refers to,
5333    otherwise it refers to EXPR + OFFSET.  STORE_REG_P is true if
5334    LOC is an lvalue register.
5335 
5336    Return true if EXPR is nonnull and if LOC, or some lowpart of it,
5337    is something we can track.  When returning true, store the mode of
5338    the lowpart we can track in *MODE_OUT (if nonnull) and its offset
5339    from EXPR in *OFFSET_OUT (if nonnull).  */
5340 
5341 static bool
track_loc_p(rtx loc,tree expr,poly_int64 offset,bool store_reg_p,machine_mode * mode_out,HOST_WIDE_INT * offset_out)5342 track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
5343 	     machine_mode *mode_out, HOST_WIDE_INT *offset_out)
5344 {
5345   machine_mode mode;
5346 
5347   if (expr == NULL || !track_expr_p (expr, true))
5348     return false;
5349 
5350   /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
5351      whole subreg, but only the old inner part is really relevant.  */
5352   mode = GET_MODE (loc);
5353   if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
5354     {
5355       machine_mode pseudo_mode;
5356 
5357       pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
5358       if (paradoxical_subreg_p (mode, pseudo_mode))
5359 	{
5360 	  offset += byte_lowpart_offset (pseudo_mode, mode);
5361 	  mode = pseudo_mode;
5362 	}
5363     }
5364 
5365   /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
5366      Do the same if we are storing to a register and EXPR occupies
5367      the whole of register LOC; in that case, the whole of EXPR is
5368      being changed.  We exclude complex modes from the second case
5369      because the real and imaginary parts are represented as separate
5370      pseudo registers, even if the whole complex value fits into one
5371      hard register.  */
5372   if ((paradoxical_subreg_p (mode, DECL_MODE (expr))
5373        || (store_reg_p
5374 	   && !COMPLEX_MODE_P (DECL_MODE (expr))
5375 	   && hard_regno_nregs (REGNO (loc), DECL_MODE (expr)) == 1))
5376       && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0))
5377     {
5378       mode = DECL_MODE (expr);
5379       offset = 0;
5380     }
5381 
5382   HOST_WIDE_INT const_offset;
5383   if (!track_offset_p (offset, &const_offset))
5384     return false;
5385 
5386   if (mode_out)
5387     *mode_out = mode;
5388   if (offset_out)
5389     *offset_out = const_offset;
5390   return true;
5391 }
5392 
5393 /* Return the MODE lowpart of LOC, or null if LOC is not something we
5394    want to track.  When returning nonnull, make sure that the attributes
5395    on the returned value are updated.  */
5396 
5397 static rtx
var_lowpart(machine_mode mode,rtx loc)5398 var_lowpart (machine_mode mode, rtx loc)
5399 {
5400   unsigned int regno;
5401 
5402   if (GET_MODE (loc) == mode)
5403     return loc;
5404 
5405   if (!REG_P (loc) && !MEM_P (loc))
5406     return NULL;
5407 
5408   poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc));
5409 
5410   if (MEM_P (loc))
5411     return adjust_address_nv (loc, mode, offset);
5412 
5413   poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
5414   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
5415 					     reg_offset, mode);
5416   return gen_rtx_REG_offset (loc, mode, regno, offset);
5417 }
5418 
5419 /* Carry information about uses and stores while walking rtx.  */
5420 
5421 struct count_use_info
5422 {
5423   /* The insn where the RTX is.  */
5424   rtx_insn *insn;
5425 
5426   /* The basic block where insn is.  */
5427   basic_block bb;
5428 
5429   /* The array of n_sets sets in the insn, as determined by cselib.  */
5430   struct cselib_set *sets;
5431   int n_sets;
5432 
5433   /* True if we're counting stores, false otherwise.  */
5434   bool store_p;
5435 };
5436 
5437 /* Find a VALUE corresponding to X.   */
5438 
5439 static inline cselib_val *
find_use_val(rtx x,machine_mode mode,struct count_use_info * cui)5440 find_use_val (rtx x, machine_mode mode, struct count_use_info *cui)
5441 {
5442   int i;
5443 
5444   if (cui->sets)
5445     {
5446       /* This is called after uses are set up and before stores are
5447 	 processed by cselib, so it's safe to look up srcs, but not
5448 	 dsts.  So we look up expressions that appear in srcs or in
5449 	 dest expressions, but we search the sets array for dests of
5450 	 stores.  */
5451       if (cui->store_p)
5452 	{
5453 	  /* Some targets represent memset and memcpy patterns
5454 	     by (set (mem:BLK ...) (reg:[QHSD]I ...)) or
5455 	     (set (mem:BLK ...) (const_int ...)) or
5456 	     (set (mem:BLK ...) (mem:BLK ...)).  Don't return anything
5457 	     in that case, otherwise we end up with mode mismatches.  */
5458 	  if (mode == BLKmode && MEM_P (x))
5459 	    return NULL;
5460 	  for (i = 0; i < cui->n_sets; i++)
5461 	    if (cui->sets[i].dest == x)
5462 	      return cui->sets[i].src_elt;
5463 	}
5464       else
5465 	return cselib_lookup (x, mode, 0, VOIDmode);
5466     }
5467 
5468   return NULL;
5469 }
5470 
5471 /* Replace all registers and addresses in an expression with VALUE
5472    expressions that map back to them, unless the expression is a
5473    register.  If no mapping is or can be performed, returns NULL.  */
5474 
5475 static rtx
replace_expr_with_values(rtx loc)5476 replace_expr_with_values (rtx loc)
5477 {
5478   if (REG_P (loc) || GET_CODE (loc) == ENTRY_VALUE)
5479     return NULL;
5480   else if (MEM_P (loc))
5481     {
5482       cselib_val *addr = cselib_lookup (XEXP (loc, 0),
5483 					get_address_mode (loc), 0,
5484 					GET_MODE (loc));
5485       if (addr)
5486 	return replace_equiv_address_nv (loc, addr->val_rtx);
5487       else
5488 	return NULL;
5489     }
5490   else
5491     return cselib_subst_to_values (loc, VOIDmode);
5492 }
5493 
5494 /* Return true if X contains a DEBUG_EXPR.  */
5495 
5496 static bool
rtx_debug_expr_p(const_rtx x)5497 rtx_debug_expr_p (const_rtx x)
5498 {
5499   subrtx_iterator::array_type array;
5500   FOR_EACH_SUBRTX (iter, array, x, ALL)
5501     if (GET_CODE (*iter) == DEBUG_EXPR)
5502       return true;
5503   return false;
5504 }
5505 
5506 /* Determine what kind of micro operation to choose for a USE.  Return
5507    MO_CLOBBER if no micro operation is to be generated.  */
5508 
5509 static enum micro_operation_type
use_type(rtx loc,struct count_use_info * cui,machine_mode * modep)5510 use_type (rtx loc, struct count_use_info *cui, machine_mode *modep)
5511 {
5512   tree expr;
5513 
5514   if (cui && cui->sets)
5515     {
5516       if (GET_CODE (loc) == VAR_LOCATION)
5517 	{
5518 	  if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false))
5519 	    {
5520 	      rtx ploc = PAT_VAR_LOCATION_LOC (loc);
5521 	      if (! VAR_LOC_UNKNOWN_P (ploc))
5522 		{
5523 		  cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1,
5524 						   VOIDmode);
5525 
5526 		  /* ??? flag_float_store and volatile mems are never
5527 		     given values, but we could in theory use them for
5528 		     locations.  */
5529 		  gcc_assert (val || 1);
5530 		}
5531 	      return MO_VAL_LOC;
5532 	    }
5533 	  else
5534 	    return MO_CLOBBER;
5535 	}
5536 
5537       if (REG_P (loc) || MEM_P (loc))
5538 	{
5539 	  if (modep)
5540 	    *modep = GET_MODE (loc);
5541 	  if (cui->store_p)
5542 	    {
5543 	      if (REG_P (loc)
5544 		  || (find_use_val (loc, GET_MODE (loc), cui)
5545 		      && cselib_lookup (XEXP (loc, 0),
5546 					get_address_mode (loc), 0,
5547 					GET_MODE (loc))))
5548 		return MO_VAL_SET;
5549 	    }
5550 	  else
5551 	    {
5552 	      cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
5553 
5554 	      if (val && !cselib_preserved_value_p (val))
5555 		return MO_VAL_USE;
5556 	    }
5557 	}
5558     }
5559 
5560   if (REG_P (loc))
5561     {
5562       gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER);
5563 
5564       if (loc == cfa_base_rtx)
5565 	return MO_CLOBBER;
5566       expr = REG_EXPR (loc);
5567 
5568       if (!expr)
5569 	return MO_USE_NO_VAR;
5570       else if (target_for_debug_bind (var_debug_decl (expr)))
5571 	return MO_CLOBBER;
5572       else if (track_loc_p (loc, expr, REG_OFFSET (loc),
5573 			    false, modep, NULL))
5574 	return MO_USE;
5575       else
5576 	return MO_USE_NO_VAR;
5577     }
5578   else if (MEM_P (loc))
5579     {
5580       expr = MEM_EXPR (loc);
5581 
5582       if (!expr)
5583 	return MO_CLOBBER;
5584       else if (target_for_debug_bind (var_debug_decl (expr)))
5585 	return MO_CLOBBER;
5586       else if (track_loc_p (loc, expr, int_mem_offset (loc),
5587 			    false, modep, NULL)
5588 	       /* Multi-part variables shouldn't refer to one-part
5589 		  variable names such as VALUEs (never happens) or
5590 		  DEBUG_EXPRs (only happens in the presence of debug
5591 		  insns).  */
5592 	       && (!MAY_HAVE_DEBUG_BIND_INSNS
5593 		   || !rtx_debug_expr_p (XEXP (loc, 0))))
5594 	return MO_USE;
5595       else
5596 	return MO_CLOBBER;
5597     }
5598 
5599   return MO_CLOBBER;
5600 }
5601 
5602 /* Log to OUT information about micro-operation MOPT involving X in
5603    INSN of BB.  */
5604 
5605 static inline void
log_op_type(rtx x,basic_block bb,rtx_insn * insn,enum micro_operation_type mopt,FILE * out)5606 log_op_type (rtx x, basic_block bb, rtx_insn *insn,
5607 	     enum micro_operation_type mopt, FILE *out)
5608 {
5609   fprintf (out, "bb %i op %i insn %i %s ",
5610 	   bb->index, VTI (bb)->mos.length (),
5611 	   INSN_UID (insn), micro_operation_type_name[mopt]);
5612   print_inline_rtx (out, x, 2);
5613   fputc ('\n', out);
5614 }
5615 
5616 /* Tell whether the CONCAT used to holds a VALUE and its location
5617    needs value resolution, i.e., an attempt of mapping the location
5618    back to other incoming values.  */
5619 #define VAL_NEEDS_RESOLUTION(x) \
5620   (RTL_FLAG_CHECK1 ("VAL_NEEDS_RESOLUTION", (x), CONCAT)->volatil)
5621 /* Whether the location in the CONCAT is a tracked expression, that
5622    should also be handled like a MO_USE.  */
5623 #define VAL_HOLDS_TRACK_EXPR(x) \
5624   (RTL_FLAG_CHECK1 ("VAL_HOLDS_TRACK_EXPR", (x), CONCAT)->used)
5625 /* Whether the location in the CONCAT should be handled like a MO_COPY
5626    as well.  */
5627 #define VAL_EXPR_IS_COPIED(x) \
5628   (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_COPIED", (x), CONCAT)->jump)
5629 /* Whether the location in the CONCAT should be handled like a
5630    MO_CLOBBER as well.  */
5631 #define VAL_EXPR_IS_CLOBBERED(x) \
5632   (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_CLOBBERED", (x), CONCAT)->unchanging)
5633 
5634 /* All preserved VALUEs.  */
5635 static vec<rtx> preserved_values;
5636 
5637 /* Ensure VAL is preserved and remember it in a vector for vt_emit_notes.  */
5638 
5639 static void
preserve_value(cselib_val * val)5640 preserve_value (cselib_val *val)
5641 {
5642   cselib_preserve_value (val);
5643   preserved_values.safe_push (val->val_rtx);
5644 }
5645 
5646 /* Helper function for MO_VAL_LOC handling.  Return non-zero if
5647    any rtxes not suitable for CONST use not replaced by VALUEs
5648    are discovered.  */
5649 
5650 static bool
non_suitable_const(const_rtx x)5651 non_suitable_const (const_rtx x)
5652 {
5653   subrtx_iterator::array_type array;
5654   FOR_EACH_SUBRTX (iter, array, x, ALL)
5655     {
5656       const_rtx x = *iter;
5657       switch (GET_CODE (x))
5658 	{
5659 	case REG:
5660 	case DEBUG_EXPR:
5661 	case PC:
5662 	case SCRATCH:
5663 	case ASM_INPUT:
5664 	case ASM_OPERANDS:
5665 	  return true;
5666 	case MEM:
5667 	  if (!MEM_READONLY_P (x))
5668 	    return true;
5669 	  break;
5670 	default:
5671 	  break;
5672 	}
5673     }
5674   return false;
5675 }
5676 
5677 /* Add uses (register and memory references) LOC which will be tracked
5678    to VTI (bb)->mos.  */
5679 
5680 static void
add_uses(rtx loc,struct count_use_info * cui)5681 add_uses (rtx loc, struct count_use_info *cui)
5682 {
5683   machine_mode mode = VOIDmode;
5684   enum micro_operation_type type = use_type (loc, cui, &mode);
5685 
5686   if (type != MO_CLOBBER)
5687     {
5688       basic_block bb = cui->bb;
5689       micro_operation mo;
5690 
5691       mo.type = type;
5692       mo.u.loc = type == MO_USE ? var_lowpart (mode, loc) : loc;
5693       mo.insn = cui->insn;
5694 
5695       if (type == MO_VAL_LOC)
5696 	{
5697 	  rtx oloc = loc;
5698 	  rtx vloc = PAT_VAR_LOCATION_LOC (oloc);
5699 	  cselib_val *val;
5700 
5701 	  gcc_assert (cui->sets);
5702 
5703 	  if (MEM_P (vloc)
5704 	      && !REG_P (XEXP (vloc, 0))
5705 	      && !MEM_P (XEXP (vloc, 0)))
5706 	    {
5707 	      rtx mloc = vloc;
5708 	      machine_mode address_mode = get_address_mode (mloc);
5709 	      cselib_val *val
5710 		= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
5711 				 GET_MODE (mloc));
5712 
5713 	      if (val && !cselib_preserved_value_p (val))
5714 		preserve_value (val);
5715 	    }
5716 
5717 	  if (CONSTANT_P (vloc)
5718 	      && (GET_CODE (vloc) != CONST || non_suitable_const (vloc)))
5719 	    /* For constants don't look up any value.  */;
5720 	  else if (!VAR_LOC_UNKNOWN_P (vloc) && !unsuitable_loc (vloc)
5721 		   && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
5722 	    {
5723 	      machine_mode mode2;
5724 	      enum micro_operation_type type2;
5725 	      rtx nloc = NULL;
5726 	      bool resolvable = REG_P (vloc) || MEM_P (vloc);
5727 
5728 	      if (resolvable)
5729 		nloc = replace_expr_with_values (vloc);
5730 
5731 	      if (nloc)
5732 		{
5733 		  oloc = shallow_copy_rtx (oloc);
5734 		  PAT_VAR_LOCATION_LOC (oloc) = nloc;
5735 		}
5736 
5737 	      oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc);
5738 
5739 	      type2 = use_type (vloc, 0, &mode2);
5740 
5741 	      gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
5742 			  || type2 == MO_CLOBBER);
5743 
5744 	      if (type2 == MO_CLOBBER
5745 		  && !cselib_preserved_value_p (val))
5746 		{
5747 		  VAL_NEEDS_RESOLUTION (oloc) = resolvable;
5748 		  preserve_value (val);
5749 		}
5750 	    }
5751 	  else if (!VAR_LOC_UNKNOWN_P (vloc))
5752 	    {
5753 	      oloc = shallow_copy_rtx (oloc);
5754 	      PAT_VAR_LOCATION_LOC (oloc) = gen_rtx_UNKNOWN_VAR_LOC ();
5755 	    }
5756 
5757 	  mo.u.loc = oloc;
5758 	}
5759       else if (type == MO_VAL_USE)
5760 	{
5761 	  machine_mode mode2 = VOIDmode;
5762 	  enum micro_operation_type type2;
5763 	  cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
5764 	  rtx vloc, oloc = loc, nloc;
5765 
5766 	  gcc_assert (cui->sets);
5767 
5768 	  if (MEM_P (oloc)
5769 	      && !REG_P (XEXP (oloc, 0))
5770 	      && !MEM_P (XEXP (oloc, 0)))
5771 	    {
5772 	      rtx mloc = oloc;
5773 	      machine_mode address_mode = get_address_mode (mloc);
5774 	      cselib_val *val
5775 		= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
5776 				 GET_MODE (mloc));
5777 
5778 	      if (val && !cselib_preserved_value_p (val))
5779 		preserve_value (val);
5780 	    }
5781 
5782 	  type2 = use_type (loc, 0, &mode2);
5783 
5784 	  gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
5785 		      || type2 == MO_CLOBBER);
5786 
5787 	  if (type2 == MO_USE)
5788 	    vloc = var_lowpart (mode2, loc);
5789 	  else
5790 	    vloc = oloc;
5791 
5792 	  /* The loc of a MO_VAL_USE may have two forms:
5793 
5794 	     (concat val src): val is at src, a value-based
5795 	     representation.
5796 
5797 	     (concat (concat val use) src): same as above, with use as
5798 	     the MO_USE tracked value, if it differs from src.
5799 
5800 	  */
5801 
5802 	  gcc_checking_assert (REG_P (loc) || MEM_P (loc));
5803 	  nloc = replace_expr_with_values (loc);
5804 	  if (!nloc)
5805 	    nloc = oloc;
5806 
5807 	  if (vloc != nloc)
5808 	    oloc = gen_rtx_CONCAT (mode2, val->val_rtx, vloc);
5809 	  else
5810 	    oloc = val->val_rtx;
5811 
5812 	  mo.u.loc = gen_rtx_CONCAT (mode, oloc, nloc);
5813 
5814 	  if (type2 == MO_USE)
5815 	    VAL_HOLDS_TRACK_EXPR (mo.u.loc) = 1;
5816 	  if (!cselib_preserved_value_p (val))
5817 	    {
5818 	      VAL_NEEDS_RESOLUTION (mo.u.loc) = 1;
5819 	      preserve_value (val);
5820 	    }
5821 	}
5822       else
5823 	gcc_assert (type == MO_USE || type == MO_USE_NO_VAR);
5824 
5825       if (dump_file && (dump_flags & TDF_DETAILS))
5826 	log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
5827       VTI (bb)->mos.safe_push (mo);
5828     }
5829 }
5830 
5831 /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
5832 
5833 static void
add_uses_1(rtx * x,void * cui)5834 add_uses_1 (rtx *x, void *cui)
5835 {
5836   subrtx_var_iterator::array_type array;
5837   FOR_EACH_SUBRTX_VAR (iter, array, *x, NONCONST)
5838     add_uses (*iter, (struct count_use_info *) cui);
5839 }
5840 
5841 /* This is the value used during expansion of locations.  We want it
5842    to be unbounded, so that variables expanded deep in a recursion
5843    nest are fully evaluated, so that their values are cached
5844    correctly.  We avoid recursion cycles through other means, and we
5845    don't unshare RTL, so excess complexity is not a problem.  */
5846 #define EXPR_DEPTH (INT_MAX)
5847 /* We use this to keep too-complex expressions from being emitted as
5848    location notes, and then to debug information.  Users can trade
5849    compile time for ridiculously complex expressions, although they're
5850    seldom useful, and they may often have to be discarded as not
5851    representable anyway.  */
5852 #define EXPR_USE_DEPTH (param_max_vartrack_expr_depth)
5853 
5854 /* Attempt to reverse the EXPR operation in the debug info and record
5855    it in the cselib table.  Say for reg1 = reg2 + 6 even when reg2 is
5856    no longer live we can express its value as VAL - 6.  */
5857 
5858 static void
reverse_op(rtx val,const_rtx expr,rtx_insn * insn)5859 reverse_op (rtx val, const_rtx expr, rtx_insn *insn)
5860 {
5861   rtx src, arg, ret;
5862   cselib_val *v;
5863   struct elt_loc_list *l;
5864   enum rtx_code code;
5865   int count;
5866 
5867   if (GET_CODE (expr) != SET)
5868     return;
5869 
5870   if (!REG_P (SET_DEST (expr)) || GET_MODE (val) != GET_MODE (SET_DEST (expr)))
5871     return;
5872 
5873   src = SET_SRC (expr);
5874   switch (GET_CODE (src))
5875     {
5876     case PLUS:
5877     case MINUS:
5878     case XOR:
5879     case NOT:
5880     case NEG:
5881       if (!REG_P (XEXP (src, 0)))
5882 	return;
5883       break;
5884     case SIGN_EXTEND:
5885     case ZERO_EXTEND:
5886       if (!REG_P (XEXP (src, 0)) && !MEM_P (XEXP (src, 0)))
5887 	return;
5888       break;
5889     default:
5890       return;
5891     }
5892 
5893   if (!SCALAR_INT_MODE_P (GET_MODE (src)) || XEXP (src, 0) == cfa_base_rtx)
5894     return;
5895 
5896   v = cselib_lookup (XEXP (src, 0), GET_MODE (XEXP (src, 0)), 0, VOIDmode);
5897   if (!v || !cselib_preserved_value_p (v))
5898     return;
5899 
5900   /* Use canonical V to avoid creating multiple redundant expressions
5901      for different VALUES equivalent to V.  */
5902   v = canonical_cselib_val (v);
5903 
5904   /* Adding a reverse op isn't useful if V already has an always valid
5905      location.  Ignore ENTRY_VALUE, while it is always constant, we should
5906      prefer non-ENTRY_VALUE locations whenever possible.  */
5907   for (l = v->locs, count = 0; l; l = l->next, count++)
5908     if (CONSTANT_P (l->loc)
5909 	&& (GET_CODE (l->loc) != CONST || !references_value_p (l->loc, 0)))
5910       return;
5911     /* Avoid creating too large locs lists.  */
5912     else if (count == param_max_vartrack_reverse_op_size)
5913       return;
5914 
5915   switch (GET_CODE (src))
5916     {
5917     case NOT:
5918     case NEG:
5919       if (GET_MODE (v->val_rtx) != GET_MODE (val))
5920 	return;
5921       ret = gen_rtx_fmt_e (GET_CODE (src), GET_MODE (val), val);
5922       break;
5923     case SIGN_EXTEND:
5924     case ZERO_EXTEND:
5925       ret = gen_lowpart_SUBREG (GET_MODE (v->val_rtx), val);
5926       break;
5927     case XOR:
5928       code = XOR;
5929       goto binary;
5930     case PLUS:
5931       code = MINUS;
5932       goto binary;
5933     case MINUS:
5934       code = PLUS;
5935       goto binary;
5936     binary:
5937       if (GET_MODE (v->val_rtx) != GET_MODE (val))
5938 	return;
5939       arg = XEXP (src, 1);
5940       if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
5941 	{
5942 	  arg = cselib_expand_value_rtx (arg, scratch_regs, 5);
5943 	  if (arg == NULL_RTX)
5944 	    return;
5945 	  if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
5946 	    return;
5947 	}
5948       ret = simplify_gen_binary (code, GET_MODE (val), val, arg);
5949       break;
5950     default:
5951       gcc_unreachable ();
5952     }
5953 
5954   cselib_add_permanent_equiv (v, ret, insn);
5955 }
5956 
5957 /* Add stores (register and memory references) LOC which will be tracked
5958    to VTI (bb)->mos.  EXPR is the RTL expression containing the store.
5959    CUIP->insn is instruction which the LOC is part of.  */
5960 
5961 static void
add_stores(rtx loc,const_rtx expr,void * cuip)5962 add_stores (rtx loc, const_rtx expr, void *cuip)
5963 {
5964   machine_mode mode = VOIDmode, mode2;
5965   struct count_use_info *cui = (struct count_use_info *)cuip;
5966   basic_block bb = cui->bb;
5967   micro_operation mo;
5968   rtx oloc = loc, nloc, src = NULL;
5969   enum micro_operation_type type = use_type (loc, cui, &mode);
5970   bool track_p = false;
5971   cselib_val *v;
5972   bool resolve, preserve;
5973 
5974   if (type == MO_CLOBBER)
5975     return;
5976 
5977   mode2 = mode;
5978 
5979   if (REG_P (loc))
5980     {
5981       gcc_assert (loc != cfa_base_rtx);
5982       if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET)
5983 	  || !(track_p = use_type (loc, NULL, &mode2) == MO_USE)
5984 	  || GET_CODE (expr) == CLOBBER)
5985 	{
5986 	  mo.type = MO_CLOBBER;
5987 	  mo.u.loc = loc;
5988 	  if (GET_CODE (expr) == SET
5989 	      && (SET_DEST (expr) == loc
5990 		  || (GET_CODE (SET_DEST (expr)) == STRICT_LOW_PART
5991 		      && XEXP (SET_DEST (expr), 0) == loc))
5992 	      && !unsuitable_loc (SET_SRC (expr))
5993 	      && find_use_val (loc, mode, cui))
5994 	    {
5995 	      gcc_checking_assert (type == MO_VAL_SET);
5996 	      mo.u.loc = gen_rtx_SET (loc, SET_SRC (expr));
5997 	    }
5998 	}
5999       else
6000 	{
6001 	  if (GET_CODE (expr) == SET
6002 	      && SET_DEST (expr) == loc
6003 	      && GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
6004 	    src = var_lowpart (mode2, SET_SRC (expr));
6005 	  loc = var_lowpart (mode2, loc);
6006 
6007 	  if (src == NULL)
6008 	    {
6009 	      mo.type = MO_SET;
6010 	      mo.u.loc = loc;
6011 	    }
6012 	  else
6013 	    {
6014 	      rtx xexpr = gen_rtx_SET (loc, src);
6015 	      if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
6016 		{
6017 		  /* If this is an instruction copying (part of) a parameter
6018 		     passed by invisible reference to its register location,
6019 		     pretend it's a SET so that the initial memory location
6020 		     is discarded, as the parameter register can be reused
6021 		     for other purposes and we do not track locations based
6022 		     on generic registers.  */
6023 		  if (MEM_P (src)
6024 		      && REG_EXPR (loc)
6025 		      && TREE_CODE (REG_EXPR (loc)) == PARM_DECL
6026 		      && DECL_MODE (REG_EXPR (loc)) != BLKmode
6027 		      && MEM_P (DECL_INCOMING_RTL (REG_EXPR (loc)))
6028 		      && XEXP (DECL_INCOMING_RTL (REG_EXPR (loc)), 0)
6029 			 != arg_pointer_rtx)
6030 		    mo.type = MO_SET;
6031 		  else
6032 		    mo.type = MO_COPY;
6033 		}
6034 	      else
6035 		mo.type = MO_SET;
6036 	      mo.u.loc = xexpr;
6037 	    }
6038 	}
6039       mo.insn = cui->insn;
6040     }
6041   else if (MEM_P (loc)
6042 	   && ((track_p = use_type (loc, NULL, &mode2) == MO_USE)
6043 	       || cui->sets))
6044     {
6045       if (MEM_P (loc) && type == MO_VAL_SET
6046 	  && !REG_P (XEXP (loc, 0))
6047 	  && !MEM_P (XEXP (loc, 0)))
6048 	{
6049 	  rtx mloc = loc;
6050 	  machine_mode address_mode = get_address_mode (mloc);
6051 	  cselib_val *val = cselib_lookup (XEXP (mloc, 0),
6052 					   address_mode, 0,
6053 					   GET_MODE (mloc));
6054 
6055 	  if (val && !cselib_preserved_value_p (val))
6056 	    preserve_value (val);
6057 	}
6058 
6059       if (GET_CODE (expr) == CLOBBER || !track_p)
6060 	{
6061 	  mo.type = MO_CLOBBER;
6062 	  mo.u.loc = track_p ? var_lowpart (mode2, loc) : loc;
6063 	}
6064       else
6065 	{
6066 	  if (GET_CODE (expr) == SET
6067 	      && SET_DEST (expr) == loc
6068 	      && GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
6069 	    src = var_lowpart (mode2, SET_SRC (expr));
6070 	  loc = var_lowpart (mode2, loc);
6071 
6072 	  if (src == NULL)
6073 	    {
6074 	      mo.type = MO_SET;
6075 	      mo.u.loc = loc;
6076 	    }
6077 	  else
6078 	    {
6079 	      rtx xexpr = gen_rtx_SET (loc, src);
6080 	      if (same_variable_part_p (SET_SRC (xexpr),
6081 					MEM_EXPR (loc),
6082 					int_mem_offset (loc)))
6083 		mo.type = MO_COPY;
6084 	      else
6085 		mo.type = MO_SET;
6086 	      mo.u.loc = xexpr;
6087 	    }
6088 	}
6089       mo.insn = cui->insn;
6090     }
6091   else
6092     return;
6093 
6094   if (type != MO_VAL_SET)
6095     goto log_and_return;
6096 
6097   v = find_use_val (oloc, mode, cui);
6098 
6099   if (!v)
6100     goto log_and_return;
6101 
6102   resolve = preserve = !cselib_preserved_value_p (v);
6103 
6104   /* We cannot track values for multiple-part variables, so we track only
6105      locations for tracked record parameters.  */
6106   if (track_p
6107       && REG_P (loc)
6108       && REG_EXPR (loc)
6109       && tracked_record_parameter_p (REG_EXPR (loc)))
6110     {
6111       /* Although we don't use the value here, it could be used later by the
6112 	 mere virtue of its existence as the operand of the reverse operation
6113 	 that gave rise to it (typically extension/truncation).  Make sure it
6114 	 is preserved as required by vt_expand_var_loc_chain.  */
6115       if (preserve)
6116 	preserve_value (v);
6117       goto log_and_return;
6118     }
6119 
6120   if (loc == stack_pointer_rtx
6121       && (maybe_ne (hard_frame_pointer_adjustment, -1)
6122 	  || (!frame_pointer_needed && !ACCUMULATE_OUTGOING_ARGS))
6123       && preserve)
6124     cselib_set_value_sp_based (v);
6125 
6126   /* Don't record MO_VAL_SET for VALUEs that can be described using
6127      cfa_base_rtx or cfa_base_rtx + CONST_INT, cselib already knows
6128      all the needed equivalences and they shouldn't change depending
6129      on which register holds that VALUE in some instruction.  */
6130   if (!frame_pointer_needed
6131       && cfa_base_rtx
6132       && cselib_sp_derived_value_p (v)
6133       && loc == stack_pointer_rtx)
6134     {
6135       if (preserve)
6136 	preserve_value (v);
6137       return;
6138     }
6139 
6140   nloc = replace_expr_with_values (oloc);
6141   if (nloc)
6142     oloc = nloc;
6143 
6144   if (GET_CODE (PATTERN (cui->insn)) == COND_EXEC)
6145     {
6146       cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0, VOIDmode);
6147 
6148       if (oval == v)
6149 	return;
6150       gcc_assert (REG_P (oloc) || MEM_P (oloc));
6151 
6152       if (oval && !cselib_preserved_value_p (oval))
6153 	{
6154 	  micro_operation moa;
6155 
6156 	  preserve_value (oval);
6157 
6158 	  moa.type = MO_VAL_USE;
6159 	  moa.u.loc = gen_rtx_CONCAT (mode, oval->val_rtx, oloc);
6160 	  VAL_NEEDS_RESOLUTION (moa.u.loc) = 1;
6161 	  moa.insn = cui->insn;
6162 
6163 	  if (dump_file && (dump_flags & TDF_DETAILS))
6164 	    log_op_type (moa.u.loc, cui->bb, cui->insn,
6165 			 moa.type, dump_file);
6166 	  VTI (bb)->mos.safe_push (moa);
6167 	}
6168 
6169       resolve = false;
6170     }
6171   else if (resolve && GET_CODE (mo.u.loc) == SET)
6172     {
6173       if (REG_P (SET_SRC (expr)) || MEM_P (SET_SRC (expr)))
6174 	nloc = replace_expr_with_values (SET_SRC (expr));
6175       else
6176 	nloc = NULL_RTX;
6177 
6178       /* Avoid the mode mismatch between oexpr and expr.  */
6179       if (!nloc && mode != mode2)
6180 	{
6181 	  nloc = SET_SRC (expr);
6182 	  gcc_assert (oloc == SET_DEST (expr));
6183 	}
6184 
6185       if (nloc && nloc != SET_SRC (mo.u.loc))
6186 	oloc = gen_rtx_SET (oloc, nloc);
6187       else
6188 	{
6189 	  if (oloc == SET_DEST (mo.u.loc))
6190 	    /* No point in duplicating.  */
6191 	    oloc = mo.u.loc;
6192 	  if (!REG_P (SET_SRC (mo.u.loc)))
6193 	    resolve = false;
6194 	}
6195     }
6196   else if (!resolve)
6197     {
6198       if (GET_CODE (mo.u.loc) == SET
6199 	  && oloc == SET_DEST (mo.u.loc))
6200 	/* No point in duplicating.  */
6201 	oloc = mo.u.loc;
6202     }
6203   else
6204     resolve = false;
6205 
6206   loc = gen_rtx_CONCAT (mode, v->val_rtx, oloc);
6207 
6208   if (mo.u.loc != oloc)
6209     loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, mo.u.loc);
6210 
6211   /* The loc of a MO_VAL_SET may have various forms:
6212 
6213      (concat val dst): dst now holds val
6214 
6215      (concat val (set dst src)): dst now holds val, copied from src
6216 
6217      (concat (concat val dstv) dst): dst now holds val; dstv is dst
6218      after replacing mems and non-top-level regs with values.
6219 
6220      (concat (concat val dstv) (set dst src)): dst now holds val,
6221      copied from src.  dstv is a value-based representation of dst, if
6222      it differs from dst.  If resolution is needed, src is a REG, and
6223      its mode is the same as that of val.
6224 
6225      (concat (concat val (set dstv srcv)) (set dst src)): src
6226      copied to dst, holding val.  dstv and srcv are value-based
6227      representations of dst and src, respectively.
6228 
6229   */
6230 
6231   if (GET_CODE (PATTERN (cui->insn)) != COND_EXEC)
6232     reverse_op (v->val_rtx, expr, cui->insn);
6233 
6234   mo.u.loc = loc;
6235 
6236   if (track_p)
6237     VAL_HOLDS_TRACK_EXPR (loc) = 1;
6238   if (preserve)
6239     {
6240       VAL_NEEDS_RESOLUTION (loc) = resolve;
6241       preserve_value (v);
6242     }
6243   if (mo.type == MO_CLOBBER)
6244     VAL_EXPR_IS_CLOBBERED (loc) = 1;
6245   if (mo.type == MO_COPY)
6246     VAL_EXPR_IS_COPIED (loc) = 1;
6247 
6248   mo.type = MO_VAL_SET;
6249 
6250  log_and_return:
6251   if (dump_file && (dump_flags & TDF_DETAILS))
6252     log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
6253   VTI (bb)->mos.safe_push (mo);
6254 }
6255 
6256 /* Arguments to the call.  */
6257 static rtx call_arguments;
6258 
6259 /* Compute call_arguments.  */
6260 
6261 static void
prepare_call_arguments(basic_block bb,rtx_insn * insn)6262 prepare_call_arguments (basic_block bb, rtx_insn *insn)
6263 {
6264   rtx link, x, call;
6265   rtx prev, cur, next;
6266   rtx this_arg = NULL_RTX;
6267   tree type = NULL_TREE, t, fndecl = NULL_TREE;
6268   tree obj_type_ref = NULL_TREE;
6269   CUMULATIVE_ARGS args_so_far_v;
6270   cumulative_args_t args_so_far;
6271 
6272   memset (&args_so_far_v, 0, sizeof (args_so_far_v));
6273   args_so_far = pack_cumulative_args (&args_so_far_v);
6274   call = get_call_rtx_from (insn);
6275   if (call)
6276     {
6277       if (GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
6278 	{
6279 	  rtx symbol = XEXP (XEXP (call, 0), 0);
6280 	  if (SYMBOL_REF_DECL (symbol))
6281 	    fndecl = SYMBOL_REF_DECL (symbol);
6282 	}
6283       if (fndecl == NULL_TREE)
6284 	fndecl = MEM_EXPR (XEXP (call, 0));
6285       if (fndecl
6286 	  && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE
6287 	  && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE)
6288 	fndecl = NULL_TREE;
6289       if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
6290 	type = TREE_TYPE (fndecl);
6291       if (fndecl && TREE_CODE (fndecl) != FUNCTION_DECL)
6292 	{
6293 	  if (TREE_CODE (fndecl) == INDIRECT_REF
6294 	      && TREE_CODE (TREE_OPERAND (fndecl, 0)) == OBJ_TYPE_REF)
6295 	    obj_type_ref = TREE_OPERAND (fndecl, 0);
6296 	  fndecl = NULL_TREE;
6297 	}
6298       if (type)
6299 	{
6300 	  for (t = TYPE_ARG_TYPES (type); t && t != void_list_node;
6301 	       t = TREE_CHAIN (t))
6302 	    if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
6303 		&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t))))
6304 	      break;
6305 	  if ((t == NULL || t == void_list_node) && obj_type_ref == NULL_TREE)
6306 	    type = NULL;
6307 	  else
6308 	    {
6309 	      int nargs ATTRIBUTE_UNUSED = list_length (TYPE_ARG_TYPES (type));
6310 	      link = CALL_INSN_FUNCTION_USAGE (insn);
6311 #ifndef PCC_STATIC_STRUCT_RETURN
6312 	      if (aggregate_value_p (TREE_TYPE (type), type)
6313 		  && targetm.calls.struct_value_rtx (type, 0) == 0)
6314 		{
6315 		  tree struct_addr = build_pointer_type (TREE_TYPE (type));
6316 		  function_arg_info arg (struct_addr, /*named=*/true);
6317 		  rtx reg;
6318 		  INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
6319 					nargs + 1);
6320 		  reg = targetm.calls.function_arg (args_so_far, arg);
6321 		  targetm.calls.function_arg_advance (args_so_far, arg);
6322 		  if (reg == NULL_RTX)
6323 		    {
6324 		      for (; link; link = XEXP (link, 1))
6325 			if (GET_CODE (XEXP (link, 0)) == USE
6326 			    && MEM_P (XEXP (XEXP (link, 0), 0)))
6327 			  {
6328 			    link = XEXP (link, 1);
6329 			    break;
6330 			  }
6331 		    }
6332 		}
6333 	      else
6334 #endif
6335 		INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
6336 				      nargs);
6337 	      if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
6338 		{
6339 		  t = TYPE_ARG_TYPES (type);
6340 		  function_arg_info arg (TREE_VALUE (t), /*named=*/true);
6341 		  this_arg = targetm.calls.function_arg (args_so_far, arg);
6342 		  if (this_arg && !REG_P (this_arg))
6343 		    this_arg = NULL_RTX;
6344 		  else if (this_arg == NULL_RTX)
6345 		    {
6346 		      for (; link; link = XEXP (link, 1))
6347 			if (GET_CODE (XEXP (link, 0)) == USE
6348 			    && MEM_P (XEXP (XEXP (link, 0), 0)))
6349 			  {
6350 			    this_arg = XEXP (XEXP (link, 0), 0);
6351 			    break;
6352 			  }
6353 		    }
6354 		}
6355 	    }
6356 	}
6357     }
6358   t = type ? TYPE_ARG_TYPES (type) : NULL_TREE;
6359 
6360   for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
6361     if (GET_CODE (XEXP (link, 0)) == USE)
6362       {
6363 	rtx item = NULL_RTX;
6364 	x = XEXP (XEXP (link, 0), 0);
6365 	if (GET_MODE (link) == VOIDmode
6366 	    || GET_MODE (link) == BLKmode
6367 	    || (GET_MODE (link) != GET_MODE (x)
6368 		&& ((GET_MODE_CLASS (GET_MODE (link)) != MODE_INT
6369 		     && GET_MODE_CLASS (GET_MODE (link)) != MODE_PARTIAL_INT)
6370 		    || (GET_MODE_CLASS (GET_MODE (x)) != MODE_INT
6371 			&& GET_MODE_CLASS (GET_MODE (x)) != MODE_PARTIAL_INT))))
6372 	  /* Can't do anything for these, if the original type mode
6373 	     isn't known or can't be converted.  */;
6374 	else if (REG_P (x))
6375 	  {
6376 	    cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
6377 	    scalar_int_mode mode;
6378 	    if (val && cselib_preserved_value_p (val))
6379 	      item = val->val_rtx;
6380 	    else if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
6381 	      {
6382 		opt_scalar_int_mode mode_iter;
6383 		FOR_EACH_WIDER_MODE (mode_iter, mode)
6384 		  {
6385 		    mode = mode_iter.require ();
6386 		    if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
6387 		      break;
6388 
6389 		    rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
6390 		    if (reg == NULL_RTX || !REG_P (reg))
6391 		      continue;
6392 		    val = cselib_lookup (reg, mode, 0, VOIDmode);
6393 		    if (val && cselib_preserved_value_p (val))
6394 		      {
6395 			item = val->val_rtx;
6396 			break;
6397 		      }
6398 		  }
6399 	      }
6400 	  }
6401 	else if (MEM_P (x))
6402 	  {
6403 	    rtx mem = x;
6404 	    cselib_val *val;
6405 
6406 	    if (!frame_pointer_needed)
6407 	      {
6408 		class adjust_mem_data amd;
6409 		amd.mem_mode = VOIDmode;
6410 		amd.stack_adjust = -VTI (bb)->out.stack_adjust;
6411 		amd.store = true;
6412 		mem = simplify_replace_fn_rtx (mem, NULL_RTX, adjust_mems,
6413 					       &amd);
6414 		gcc_assert (amd.side_effects.is_empty ());
6415 	      }
6416 	    val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode);
6417 	    if (val && cselib_preserved_value_p (val))
6418 	      item = val->val_rtx;
6419 	    else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT
6420 		     && GET_MODE_CLASS (GET_MODE (mem)) != MODE_PARTIAL_INT)
6421 	      {
6422 		/* For non-integer stack argument see also if they weren't
6423 		   initialized by integers.  */
6424 		scalar_int_mode imode;
6425 		if (int_mode_for_mode (GET_MODE (mem)).exists (&imode)
6426 		    && imode != GET_MODE (mem))
6427 		  {
6428 		    val = cselib_lookup (adjust_address_nv (mem, imode, 0),
6429 					 imode, 0, VOIDmode);
6430 		    if (val && cselib_preserved_value_p (val))
6431 		      item = lowpart_subreg (GET_MODE (x), val->val_rtx,
6432 					     imode);
6433 		  }
6434 	      }
6435 	  }
6436 	if (item)
6437 	  {
6438 	    rtx x2 = x;
6439 	    if (GET_MODE (item) != GET_MODE (link))
6440 	      item = lowpart_subreg (GET_MODE (link), item, GET_MODE (item));
6441 	    if (GET_MODE (x2) != GET_MODE (link))
6442 	      x2 = lowpart_subreg (GET_MODE (link), x2, GET_MODE (x2));
6443 	    item = gen_rtx_CONCAT (GET_MODE (link), x2, item);
6444 	    call_arguments
6445 	      = gen_rtx_EXPR_LIST (VOIDmode, item, call_arguments);
6446 	  }
6447 	if (t && t != void_list_node)
6448 	  {
6449 	    rtx reg;
6450 	    function_arg_info arg (TREE_VALUE (t), /*named=*/true);
6451 	    apply_pass_by_reference_rules (&args_so_far_v, arg);
6452 	    reg = targetm.calls.function_arg (args_so_far, arg);
6453 	    if (TREE_CODE (arg.type) == REFERENCE_TYPE
6454 		&& INTEGRAL_TYPE_P (TREE_TYPE (arg.type))
6455 		&& reg
6456 		&& REG_P (reg)
6457 		&& GET_MODE (reg) == arg.mode
6458 		&& (GET_MODE_CLASS (arg.mode) == MODE_INT
6459 		    || GET_MODE_CLASS (arg.mode) == MODE_PARTIAL_INT)
6460 		&& REG_P (x)
6461 		&& REGNO (x) == REGNO (reg)
6462 		&& GET_MODE (x) == arg.mode
6463 		&& item)
6464 	      {
6465 		machine_mode indmode
6466 		  = TYPE_MODE (TREE_TYPE (arg.type));
6467 		rtx mem = gen_rtx_MEM (indmode, x);
6468 		cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
6469 		if (val && cselib_preserved_value_p (val))
6470 		  {
6471 		    item = gen_rtx_CONCAT (indmode, mem, val->val_rtx);
6472 		    call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
6473 							call_arguments);
6474 		  }
6475 		else
6476 		  {
6477 		    struct elt_loc_list *l;
6478 		    tree initial;
6479 
6480 		    /* Try harder, when passing address of a constant
6481 		       pool integer it can be easily read back.  */
6482 		    item = XEXP (item, 1);
6483 		    if (GET_CODE (item) == SUBREG)
6484 		      item = SUBREG_REG (item);
6485 		    gcc_assert (GET_CODE (item) == VALUE);
6486 		    val = CSELIB_VAL_PTR (item);
6487 		    for (l = val->locs; l; l = l->next)
6488 		      if (GET_CODE (l->loc) == SYMBOL_REF
6489 			  && TREE_CONSTANT_POOL_ADDRESS_P (l->loc)
6490 			  && SYMBOL_REF_DECL (l->loc)
6491 			  && DECL_INITIAL (SYMBOL_REF_DECL (l->loc)))
6492 			{
6493 			  initial = DECL_INITIAL (SYMBOL_REF_DECL (l->loc));
6494 			  if (tree_fits_shwi_p (initial))
6495 			    {
6496 			      item = GEN_INT (tree_to_shwi (initial));
6497 			      item = gen_rtx_CONCAT (indmode, mem, item);
6498 			      call_arguments
6499 				= gen_rtx_EXPR_LIST (VOIDmode, item,
6500 						     call_arguments);
6501 			    }
6502 			  break;
6503 			}
6504 		  }
6505 	      }
6506 	    targetm.calls.function_arg_advance (args_so_far, arg);
6507 	    t = TREE_CHAIN (t);
6508 	  }
6509       }
6510 
6511   /* Add debug arguments.  */
6512   if (fndecl
6513       && TREE_CODE (fndecl) == FUNCTION_DECL
6514       && DECL_HAS_DEBUG_ARGS_P (fndecl))
6515     {
6516       vec<tree, va_gc> **debug_args = decl_debug_args_lookup (fndecl);
6517       if (debug_args)
6518 	{
6519 	  unsigned int ix;
6520 	  tree param;
6521 	  for (ix = 0; vec_safe_iterate (*debug_args, ix, &param); ix += 2)
6522 	    {
6523 	      rtx item;
6524 	      tree dtemp = (**debug_args)[ix + 1];
6525 	      machine_mode mode = DECL_MODE (dtemp);
6526 	      item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
6527 	      item = gen_rtx_CONCAT (mode, item, DECL_RTL_KNOWN_SET (dtemp));
6528 	      call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
6529 						  call_arguments);
6530 	    }
6531 	}
6532     }
6533 
6534   /* Reverse call_arguments chain.  */
6535   prev = NULL_RTX;
6536   for (cur = call_arguments; cur; cur = next)
6537     {
6538       next = XEXP (cur, 1);
6539       XEXP (cur, 1) = prev;
6540       prev = cur;
6541     }
6542   call_arguments = prev;
6543 
6544   x = get_call_rtx_from (insn);
6545   if (x)
6546     {
6547       x = XEXP (XEXP (x, 0), 0);
6548       if (GET_CODE (x) == SYMBOL_REF)
6549 	/* Don't record anything.  */;
6550       else if (CONSTANT_P (x))
6551 	{
6552 	  x = gen_rtx_CONCAT (GET_MODE (x) == VOIDmode ? Pmode : GET_MODE (x),
6553 			      pc_rtx, x);
6554 	  call_arguments
6555 	    = gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
6556 	}
6557       else
6558 	{
6559 	  cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
6560 	  if (val && cselib_preserved_value_p (val))
6561 	    {
6562 	      x = gen_rtx_CONCAT (GET_MODE (x), pc_rtx, val->val_rtx);
6563 	      call_arguments
6564 		= gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
6565 	    }
6566 	}
6567     }
6568   if (this_arg)
6569     {
6570       machine_mode mode
6571 	= TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
6572       rtx clobbered = gen_rtx_MEM (mode, this_arg);
6573       HOST_WIDE_INT token
6574 	= tree_to_shwi (OBJ_TYPE_REF_TOKEN (obj_type_ref));
6575       if (token)
6576 	clobbered = plus_constant (mode, clobbered,
6577 				   token * GET_MODE_SIZE (mode));
6578       clobbered = gen_rtx_MEM (mode, clobbered);
6579       x = gen_rtx_CONCAT (mode, gen_rtx_CLOBBER (VOIDmode, pc_rtx), clobbered);
6580       call_arguments
6581 	= gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments);
6582     }
6583 }
6584 
6585 /* Callback for cselib_record_sets_hook, that records as micro
6586    operations uses and stores in an insn after cselib_record_sets has
6587    analyzed the sets in an insn, but before it modifies the stored
6588    values in the internal tables, unless cselib_record_sets doesn't
6589    call it directly (perhaps because we're not doing cselib in the
6590    first place, in which case sets and n_sets will be 0).  */
6591 
6592 static void
add_with_sets(rtx_insn * insn,struct cselib_set * sets,int n_sets)6593 add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_sets)
6594 {
6595   basic_block bb = BLOCK_FOR_INSN (insn);
6596   int n1, n2;
6597   struct count_use_info cui;
6598   micro_operation *mos;
6599 
6600   cselib_hook_called = true;
6601 
6602   cui.insn = insn;
6603   cui.bb = bb;
6604   cui.sets = sets;
6605   cui.n_sets = n_sets;
6606 
6607   n1 = VTI (bb)->mos.length ();
6608   cui.store_p = false;
6609   note_uses (&PATTERN (insn), add_uses_1, &cui);
6610   n2 = VTI (bb)->mos.length () - 1;
6611   mos = VTI (bb)->mos.address ();
6612 
6613   /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
6614      MO_VAL_LOC last.  */
6615   while (n1 < n2)
6616     {
6617       while (n1 < n2 && mos[n1].type == MO_USE)
6618 	n1++;
6619       while (n1 < n2 && mos[n2].type != MO_USE)
6620 	n2--;
6621       if (n1 < n2)
6622 	std::swap (mos[n1], mos[n2]);
6623     }
6624 
6625   n2 = VTI (bb)->mos.length () - 1;
6626   while (n1 < n2)
6627     {
6628       while (n1 < n2 && mos[n1].type != MO_VAL_LOC)
6629 	n1++;
6630       while (n1 < n2 && mos[n2].type == MO_VAL_LOC)
6631 	n2--;
6632       if (n1 < n2)
6633 	std::swap (mos[n1], mos[n2]);
6634     }
6635 
6636   if (CALL_P (insn))
6637     {
6638       micro_operation mo;
6639 
6640       mo.type = MO_CALL;
6641       mo.insn = insn;
6642       mo.u.loc = call_arguments;
6643       call_arguments = NULL_RTX;
6644 
6645       if (dump_file && (dump_flags & TDF_DETAILS))
6646 	log_op_type (PATTERN (insn), bb, insn, mo.type, dump_file);
6647       VTI (bb)->mos.safe_push (mo);
6648     }
6649 
6650   n1 = VTI (bb)->mos.length ();
6651   /* This will record NEXT_INSN (insn), such that we can
6652      insert notes before it without worrying about any
6653      notes that MO_USEs might emit after the insn.  */
6654   cui.store_p = true;
6655   note_stores (insn, add_stores, &cui);
6656   n2 = VTI (bb)->mos.length () - 1;
6657   mos = VTI (bb)->mos.address ();
6658 
6659   /* Order the MO_VAL_USEs first (note_stores does nothing
6660      on DEBUG_INSNs, so there are no MO_VAL_LOCs from this
6661      insn), then MO_CLOBBERs, then MO_SET/MO_COPY/MO_VAL_SET.  */
6662   while (n1 < n2)
6663     {
6664       while (n1 < n2 && mos[n1].type == MO_VAL_USE)
6665 	n1++;
6666       while (n1 < n2 && mos[n2].type != MO_VAL_USE)
6667 	n2--;
6668       if (n1 < n2)
6669 	std::swap (mos[n1], mos[n2]);
6670     }
6671 
6672   n2 = VTI (bb)->mos.length () - 1;
6673   while (n1 < n2)
6674     {
6675       while (n1 < n2 && mos[n1].type == MO_CLOBBER)
6676 	n1++;
6677       while (n1 < n2 && mos[n2].type != MO_CLOBBER)
6678 	n2--;
6679       if (n1 < n2)
6680 	std::swap (mos[n1], mos[n2]);
6681     }
6682 }
6683 
6684 static enum var_init_status
find_src_status(dataflow_set * in,rtx src)6685 find_src_status (dataflow_set *in, rtx src)
6686 {
6687   tree decl = NULL_TREE;
6688   enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
6689 
6690   if (! flag_var_tracking_uninit)
6691     status = VAR_INIT_STATUS_INITIALIZED;
6692 
6693   if (src && REG_P (src))
6694     decl = var_debug_decl (REG_EXPR (src));
6695   else if (src && MEM_P (src))
6696     decl = var_debug_decl (MEM_EXPR (src));
6697 
6698   if (src && decl)
6699     status = get_init_value (in, src, dv_from_decl (decl));
6700 
6701   return status;
6702 }
6703 
6704 /* SRC is the source of an assignment.  Use SET to try to find what
6705    was ultimately assigned to SRC.  Return that value if known,
6706    otherwise return SRC itself.  */
6707 
6708 static rtx
find_src_set_src(dataflow_set * set,rtx src)6709 find_src_set_src (dataflow_set *set, rtx src)
6710 {
6711   tree decl = NULL_TREE;   /* The variable being copied around.          */
6712   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
6713   variable *var;
6714   location_chain *nextp;
6715   int i;
6716   bool found;
6717 
6718   if (src && REG_P (src))
6719     decl = var_debug_decl (REG_EXPR (src));
6720   else if (src && MEM_P (src))
6721     decl = var_debug_decl (MEM_EXPR (src));
6722 
6723   if (src && decl)
6724     {
6725       decl_or_value dv = dv_from_decl (decl);
6726 
6727       var = shared_hash_find (set->vars, dv);
6728       if (var)
6729 	{
6730 	  found = false;
6731 	  for (i = 0; i < var->n_var_parts && !found; i++)
6732 	    for (nextp = var->var_part[i].loc_chain; nextp && !found;
6733 		 nextp = nextp->next)
6734 	      if (rtx_equal_p (nextp->loc, src))
6735 		{
6736 		  set_src = nextp->set_src;
6737 		  found = true;
6738 		}
6739 
6740 	}
6741     }
6742 
6743   return set_src;
6744 }
6745 
6746 /* Compute the changes of variable locations in the basic block BB.  */
6747 
6748 static bool
compute_bb_dataflow(basic_block bb)6749 compute_bb_dataflow (basic_block bb)
6750 {
6751   unsigned int i;
6752   micro_operation *mo;
6753   bool changed;
6754   dataflow_set old_out;
6755   dataflow_set *in = &VTI (bb)->in;
6756   dataflow_set *out = &VTI (bb)->out;
6757 
6758   dataflow_set_init (&old_out);
6759   dataflow_set_copy (&old_out, out);
6760   dataflow_set_copy (out, in);
6761 
6762   if (MAY_HAVE_DEBUG_BIND_INSNS)
6763     local_get_addr_cache = new hash_map<rtx, rtx>;
6764 
6765   FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo)
6766     {
6767       rtx_insn *insn = mo->insn;
6768 
6769       switch (mo->type)
6770 	{
6771 	  case MO_CALL:
6772 	    dataflow_set_clear_at_call (out, insn);
6773 	    break;
6774 
6775 	  case MO_USE:
6776 	    {
6777 	      rtx loc = mo->u.loc;
6778 
6779 	      if (REG_P (loc))
6780 		var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
6781 	      else if (MEM_P (loc))
6782 		var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
6783 	    }
6784 	    break;
6785 
6786 	  case MO_VAL_LOC:
6787 	    {
6788 	      rtx loc = mo->u.loc;
6789 	      rtx val, vloc;
6790 	      tree var;
6791 
6792 	      if (GET_CODE (loc) == CONCAT)
6793 		{
6794 		  val = XEXP (loc, 0);
6795 		  vloc = XEXP (loc, 1);
6796 		}
6797 	      else
6798 		{
6799 		  val = NULL_RTX;
6800 		  vloc = loc;
6801 		}
6802 
6803 	      var = PAT_VAR_LOCATION_DECL (vloc);
6804 
6805 	      clobber_variable_part (out, NULL_RTX,
6806 				     dv_from_decl (var), 0, NULL_RTX);
6807 	      if (val)
6808 		{
6809 		  if (VAL_NEEDS_RESOLUTION (loc))
6810 		    val_resolve (out, val, PAT_VAR_LOCATION_LOC (vloc), insn);
6811 		  set_variable_part (out, val, dv_from_decl (var), 0,
6812 				     VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
6813 				     INSERT);
6814 		}
6815 	      else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
6816 		set_variable_part (out, PAT_VAR_LOCATION_LOC (vloc),
6817 				   dv_from_decl (var), 0,
6818 				   VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
6819 				   INSERT);
6820 	    }
6821 	    break;
6822 
6823 	  case MO_VAL_USE:
6824 	    {
6825 	      rtx loc = mo->u.loc;
6826 	      rtx val, vloc, uloc;
6827 
6828 	      vloc = uloc = XEXP (loc, 1);
6829 	      val = XEXP (loc, 0);
6830 
6831 	      if (GET_CODE (val) == CONCAT)
6832 		{
6833 		  uloc = XEXP (val, 1);
6834 		  val = XEXP (val, 0);
6835 		}
6836 
6837 	      if (VAL_NEEDS_RESOLUTION (loc))
6838 		val_resolve (out, val, vloc, insn);
6839 	      else
6840 		val_store (out, val, uloc, insn, false);
6841 
6842 	      if (VAL_HOLDS_TRACK_EXPR (loc))
6843 		{
6844 		  if (GET_CODE (uloc) == REG)
6845 		    var_reg_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
6846 				 NULL);
6847 		  else if (GET_CODE (uloc) == MEM)
6848 		    var_mem_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
6849 				 NULL);
6850 		}
6851 	    }
6852 	    break;
6853 
6854 	  case MO_VAL_SET:
6855 	    {
6856 	      rtx loc = mo->u.loc;
6857 	      rtx val, vloc, uloc;
6858 	      rtx dstv, srcv;
6859 
6860 	      vloc = loc;
6861 	      uloc = XEXP (vloc, 1);
6862 	      val = XEXP (vloc, 0);
6863 	      vloc = uloc;
6864 
6865 	      if (GET_CODE (uloc) == SET)
6866 		{
6867 		  dstv = SET_DEST (uloc);
6868 		  srcv = SET_SRC (uloc);
6869 		}
6870 	      else
6871 		{
6872 		  dstv = uloc;
6873 		  srcv = NULL;
6874 		}
6875 
6876 	      if (GET_CODE (val) == CONCAT)
6877 		{
6878 		  dstv = vloc = XEXP (val, 1);
6879 		  val = XEXP (val, 0);
6880 		}
6881 
6882 	      if (GET_CODE (vloc) == SET)
6883 		{
6884 		  srcv = SET_SRC (vloc);
6885 
6886 		  gcc_assert (val != srcv);
6887 		  gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
6888 
6889 		  dstv = vloc = SET_DEST (vloc);
6890 
6891 		  if (VAL_NEEDS_RESOLUTION (loc))
6892 		    val_resolve (out, val, srcv, insn);
6893 		}
6894 	      else if (VAL_NEEDS_RESOLUTION (loc))
6895 		{
6896 		  gcc_assert (GET_CODE (uloc) == SET
6897 			      && GET_CODE (SET_SRC (uloc)) == REG);
6898 		  val_resolve (out, val, SET_SRC (uloc), insn);
6899 		}
6900 
6901 	      if (VAL_HOLDS_TRACK_EXPR (loc))
6902 		{
6903 		  if (VAL_EXPR_IS_CLOBBERED (loc))
6904 		    {
6905 		      if (REG_P (uloc))
6906 			var_reg_delete (out, uloc, true);
6907 		      else if (MEM_P (uloc))
6908 			{
6909 			  gcc_assert (MEM_P (dstv));
6910 			  gcc_assert (MEM_ATTRS (dstv) == MEM_ATTRS (uloc));
6911 			  var_mem_delete (out, dstv, true);
6912 			}
6913 		    }
6914 		  else
6915 		    {
6916 		      bool copied_p = VAL_EXPR_IS_COPIED (loc);
6917 		      rtx src = NULL, dst = uloc;
6918 		      enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
6919 
6920 		      if (GET_CODE (uloc) == SET)
6921 			{
6922 			  src = SET_SRC (uloc);
6923 			  dst = SET_DEST (uloc);
6924 			}
6925 
6926 		      if (copied_p)
6927 			{
6928 			  if (flag_var_tracking_uninit)
6929 			    {
6930 			      status = find_src_status (in, src);
6931 
6932 			      if (status == VAR_INIT_STATUS_UNKNOWN)
6933 				status = find_src_status (out, src);
6934 			    }
6935 
6936 			  src = find_src_set_src (in, src);
6937 			}
6938 
6939 		      if (REG_P (dst))
6940 			var_reg_delete_and_set (out, dst, !copied_p,
6941 						status, srcv);
6942 		      else if (MEM_P (dst))
6943 			{
6944 			  gcc_assert (MEM_P (dstv));
6945 			  gcc_assert (MEM_ATTRS (dstv) == MEM_ATTRS (dst));
6946 			  var_mem_delete_and_set (out, dstv, !copied_p,
6947 						  status, srcv);
6948 			}
6949 		    }
6950 		}
6951 	      else if (REG_P (uloc))
6952 		var_regno_delete (out, REGNO (uloc));
6953 	      else if (MEM_P (uloc))
6954 		{
6955 		  gcc_checking_assert (GET_CODE (vloc) == MEM);
6956 		  gcc_checking_assert (dstv == vloc);
6957 		  if (dstv != vloc)
6958 		    clobber_overlapping_mems (out, vloc);
6959 		}
6960 
6961 	      val_store (out, val, dstv, insn, true);
6962 	    }
6963 	    break;
6964 
6965 	  case MO_SET:
6966 	    {
6967 	      rtx loc = mo->u.loc;
6968 	      rtx set_src = NULL;
6969 
6970 	      if (GET_CODE (loc) == SET)
6971 		{
6972 		  set_src = SET_SRC (loc);
6973 		  loc = SET_DEST (loc);
6974 		}
6975 
6976 	      if (REG_P (loc))
6977 		var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
6978 					set_src);
6979 	      else if (MEM_P (loc))
6980 		var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
6981 					set_src);
6982 	    }
6983 	    break;
6984 
6985 	  case MO_COPY:
6986 	    {
6987 	      rtx loc = mo->u.loc;
6988 	      enum var_init_status src_status;
6989 	      rtx set_src = NULL;
6990 
6991 	      if (GET_CODE (loc) == SET)
6992 		{
6993 		  set_src = SET_SRC (loc);
6994 		  loc = SET_DEST (loc);
6995 		}
6996 
6997 	      if (! flag_var_tracking_uninit)
6998 		src_status = VAR_INIT_STATUS_INITIALIZED;
6999 	      else
7000 		{
7001 		  src_status = find_src_status (in, set_src);
7002 
7003 		  if (src_status == VAR_INIT_STATUS_UNKNOWN)
7004 		    src_status = find_src_status (out, set_src);
7005 		}
7006 
7007 	      set_src = find_src_set_src (in, set_src);
7008 
7009 	      if (REG_P (loc))
7010 		var_reg_delete_and_set (out, loc, false, src_status, set_src);
7011 	      else if (MEM_P (loc))
7012 		var_mem_delete_and_set (out, loc, false, src_status, set_src);
7013 	    }
7014 	    break;
7015 
7016 	  case MO_USE_NO_VAR:
7017 	    {
7018 	      rtx loc = mo->u.loc;
7019 
7020 	      if (REG_P (loc))
7021 		var_reg_delete (out, loc, false);
7022 	      else if (MEM_P (loc))
7023 		var_mem_delete (out, loc, false);
7024 	    }
7025 	    break;
7026 
7027 	  case MO_CLOBBER:
7028 	    {
7029 	      rtx loc = mo->u.loc;
7030 
7031 	      if (REG_P (loc))
7032 		var_reg_delete (out, loc, true);
7033 	      else if (MEM_P (loc))
7034 		var_mem_delete (out, loc, true);
7035 	    }
7036 	    break;
7037 
7038 	  case MO_ADJUST:
7039 	    out->stack_adjust += mo->u.adjust;
7040 	    break;
7041 	}
7042     }
7043 
7044   if (MAY_HAVE_DEBUG_BIND_INSNS)
7045     {
7046       delete local_get_addr_cache;
7047       local_get_addr_cache = NULL;
7048 
7049       dataflow_set_equiv_regs (out);
7050       shared_hash_htab (out->vars)
7051 	->traverse <dataflow_set *, canonicalize_values_mark> (out);
7052       shared_hash_htab (out->vars)
7053 	->traverse <dataflow_set *, canonicalize_values_star> (out);
7054       if (flag_checking)
7055 	shared_hash_htab (out->vars)
7056 	  ->traverse <dataflow_set *, canonicalize_loc_order_check> (out);
7057     }
7058   changed = dataflow_set_different (&old_out, out);
7059   dataflow_set_destroy (&old_out);
7060   return changed;
7061 }
7062 
7063 /* Find the locations of variables in the whole function.  */
7064 
7065 static bool
vt_find_locations(void)7066 vt_find_locations (void)
7067 {
7068   bb_heap_t *worklist = new bb_heap_t (LONG_MIN);
7069   bb_heap_t *pending = new bb_heap_t (LONG_MIN);
7070   sbitmap in_worklist, in_pending;
7071   basic_block bb;
7072   edge e;
7073   int *bb_order;
7074   int *rc_order;
7075   int i;
7076   int htabsz = 0;
7077   int htabmax = param_max_vartrack_size;
7078   bool success = true;
7079   unsigned int n_blocks_processed = 0;
7080 
7081   timevar_push (TV_VAR_TRACKING_DATAFLOW);
7082   /* Compute reverse completion order of depth first search of the CFG
7083      so that the data-flow runs faster.  */
7084   rc_order = XNEWVEC (int, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
7085   bb_order = XNEWVEC (int, last_basic_block_for_fn (cfun));
7086   auto_bitmap exit_bbs;
7087   bitmap_set_bit (exit_bbs, EXIT_BLOCK);
7088   auto_vec<std::pair<int, int> > toplevel_scc_extents;
7089   int n = rev_post_order_and_mark_dfs_back_seme
7090     (cfun, single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), exit_bbs, true,
7091      rc_order, &toplevel_scc_extents);
7092   for (i = 0; i < n; i++)
7093     bb_order[rc_order[i]] = i;
7094 
7095   in_worklist = sbitmap_alloc (last_basic_block_for_fn (cfun));
7096   in_pending = sbitmap_alloc (last_basic_block_for_fn (cfun));
7097   bitmap_clear (in_worklist);
7098   bitmap_clear (in_pending);
7099 
7100   /* We're performing the dataflow iteration independently over the
7101      toplevel SCCs plus leading non-cyclic entry blocks and separately
7102      over the tail.  That ensures best memory locality and the least
7103      number of visited blocks.  */
7104   unsigned extent = 0;
7105   int curr_start = -1;
7106   int curr_end = -1;
7107   do
7108     {
7109       curr_start = curr_end + 1;
7110       if (toplevel_scc_extents.length () <= extent)
7111 	curr_end = n - 1;
7112       else
7113 	curr_end = toplevel_scc_extents[extent++].second;
7114 
7115       for (int i = curr_start; i <= curr_end; ++i)
7116 	{
7117 	  pending->insert (i, BASIC_BLOCK_FOR_FN (cfun, rc_order[i]));
7118 	  bitmap_set_bit (in_pending, rc_order[i]);
7119 	}
7120 
7121       while (success && !pending->empty ())
7122 	{
7123 	  std::swap (worklist, pending);
7124 	  std::swap (in_worklist, in_pending);
7125 
7126 	  while (!worklist->empty ())
7127 	    {
7128 	      bool changed;
7129 	      edge_iterator ei;
7130 	      int oldinsz, oldoutsz;
7131 
7132 	      bb = worklist->extract_min ();
7133 	      bitmap_clear_bit (in_worklist, bb->index);
7134 
7135 	      if (VTI (bb)->in.vars)
7136 		{
7137 		  htabsz -= (shared_hash_htab (VTI (bb)->in.vars)->size ()
7138 			     + shared_hash_htab (VTI (bb)->out.vars)->size ());
7139 		  oldinsz = shared_hash_htab (VTI (bb)->in.vars)->elements ();
7140 		  oldoutsz = shared_hash_htab (VTI (bb)->out.vars)->elements ();
7141 		}
7142 	      else
7143 		oldinsz = oldoutsz = 0;
7144 
7145 	      if (MAY_HAVE_DEBUG_BIND_INSNS)
7146 		{
7147 		  dataflow_set *in = &VTI (bb)->in, *first_out = NULL;
7148 		  bool first = true, adjust = false;
7149 
7150 		  /* Calculate the IN set as the intersection of
7151 		     predecessor OUT sets.  */
7152 
7153 		  dataflow_set_clear (in);
7154 		  dst_can_be_shared = true;
7155 
7156 		  FOR_EACH_EDGE (e, ei, bb->preds)
7157 		    if (!VTI (e->src)->flooded)
7158 		      gcc_assert (bb_order[bb->index]
7159 				  <= bb_order[e->src->index]);
7160 		    else if (first)
7161 		      {
7162 			dataflow_set_copy (in, &VTI (e->src)->out);
7163 			first_out = &VTI (e->src)->out;
7164 			first = false;
7165 		      }
7166 		    else
7167 		      {
7168 			dataflow_set_merge (in, &VTI (e->src)->out);
7169 			adjust = true;
7170 		      }
7171 
7172 		  if (adjust)
7173 		    {
7174 		      dataflow_post_merge_adjust (in, &VTI (bb)->permp);
7175 
7176 		      if (flag_checking)
7177 			/* Merge and merge_adjust should keep entries in
7178 			   canonical order.  */
7179 			shared_hash_htab (in->vars)
7180 			  ->traverse <dataflow_set *,
7181 				      canonicalize_loc_order_check> (in);
7182 
7183 		      if (dst_can_be_shared)
7184 			{
7185 			  shared_hash_destroy (in->vars);
7186 			  in->vars = shared_hash_copy (first_out->vars);
7187 			}
7188 		    }
7189 
7190 		  VTI (bb)->flooded = true;
7191 		}
7192 	      else
7193 		{
7194 		  /* Calculate the IN set as union of predecessor OUT sets.  */
7195 		  dataflow_set_clear (&VTI (bb)->in);
7196 		  FOR_EACH_EDGE (e, ei, bb->preds)
7197 		    dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
7198 		}
7199 
7200 	      changed = compute_bb_dataflow (bb);
7201 	      n_blocks_processed++;
7202 	      htabsz += (shared_hash_htab (VTI (bb)->in.vars)->size ()
7203 			 + shared_hash_htab (VTI (bb)->out.vars)->size ());
7204 
7205 	      if (htabmax && htabsz > htabmax)
7206 		{
7207 		  if (MAY_HAVE_DEBUG_BIND_INSNS)
7208 		    inform (DECL_SOURCE_LOCATION (cfun->decl),
7209 			    "variable tracking size limit exceeded with "
7210 			    "%<-fvar-tracking-assignments%>, retrying without");
7211 		  else
7212 		    inform (DECL_SOURCE_LOCATION (cfun->decl),
7213 			    "variable tracking size limit exceeded");
7214 		  success = false;
7215 		  break;
7216 		}
7217 
7218 	      if (changed)
7219 		{
7220 		  FOR_EACH_EDGE (e, ei, bb->succs)
7221 		    {
7222 		      if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
7223 			continue;
7224 
7225 		      /* Iterate to an earlier block in RPO in the next
7226 			 round, iterate to the same block immediately.  */
7227 		      if (bb_order[e->dest->index] < bb_order[bb->index])
7228 			{
7229 			  gcc_assert (bb_order[e->dest->index] >= curr_start);
7230 			  if (!bitmap_bit_p (in_pending, e->dest->index))
7231 			    {
7232 			      /* Send E->DEST to next round.  */
7233 			      bitmap_set_bit (in_pending, e->dest->index);
7234 			      pending->insert (bb_order[e->dest->index],
7235 					       e->dest);
7236 			    }
7237 			}
7238 		      else if (bb_order[e->dest->index] <= curr_end
7239 			       && !bitmap_bit_p (in_worklist, e->dest->index))
7240 			{
7241 			  /* Add E->DEST to current round or delay
7242 			     processing if it is in the next SCC.  */
7243 			  bitmap_set_bit (in_worklist, e->dest->index);
7244 			  worklist->insert (bb_order[e->dest->index],
7245 					    e->dest);
7246 			}
7247 		    }
7248 		}
7249 
7250 	      if (dump_file)
7251 		fprintf (dump_file,
7252 			 "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, "
7253 			 "tsz %i\n", bb->index,
7254 			 (int)shared_hash_htab (VTI (bb)->in.vars)->size (),
7255 			 oldinsz,
7256 			 (int)shared_hash_htab (VTI (bb)->out.vars)->size (),
7257 			 oldoutsz,
7258 			 (int)worklist->nodes (), (int)pending->nodes (),
7259 			 htabsz);
7260 
7261 	      if (dump_file && (dump_flags & TDF_DETAILS))
7262 		{
7263 		  fprintf (dump_file, "BB %i IN:\n", bb->index);
7264 		  dump_dataflow_set (&VTI (bb)->in);
7265 		  fprintf (dump_file, "BB %i OUT:\n", bb->index);
7266 		  dump_dataflow_set (&VTI (bb)->out);
7267 		}
7268 	    }
7269 	}
7270     }
7271   while (curr_end != n - 1);
7272 
7273   statistics_counter_event (cfun, "compute_bb_dataflow times",
7274 			    n_blocks_processed);
7275 
7276   if (success && MAY_HAVE_DEBUG_BIND_INSNS)
7277     FOR_EACH_BB_FN (bb, cfun)
7278       gcc_assert (VTI (bb)->flooded);
7279 
7280   free (rc_order);
7281   free (bb_order);
7282   delete worklist;
7283   delete pending;
7284   sbitmap_free (in_worklist);
7285   sbitmap_free (in_pending);
7286 
7287   timevar_pop (TV_VAR_TRACKING_DATAFLOW);
7288   return success;
7289 }
7290 
7291 /* Print the content of the LIST to dump file.  */
7292 
7293 static void
dump_attrs_list(attrs * list)7294 dump_attrs_list (attrs *list)
7295 {
7296   for (; list; list = list->next)
7297     {
7298       if (dv_is_decl_p (list->dv))
7299 	print_mem_expr (dump_file, dv_as_decl (list->dv));
7300       else
7301 	print_rtl_single (dump_file, dv_as_value (list->dv));
7302       fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
7303     }
7304   fprintf (dump_file, "\n");
7305 }
7306 
7307 /* Print the information about variable *SLOT to dump file.  */
7308 
7309 int
dump_var_tracking_slot(variable ** slot,void * data ATTRIBUTE_UNUSED)7310 dump_var_tracking_slot (variable **slot, void *data ATTRIBUTE_UNUSED)
7311 {
7312   variable *var = *slot;
7313 
7314   dump_var (var);
7315 
7316   /* Continue traversing the hash table.  */
7317   return 1;
7318 }
7319 
7320 /* Print the information about variable VAR to dump file.  */
7321 
7322 static void
dump_var(variable * var)7323 dump_var (variable *var)
7324 {
7325   int i;
7326   location_chain *node;
7327 
7328   if (dv_is_decl_p (var->dv))
7329     {
7330       const_tree decl = dv_as_decl (var->dv);
7331 
7332       if (DECL_NAME (decl))
7333 	{
7334 	  fprintf (dump_file, "  name: %s",
7335 		   IDENTIFIER_POINTER (DECL_NAME (decl)));
7336 	  if (dump_flags & TDF_UID)
7337 	    fprintf (dump_file, "D.%u", DECL_UID (decl));
7338 	}
7339       else if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
7340 	fprintf (dump_file, "  name: D#%u", DEBUG_TEMP_UID (decl));
7341       else
7342 	fprintf (dump_file, "  name: D.%u", DECL_UID (decl));
7343       fprintf (dump_file, "\n");
7344     }
7345   else
7346     {
7347       fputc (' ', dump_file);
7348       print_rtl_single (dump_file, dv_as_value (var->dv));
7349     }
7350 
7351   for (i = 0; i < var->n_var_parts; i++)
7352     {
7353       fprintf (dump_file, "    offset %ld\n",
7354 	       (long)(var->onepart ? 0 : VAR_PART_OFFSET (var, i)));
7355       for (node = var->var_part[i].loc_chain; node; node = node->next)
7356 	{
7357 	  fprintf (dump_file, "      ");
7358 	  if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
7359 	    fprintf (dump_file, "[uninit]");
7360 	  print_rtl_single (dump_file, node->loc);
7361 	}
7362     }
7363 }
7364 
7365 /* Print the information about variables from hash table VARS to dump file.  */
7366 
7367 static void
dump_vars(variable_table_type * vars)7368 dump_vars (variable_table_type *vars)
7369 {
7370   if (!vars->is_empty ())
7371     {
7372       fprintf (dump_file, "Variables:\n");
7373       vars->traverse <void *, dump_var_tracking_slot> (NULL);
7374     }
7375 }
7376 
7377 /* Print the dataflow set SET to dump file.  */
7378 
7379 static void
dump_dataflow_set(dataflow_set * set)7380 dump_dataflow_set (dataflow_set *set)
7381 {
7382   int i;
7383 
7384   fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
7385 	   set->stack_adjust);
7386   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
7387     {
7388       if (set->regs[i])
7389 	{
7390 	  fprintf (dump_file, "Reg %d:", i);
7391 	  dump_attrs_list (set->regs[i]);
7392 	}
7393     }
7394   dump_vars (shared_hash_htab (set->vars));
7395   fprintf (dump_file, "\n");
7396 }
7397 
7398 /* Print the IN and OUT sets for each basic block to dump file.  */
7399 
7400 static void
dump_dataflow_sets(void)7401 dump_dataflow_sets (void)
7402 {
7403   basic_block bb;
7404 
7405   FOR_EACH_BB_FN (bb, cfun)
7406     {
7407       fprintf (dump_file, "\nBasic block %d:\n", bb->index);
7408       fprintf (dump_file, "IN:\n");
7409       dump_dataflow_set (&VTI (bb)->in);
7410       fprintf (dump_file, "OUT:\n");
7411       dump_dataflow_set (&VTI (bb)->out);
7412     }
7413 }
7414 
7415 /* Return the variable for DV in dropped_values, inserting one if
7416    requested with INSERT.  */
7417 
7418 static inline variable *
variable_from_dropped(decl_or_value dv,enum insert_option insert)7419 variable_from_dropped (decl_or_value dv, enum insert_option insert)
7420 {
7421   variable **slot;
7422   variable *empty_var;
7423   onepart_enum onepart;
7424 
7425   slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv), insert);
7426 
7427   if (!slot)
7428     return NULL;
7429 
7430   if (*slot)
7431     return *slot;
7432 
7433   gcc_checking_assert (insert == INSERT);
7434 
7435   onepart = dv_onepart_p (dv);
7436 
7437   gcc_checking_assert (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR);
7438 
7439   empty_var = onepart_pool_allocate (onepart);
7440   empty_var->dv = dv;
7441   empty_var->refcount = 1;
7442   empty_var->n_var_parts = 0;
7443   empty_var->onepart = onepart;
7444   empty_var->in_changed_variables = false;
7445   empty_var->var_part[0].loc_chain = NULL;
7446   empty_var->var_part[0].cur_loc = NULL;
7447   VAR_LOC_1PAUX (empty_var) = NULL;
7448   set_dv_changed (dv, true);
7449 
7450   *slot = empty_var;
7451 
7452   return empty_var;
7453 }
7454 
7455 /* Recover the one-part aux from dropped_values.  */
7456 
7457 static struct onepart_aux *
recover_dropped_1paux(variable * var)7458 recover_dropped_1paux (variable *var)
7459 {
7460   variable *dvar;
7461 
7462   gcc_checking_assert (var->onepart);
7463 
7464   if (VAR_LOC_1PAUX (var))
7465     return VAR_LOC_1PAUX (var);
7466 
7467   if (var->onepart == ONEPART_VDECL)
7468     return NULL;
7469 
7470   dvar = variable_from_dropped (var->dv, NO_INSERT);
7471 
7472   if (!dvar)
7473     return NULL;
7474 
7475   VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (dvar);
7476   VAR_LOC_1PAUX (dvar) = NULL;
7477 
7478   return VAR_LOC_1PAUX (var);
7479 }
7480 
7481 /* Add variable VAR to the hash table of changed variables and
7482    if it has no locations delete it from SET's hash table.  */
7483 
7484 static void
variable_was_changed(variable * var,dataflow_set * set)7485 variable_was_changed (variable *var, dataflow_set *set)
7486 {
7487   hashval_t hash = dv_htab_hash (var->dv);
7488 
7489   if (emit_notes)
7490     {
7491       variable **slot;
7492 
7493       /* Remember this decl or VALUE has been added to changed_variables.  */
7494       set_dv_changed (var->dv, true);
7495 
7496       slot = changed_variables->find_slot_with_hash (var->dv, hash, INSERT);
7497 
7498       if (*slot)
7499 	{
7500 	  variable *old_var = *slot;
7501 	  gcc_assert (old_var->in_changed_variables);
7502 	  old_var->in_changed_variables = false;
7503 	  if (var != old_var && var->onepart)
7504 	    {
7505 	      /* Restore the auxiliary info from an empty variable
7506 		 previously created for changed_variables, so it is
7507 		 not lost.  */
7508 	      gcc_checking_assert (!VAR_LOC_1PAUX (var));
7509 	      VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (old_var);
7510 	      VAR_LOC_1PAUX (old_var) = NULL;
7511 	    }
7512 	  variable_htab_free (*slot);
7513 	}
7514 
7515       if (set && var->n_var_parts == 0)
7516 	{
7517 	  onepart_enum onepart = var->onepart;
7518 	  variable *empty_var = NULL;
7519 	  variable **dslot = NULL;
7520 
7521 	  if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
7522 	    {
7523 	      dslot = dropped_values->find_slot_with_hash (var->dv,
7524 							   dv_htab_hash (var->dv),
7525 							   INSERT);
7526 	      empty_var = *dslot;
7527 
7528 	      if (empty_var)
7529 		{
7530 		  gcc_checking_assert (!empty_var->in_changed_variables);
7531 		  if (!VAR_LOC_1PAUX (var))
7532 		    {
7533 		      VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (empty_var);
7534 		      VAR_LOC_1PAUX (empty_var) = NULL;
7535 		    }
7536 		  else
7537 		    gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
7538 		}
7539 	    }
7540 
7541 	  if (!empty_var)
7542 	    {
7543 	      empty_var = onepart_pool_allocate (onepart);
7544 	      empty_var->dv = var->dv;
7545 	      empty_var->refcount = 1;
7546 	      empty_var->n_var_parts = 0;
7547 	      empty_var->onepart = onepart;
7548 	      if (dslot)
7549 		{
7550 		  empty_var->refcount++;
7551 		  *dslot = empty_var;
7552 		}
7553 	    }
7554 	  else
7555 	    empty_var->refcount++;
7556 	  empty_var->in_changed_variables = true;
7557 	  *slot = empty_var;
7558 	  if (onepart)
7559 	    {
7560 	      empty_var->var_part[0].loc_chain = NULL;
7561 	      empty_var->var_part[0].cur_loc = NULL;
7562 	      VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (var);
7563 	      VAR_LOC_1PAUX (var) = NULL;
7564 	    }
7565 	  goto drop_var;
7566 	}
7567       else
7568 	{
7569 	  if (var->onepart && !VAR_LOC_1PAUX (var))
7570 	    recover_dropped_1paux (var);
7571 	  var->refcount++;
7572 	  var->in_changed_variables = true;
7573 	  *slot = var;
7574 	}
7575     }
7576   else
7577     {
7578       gcc_assert (set);
7579       if (var->n_var_parts == 0)
7580 	{
7581 	  variable **slot;
7582 
7583 	drop_var:
7584 	  slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
7585 	  if (slot)
7586 	    {
7587 	      if (shared_hash_shared (set->vars))
7588 		slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
7589 						      NO_INSERT);
7590 	      shared_hash_htab (set->vars)->clear_slot (slot);
7591 	    }
7592 	}
7593     }
7594 }
7595 
7596 /* Look for the index in VAR->var_part corresponding to OFFSET.
7597    Return -1 if not found.  If INSERTION_POINT is non-NULL, the
7598    referenced int will be set to the index that the part has or should
7599    have, if it should be inserted.  */
7600 
7601 static inline int
find_variable_location_part(variable * var,HOST_WIDE_INT offset,int * insertion_point)7602 find_variable_location_part (variable *var, HOST_WIDE_INT offset,
7603 			     int *insertion_point)
7604 {
7605   int pos, low, high;
7606 
7607   if (var->onepart)
7608     {
7609       if (offset != 0)
7610 	return -1;
7611 
7612       if (insertion_point)
7613 	*insertion_point = 0;
7614 
7615       return var->n_var_parts - 1;
7616     }
7617 
7618   /* Find the location part.  */
7619   low = 0;
7620   high = var->n_var_parts;
7621   while (low != high)
7622     {
7623       pos = (low + high) / 2;
7624       if (VAR_PART_OFFSET (var, pos) < offset)
7625 	low = pos + 1;
7626       else
7627 	high = pos;
7628     }
7629   pos = low;
7630 
7631   if (insertion_point)
7632     *insertion_point = pos;
7633 
7634   if (pos < var->n_var_parts && VAR_PART_OFFSET (var, pos) == offset)
7635     return pos;
7636 
7637   return -1;
7638 }
7639 
7640 static variable **
set_slot_part(dataflow_set * set,rtx loc,variable ** slot,decl_or_value dv,HOST_WIDE_INT offset,enum var_init_status initialized,rtx set_src)7641 set_slot_part (dataflow_set *set, rtx loc, variable **slot,
7642 	       decl_or_value dv, HOST_WIDE_INT offset,
7643 	       enum var_init_status initialized, rtx set_src)
7644 {
7645   int pos;
7646   location_chain *node, *next;
7647   location_chain **nextp;
7648   variable *var;
7649   onepart_enum onepart;
7650 
7651   var = *slot;
7652 
7653   if (var)
7654     onepart = var->onepart;
7655   else
7656     onepart = dv_onepart_p (dv);
7657 
7658   gcc_checking_assert (offset == 0 || !onepart);
7659   gcc_checking_assert (loc != dv_as_opaque (dv));
7660 
7661   if (! flag_var_tracking_uninit)
7662     initialized = VAR_INIT_STATUS_INITIALIZED;
7663 
7664   if (!var)
7665     {
7666       /* Create new variable information.  */
7667       var = onepart_pool_allocate (onepart);
7668       var->dv = dv;
7669       var->refcount = 1;
7670       var->n_var_parts = 1;
7671       var->onepart = onepart;
7672       var->in_changed_variables = false;
7673       if (var->onepart)
7674 	VAR_LOC_1PAUX (var) = NULL;
7675       else
7676 	VAR_PART_OFFSET (var, 0) = offset;
7677       var->var_part[0].loc_chain = NULL;
7678       var->var_part[0].cur_loc = NULL;
7679       *slot = var;
7680       pos = 0;
7681       nextp = &var->var_part[0].loc_chain;
7682     }
7683   else if (onepart)
7684     {
7685       int r = -1, c = 0;
7686 
7687       gcc_assert (dv_as_opaque (var->dv) == dv_as_opaque (dv));
7688 
7689       pos = 0;
7690 
7691       if (GET_CODE (loc) == VALUE)
7692 	{
7693 	  for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
7694 	       nextp = &node->next)
7695 	    if (GET_CODE (node->loc) == VALUE)
7696 	      {
7697 		if (node->loc == loc)
7698 		  {
7699 		    r = 0;
7700 		    break;
7701 		  }
7702 		if (canon_value_cmp (node->loc, loc))
7703 		  c++;
7704 		else
7705 		  {
7706 		    r = 1;
7707 		    break;
7708 		  }
7709 	      }
7710 	    else if (REG_P (node->loc) || MEM_P (node->loc))
7711 	      c++;
7712 	    else
7713 	      {
7714 		r = 1;
7715 		break;
7716 	      }
7717 	}
7718       else if (REG_P (loc))
7719 	{
7720 	  for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
7721 	       nextp = &node->next)
7722 	    if (REG_P (node->loc))
7723 	      {
7724 		if (REGNO (node->loc) < REGNO (loc))
7725 		  c++;
7726 		else
7727 		  {
7728 		    if (REGNO (node->loc) == REGNO (loc))
7729 		      r = 0;
7730 		    else
7731 		      r = 1;
7732 		    break;
7733 		  }
7734 	      }
7735 	    else
7736 	      {
7737 		r = 1;
7738 		break;
7739 	      }
7740 	}
7741       else if (MEM_P (loc))
7742 	{
7743 	  for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
7744 	       nextp = &node->next)
7745 	    if (REG_P (node->loc))
7746 	      c++;
7747 	    else if (MEM_P (node->loc))
7748 	      {
7749 		if ((r = loc_cmp (XEXP (node->loc, 0), XEXP (loc, 0))) >= 0)
7750 		  break;
7751 		else
7752 		  c++;
7753 	      }
7754 	    else
7755 	      {
7756 		r = 1;
7757 		break;
7758 	      }
7759 	}
7760       else
7761 	for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
7762 	     nextp = &node->next)
7763 	  if ((r = loc_cmp (node->loc, loc)) >= 0)
7764 	    break;
7765 	  else
7766 	    c++;
7767 
7768       if (r == 0)
7769 	return slot;
7770 
7771       if (shared_var_p (var, set->vars))
7772 	{
7773 	  slot = unshare_variable (set, slot, var, initialized);
7774 	  var = *slot;
7775 	  for (nextp = &var->var_part[0].loc_chain; c;
7776 	       nextp = &(*nextp)->next)
7777 	    c--;
7778 	  gcc_assert ((!node && !*nextp) || node->loc == (*nextp)->loc);
7779 	}
7780     }
7781   else
7782     {
7783       int inspos = 0;
7784 
7785       gcc_assert (dv_as_decl (var->dv) == dv_as_decl (dv));
7786 
7787       pos = find_variable_location_part (var, offset, &inspos);
7788 
7789       if (pos >= 0)
7790 	{
7791 	  node = var->var_part[pos].loc_chain;
7792 
7793 	  if (node
7794 	      && ((REG_P (node->loc) && REG_P (loc)
7795 		   && REGNO (node->loc) == REGNO (loc))
7796 		  || rtx_equal_p (node->loc, loc)))
7797 	    {
7798 	      /* LOC is in the beginning of the chain so we have nothing
7799 		 to do.  */
7800 	      if (node->init < initialized)
7801 		node->init = initialized;
7802 	      if (set_src != NULL)
7803 		node->set_src = set_src;
7804 
7805 	      return slot;
7806 	    }
7807 	  else
7808 	    {
7809 	      /* We have to make a copy of a shared variable.  */
7810 	      if (shared_var_p (var, set->vars))
7811 		{
7812 		  slot = unshare_variable (set, slot, var, initialized);
7813 		  var = *slot;
7814 		}
7815 	    }
7816 	}
7817       else
7818 	{
7819 	  /* We have not found the location part, new one will be created.  */
7820 
7821 	  /* We have to make a copy of the shared variable.  */
7822 	  if (shared_var_p (var, set->vars))
7823 	    {
7824 	      slot = unshare_variable (set, slot, var, initialized);
7825 	      var = *slot;
7826 	    }
7827 
7828 	  /* We track only variables whose size is <= MAX_VAR_PARTS bytes
7829 	     thus there are at most MAX_VAR_PARTS different offsets.  */
7830 	  gcc_assert (var->n_var_parts < MAX_VAR_PARTS
7831 		      && (!var->n_var_parts || !onepart));
7832 
7833 	  /* We have to move the elements of array starting at index
7834 	     inspos to the next position.  */
7835 	  for (pos = var->n_var_parts; pos > inspos; pos--)
7836 	    var->var_part[pos] = var->var_part[pos - 1];
7837 
7838 	  var->n_var_parts++;
7839 	  gcc_checking_assert (!onepart);
7840 	  VAR_PART_OFFSET (var, pos) = offset;
7841 	  var->var_part[pos].loc_chain = NULL;
7842 	  var->var_part[pos].cur_loc = NULL;
7843 	}
7844 
7845       /* Delete the location from the list.  */
7846       nextp = &var->var_part[pos].loc_chain;
7847       for (node = var->var_part[pos].loc_chain; node; node = next)
7848 	{
7849 	  next = node->next;
7850 	  if ((REG_P (node->loc) && REG_P (loc)
7851 	       && REGNO (node->loc) == REGNO (loc))
7852 	      || rtx_equal_p (node->loc, loc))
7853 	    {
7854 	      /* Save these values, to assign to the new node, before
7855 		 deleting this one.  */
7856 	      if (node->init > initialized)
7857 		initialized = node->init;
7858 	      if (node->set_src != NULL && set_src == NULL)
7859 		set_src = node->set_src;
7860 	      if (var->var_part[pos].cur_loc == node->loc)
7861 		var->var_part[pos].cur_loc = NULL;
7862 	      delete node;
7863 	      *nextp = next;
7864 	      break;
7865 	    }
7866 	  else
7867 	    nextp = &node->next;
7868 	}
7869 
7870       nextp = &var->var_part[pos].loc_chain;
7871     }
7872 
7873   /* Add the location to the beginning.  */
7874   node = new location_chain;
7875   node->loc = loc;
7876   node->init = initialized;
7877   node->set_src = set_src;
7878   node->next = *nextp;
7879   *nextp = node;
7880 
7881   /* If no location was emitted do so.  */
7882   if (var->var_part[pos].cur_loc == NULL)
7883     variable_was_changed (var, set);
7884 
7885   return slot;
7886 }
7887 
7888 /* Set the part of variable's location in the dataflow set SET.  The
7889    variable part is specified by variable's declaration in DV and
7890    offset OFFSET and the part's location by LOC.  IOPT should be
7891    NO_INSERT if the variable is known to be in SET already and the
7892    variable hash table must not be resized, and INSERT otherwise.  */
7893 
7894 static void
set_variable_part(dataflow_set * set,rtx loc,decl_or_value dv,HOST_WIDE_INT offset,enum var_init_status initialized,rtx set_src,enum insert_option iopt)7895 set_variable_part (dataflow_set *set, rtx loc,
7896 		   decl_or_value dv, HOST_WIDE_INT offset,
7897 		   enum var_init_status initialized, rtx set_src,
7898 		   enum insert_option iopt)
7899 {
7900   variable **slot;
7901 
7902   if (iopt == NO_INSERT)
7903     slot = shared_hash_find_slot_noinsert (set->vars, dv);
7904   else
7905     {
7906       slot = shared_hash_find_slot (set->vars, dv);
7907       if (!slot)
7908 	slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt);
7909     }
7910   set_slot_part (set, loc, slot, dv, offset, initialized, set_src);
7911 }
7912 
7913 /* Remove all recorded register locations for the given variable part
7914    from dataflow set SET, except for those that are identical to loc.
7915    The variable part is specified by variable's declaration or value
7916    DV and offset OFFSET.  */
7917 
7918 static variable **
clobber_slot_part(dataflow_set * set,rtx loc,variable ** slot,HOST_WIDE_INT offset,rtx set_src)7919 clobber_slot_part (dataflow_set *set, rtx loc, variable **slot,
7920 		   HOST_WIDE_INT offset, rtx set_src)
7921 {
7922   variable *var = *slot;
7923   int pos = find_variable_location_part (var, offset, NULL);
7924 
7925   if (pos >= 0)
7926     {
7927       location_chain *node, *next;
7928 
7929       /* Remove the register locations from the dataflow set.  */
7930       next = var->var_part[pos].loc_chain;
7931       for (node = next; node; node = next)
7932 	{
7933 	  next = node->next;
7934 	  if (node->loc != loc
7935 	      && (!flag_var_tracking_uninit
7936 		  || !set_src
7937 		  || MEM_P (set_src)
7938 		  || !rtx_equal_p (set_src, node->set_src)))
7939 	    {
7940 	      if (REG_P (node->loc))
7941 		{
7942 		  attrs *anode, *anext;
7943 		  attrs **anextp;
7944 
7945 		  /* Remove the variable part from the register's
7946 		     list, but preserve any other variable parts
7947 		     that might be regarded as live in that same
7948 		     register.  */
7949 		  anextp = &set->regs[REGNO (node->loc)];
7950 		  for (anode = *anextp; anode; anode = anext)
7951 		    {
7952 		      anext = anode->next;
7953 		      if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
7954 			  && anode->offset == offset)
7955 			{
7956 			  delete anode;
7957 			  *anextp = anext;
7958 			}
7959 		      else
7960 			anextp = &anode->next;
7961 		    }
7962 		}
7963 
7964 	      slot = delete_slot_part (set, node->loc, slot, offset);
7965 	    }
7966 	}
7967     }
7968 
7969   return slot;
7970 }
7971 
7972 /* Remove all recorded register locations for the given variable part
7973    from dataflow set SET, except for those that are identical to loc.
7974    The variable part is specified by variable's declaration or value
7975    DV and offset OFFSET.  */
7976 
7977 static void
clobber_variable_part(dataflow_set * set,rtx loc,decl_or_value dv,HOST_WIDE_INT offset,rtx set_src)7978 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
7979 		       HOST_WIDE_INT offset, rtx set_src)
7980 {
7981   variable **slot;
7982 
7983   if (!dv_as_opaque (dv)
7984       || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
7985     return;
7986 
7987   slot = shared_hash_find_slot_noinsert (set->vars, dv);
7988   if (!slot)
7989     return;
7990 
7991   clobber_slot_part (set, loc, slot, offset, set_src);
7992 }
7993 
7994 /* Delete the part of variable's location from dataflow set SET.  The
7995    variable part is specified by its SET->vars slot SLOT and offset
7996    OFFSET and the part's location by LOC.  */
7997 
7998 static variable **
delete_slot_part(dataflow_set * set,rtx loc,variable ** slot,HOST_WIDE_INT offset)7999 delete_slot_part (dataflow_set *set, rtx loc, variable **slot,
8000 		  HOST_WIDE_INT offset)
8001 {
8002   variable *var = *slot;
8003   int pos = find_variable_location_part (var, offset, NULL);
8004 
8005   if (pos >= 0)
8006     {
8007       location_chain *node, *next;
8008       location_chain **nextp;
8009       bool changed;
8010       rtx cur_loc;
8011 
8012       if (shared_var_p (var, set->vars))
8013 	{
8014 	  /* If the variable contains the location part we have to
8015 	     make a copy of the variable.  */
8016 	  for (node = var->var_part[pos].loc_chain; node;
8017 	       node = node->next)
8018 	    {
8019 	      if ((REG_P (node->loc) && REG_P (loc)
8020 		   && REGNO (node->loc) == REGNO (loc))
8021 		  || rtx_equal_p (node->loc, loc))
8022 		{
8023 		  slot = unshare_variable (set, slot, var,
8024 					   VAR_INIT_STATUS_UNKNOWN);
8025 		  var = *slot;
8026 		  break;
8027 		}
8028 	    }
8029 	}
8030 
8031       if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
8032 	cur_loc = VAR_LOC_FROM (var);
8033       else
8034 	cur_loc = var->var_part[pos].cur_loc;
8035 
8036       /* Delete the location part.  */
8037       changed = false;
8038       nextp = &var->var_part[pos].loc_chain;
8039       for (node = *nextp; node; node = next)
8040 	{
8041 	  next = node->next;
8042 	  if ((REG_P (node->loc) && REG_P (loc)
8043 	       && REGNO (node->loc) == REGNO (loc))
8044 	      || rtx_equal_p (node->loc, loc))
8045 	    {
8046 	      /* If we have deleted the location which was last emitted
8047 		 we have to emit new location so add the variable to set
8048 		 of changed variables.  */
8049 	      if (cur_loc == node->loc)
8050 		{
8051 		  changed = true;
8052 		  var->var_part[pos].cur_loc = NULL;
8053 		  if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
8054 		    VAR_LOC_FROM (var) = NULL;
8055 		}
8056 	      delete node;
8057 	      *nextp = next;
8058 	      break;
8059 	    }
8060 	  else
8061 	    nextp = &node->next;
8062 	}
8063 
8064       if (var->var_part[pos].loc_chain == NULL)
8065 	{
8066 	  changed = true;
8067 	  var->n_var_parts--;
8068 	  while (pos < var->n_var_parts)
8069 	    {
8070 	      var->var_part[pos] = var->var_part[pos + 1];
8071 	      pos++;
8072 	    }
8073 	}
8074       if (changed)
8075 	variable_was_changed (var, set);
8076     }
8077 
8078   return slot;
8079 }
8080 
8081 /* Delete the part of variable's location from dataflow set SET.  The
8082    variable part is specified by variable's declaration or value DV
8083    and offset OFFSET and the part's location by LOC.  */
8084 
8085 static void
delete_variable_part(dataflow_set * set,rtx loc,decl_or_value dv,HOST_WIDE_INT offset)8086 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
8087 		      HOST_WIDE_INT offset)
8088 {
8089   variable **slot = shared_hash_find_slot_noinsert (set->vars, dv);
8090   if (!slot)
8091     return;
8092 
8093   delete_slot_part (set, loc, slot, offset);
8094 }
8095 
8096 
8097 /* Structure for passing some other parameters to function
8098    vt_expand_loc_callback.  */
8099 class expand_loc_callback_data
8100 {
8101 public:
8102   /* The variables and values active at this point.  */
8103   variable_table_type *vars;
8104 
8105   /* Stack of values and debug_exprs under expansion, and their
8106      children.  */
8107   auto_vec<rtx, 4> expanding;
8108 
8109   /* Stack of values and debug_exprs whose expansion hit recursion
8110      cycles.  They will have VALUE_RECURSED_INTO marked when added to
8111      this list.  This flag will be cleared if any of its dependencies
8112      resolves to a valid location.  So, if the flag remains set at the
8113      end of the search, we know no valid location for this one can
8114      possibly exist.  */
8115   auto_vec<rtx, 4> pending;
8116 
8117   /* The maximum depth among the sub-expressions under expansion.
8118      Zero indicates no expansion so far.  */
8119   expand_depth depth;
8120 };
8121 
8122 /* Allocate the one-part auxiliary data structure for VAR, with enough
8123    room for COUNT dependencies.  */
8124 
8125 static void
loc_exp_dep_alloc(variable * var,int count)8126 loc_exp_dep_alloc (variable *var, int count)
8127 {
8128   size_t allocsize;
8129 
8130   gcc_checking_assert (var->onepart);
8131 
8132   /* We can be called with COUNT == 0 to allocate the data structure
8133      without any dependencies, e.g. for the backlinks only.  However,
8134      if we are specifying a COUNT, then the dependency list must have
8135      been emptied before.  It would be possible to adjust pointers or
8136      force it empty here, but this is better done at an earlier point
8137      in the algorithm, so we instead leave an assertion to catch
8138      errors.  */
8139   gcc_checking_assert (!count
8140 		       || VAR_LOC_DEP_VEC (var) == NULL
8141 		       || VAR_LOC_DEP_VEC (var)->is_empty ());
8142 
8143   if (VAR_LOC_1PAUX (var) && VAR_LOC_DEP_VEC (var)->space (count))
8144     return;
8145 
8146   allocsize = offsetof (struct onepart_aux, deps)
8147 	      + deps_vec::embedded_size (count);
8148 
8149   if (VAR_LOC_1PAUX (var))
8150     {
8151       VAR_LOC_1PAUX (var) = XRESIZEVAR (struct onepart_aux,
8152 					VAR_LOC_1PAUX (var), allocsize);
8153       /* If the reallocation moves the onepaux structure, the
8154 	 back-pointer to BACKLINKS in the first list member will still
8155 	 point to its old location.  Adjust it.  */
8156       if (VAR_LOC_DEP_LST (var))
8157 	VAR_LOC_DEP_LST (var)->pprev = VAR_LOC_DEP_LSTP (var);
8158     }
8159   else
8160     {
8161       VAR_LOC_1PAUX (var) = XNEWVAR (struct onepart_aux, allocsize);
8162       *VAR_LOC_DEP_LSTP (var) = NULL;
8163       VAR_LOC_FROM (var) = NULL;
8164       VAR_LOC_DEPTH (var).complexity = 0;
8165       VAR_LOC_DEPTH (var).entryvals = 0;
8166     }
8167   VAR_LOC_DEP_VEC (var)->embedded_init (count);
8168 }
8169 
8170 /* Remove all entries from the vector of active dependencies of VAR,
8171    removing them from the back-links lists too.  */
8172 
8173 static void
loc_exp_dep_clear(variable * var)8174 loc_exp_dep_clear (variable *var)
8175 {
8176   while (VAR_LOC_DEP_VEC (var) && !VAR_LOC_DEP_VEC (var)->is_empty ())
8177     {
8178       loc_exp_dep *led = &VAR_LOC_DEP_VEC (var)->last ();
8179       if (led->next)
8180 	led->next->pprev = led->pprev;
8181       if (led->pprev)
8182 	*led->pprev = led->next;
8183       VAR_LOC_DEP_VEC (var)->pop ();
8184     }
8185 }
8186 
8187 /* Insert an active dependency from VAR on X to the vector of
8188    dependencies, and add the corresponding back-link to X's list of
8189    back-links in VARS.  */
8190 
8191 static void
loc_exp_insert_dep(variable * var,rtx x,variable_table_type * vars)8192 loc_exp_insert_dep (variable *var, rtx x, variable_table_type *vars)
8193 {
8194   decl_or_value dv;
8195   variable *xvar;
8196   loc_exp_dep *led;
8197 
8198   dv = dv_from_rtx (x);
8199 
8200   /* ??? Build a vector of variables parallel to EXPANDING, to avoid
8201      an additional look up?  */
8202   xvar = vars->find_with_hash (dv, dv_htab_hash (dv));
8203 
8204   if (!xvar)
8205     {
8206       xvar = variable_from_dropped (dv, NO_INSERT);
8207       gcc_checking_assert (xvar);
8208     }
8209 
8210   /* No point in adding the same backlink more than once.  This may
8211      arise if say the same value appears in two complex expressions in
8212      the same loc_list, or even more than once in a single
8213      expression.  */
8214   if (VAR_LOC_DEP_LST (xvar) && VAR_LOC_DEP_LST (xvar)->dv == var->dv)
8215     return;
8216 
8217   if (var->onepart == NOT_ONEPART)
8218     led = new loc_exp_dep;
8219   else
8220     {
8221       loc_exp_dep empty;
8222       memset (&empty, 0, sizeof (empty));
8223       VAR_LOC_DEP_VEC (var)->quick_push (empty);
8224       led = &VAR_LOC_DEP_VEC (var)->last ();
8225     }
8226   led->dv = var->dv;
8227   led->value = x;
8228 
8229   loc_exp_dep_alloc (xvar, 0);
8230   led->pprev = VAR_LOC_DEP_LSTP (xvar);
8231   led->next = *led->pprev;
8232   if (led->next)
8233     led->next->pprev = &led->next;
8234   *led->pprev = led;
8235 }
8236 
8237 /* Create active dependencies of VAR on COUNT values starting at
8238    VALUE, and corresponding back-links to the entries in VARS.  Return
8239    true if we found any pending-recursion results.  */
8240 
8241 static bool
loc_exp_dep_set(variable * var,rtx result,rtx * value,int count,variable_table_type * vars)8242 loc_exp_dep_set (variable *var, rtx result, rtx *value, int count,
8243 		 variable_table_type *vars)
8244 {
8245   bool pending_recursion = false;
8246 
8247   gcc_checking_assert (VAR_LOC_DEP_VEC (var) == NULL
8248 		       || VAR_LOC_DEP_VEC (var)->is_empty ());
8249 
8250   /* Set up all dependencies from last_child (as set up at the end of
8251      the loop above) to the end.  */
8252   loc_exp_dep_alloc (var, count);
8253 
8254   while (count--)
8255     {
8256       rtx x = *value++;
8257 
8258       if (!pending_recursion)
8259 	pending_recursion = !result && VALUE_RECURSED_INTO (x);
8260 
8261       loc_exp_insert_dep (var, x, vars);
8262     }
8263 
8264   return pending_recursion;
8265 }
8266 
8267 /* Notify the back-links of IVAR that are pending recursion that we
8268    have found a non-NIL value for it, so they are cleared for another
8269    attempt to compute a current location.  */
8270 
8271 static void
notify_dependents_of_resolved_value(variable * ivar,variable_table_type * vars)8272 notify_dependents_of_resolved_value (variable *ivar, variable_table_type *vars)
8273 {
8274   loc_exp_dep *led, *next;
8275 
8276   for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
8277     {
8278       decl_or_value dv = led->dv;
8279       variable *var;
8280 
8281       next = led->next;
8282 
8283       if (dv_is_value_p (dv))
8284 	{
8285 	  rtx value = dv_as_value (dv);
8286 
8287 	  /* If we have already resolved it, leave it alone.  */
8288 	  if (!VALUE_RECURSED_INTO (value))
8289 	    continue;
8290 
8291 	  /* Check that VALUE_RECURSED_INTO, true from the test above,
8292 	     implies NO_LOC_P.  */
8293 	  gcc_checking_assert (NO_LOC_P (value));
8294 
8295 	  /* We won't notify variables that are being expanded,
8296 	     because their dependency list is cleared before
8297 	     recursing.  */
8298 	  NO_LOC_P (value) = false;
8299 	  VALUE_RECURSED_INTO (value) = false;
8300 
8301 	  gcc_checking_assert (dv_changed_p (dv));
8302 	}
8303       else
8304 	{
8305 	  gcc_checking_assert (dv_onepart_p (dv) != NOT_ONEPART);
8306 	  if (!dv_changed_p (dv))
8307 	    continue;
8308       }
8309 
8310       var = vars->find_with_hash (dv, dv_htab_hash (dv));
8311 
8312       if (!var)
8313 	var = variable_from_dropped (dv, NO_INSERT);
8314 
8315       if (var)
8316 	notify_dependents_of_resolved_value (var, vars);
8317 
8318       if (next)
8319 	next->pprev = led->pprev;
8320       if (led->pprev)
8321 	*led->pprev = next;
8322       led->next = NULL;
8323       led->pprev = NULL;
8324     }
8325 }
8326 
8327 static rtx vt_expand_loc_callback (rtx x, bitmap regs,
8328 				   int max_depth, void *data);
8329 
8330 /* Return the combined depth, when one sub-expression evaluated to
8331    BEST_DEPTH and the previous known depth was SAVED_DEPTH.  */
8332 
8333 static inline expand_depth
update_depth(expand_depth saved_depth,expand_depth best_depth)8334 update_depth (expand_depth saved_depth, expand_depth best_depth)
8335 {
8336   /* If we didn't find anything, stick with what we had.  */
8337   if (!best_depth.complexity)
8338     return saved_depth;
8339 
8340   /* If we found hadn't found anything, use the depth of the current
8341      expression.  Do NOT add one extra level, we want to compute the
8342      maximum depth among sub-expressions.  We'll increment it later,
8343      if appropriate.  */
8344   if (!saved_depth.complexity)
8345     return best_depth;
8346 
8347   /* Combine the entryval count so that regardless of which one we
8348      return, the entryval count is accurate.  */
8349   best_depth.entryvals = saved_depth.entryvals
8350     = best_depth.entryvals + saved_depth.entryvals;
8351 
8352   if (saved_depth.complexity < best_depth.complexity)
8353     return best_depth;
8354   else
8355     return saved_depth;
8356 }
8357 
8358 /* Expand VAR to a location RTX, updating its cur_loc.  Use REGS and
8359    DATA for cselib expand callback.  If PENDRECP is given, indicate in
8360    it whether any sub-expression couldn't be fully evaluated because
8361    it is pending recursion resolution.  */
8362 
8363 static inline rtx
vt_expand_var_loc_chain(variable * var,bitmap regs,void * data,bool * pendrecp)8364 vt_expand_var_loc_chain (variable *var, bitmap regs, void *data,
8365 			 bool *pendrecp)
8366 {
8367   class expand_loc_callback_data *elcd
8368     = (class expand_loc_callback_data *) data;
8369   location_chain *loc, *next;
8370   rtx result = NULL;
8371   int first_child, result_first_child, last_child;
8372   bool pending_recursion;
8373   rtx loc_from = NULL;
8374   struct elt_loc_list *cloc = NULL;
8375   expand_depth depth = { 0, 0 }, saved_depth = elcd->depth;
8376   int wanted_entryvals, found_entryvals = 0;
8377 
8378   /* Clear all backlinks pointing at this, so that we're not notified
8379      while we're active.  */
8380   loc_exp_dep_clear (var);
8381 
8382  retry:
8383   if (var->onepart == ONEPART_VALUE)
8384     {
8385       cselib_val *val = CSELIB_VAL_PTR (dv_as_value (var->dv));
8386 
8387       gcc_checking_assert (cselib_preserved_value_p (val));
8388 
8389       cloc = val->locs;
8390     }
8391 
8392   first_child = result_first_child = last_child
8393     = elcd->expanding.length ();
8394 
8395   wanted_entryvals = found_entryvals;
8396 
8397   /* Attempt to expand each available location in turn.  */
8398   for (next = loc = var->n_var_parts ? var->var_part[0].loc_chain : NULL;
8399        loc || cloc; loc = next)
8400     {
8401       result_first_child = last_child;
8402 
8403       if (!loc)
8404 	{
8405 	  loc_from = cloc->loc;
8406 	  next = loc;
8407 	  cloc = cloc->next;
8408 	  if (unsuitable_loc (loc_from))
8409 	    continue;
8410 	}
8411       else
8412 	{
8413 	  loc_from = loc->loc;
8414 	  next = loc->next;
8415 	}
8416 
8417       gcc_checking_assert (!unsuitable_loc (loc_from));
8418 
8419       elcd->depth.complexity = elcd->depth.entryvals = 0;
8420       result = cselib_expand_value_rtx_cb (loc_from, regs, EXPR_DEPTH,
8421 					   vt_expand_loc_callback, data);
8422       last_child = elcd->expanding.length ();
8423 
8424       if (result)
8425 	{
8426 	  depth = elcd->depth;
8427 
8428 	  gcc_checking_assert (depth.complexity
8429 			       || result_first_child == last_child);
8430 
8431 	  if (last_child - result_first_child != 1)
8432 	    {
8433 	      if (!depth.complexity && GET_CODE (result) == ENTRY_VALUE)
8434 		depth.entryvals++;
8435 	      depth.complexity++;
8436 	    }
8437 
8438 	  if (depth.complexity <= EXPR_USE_DEPTH)
8439 	    {
8440 	      if (depth.entryvals <= wanted_entryvals)
8441 		break;
8442 	      else if (!found_entryvals || depth.entryvals < found_entryvals)
8443 		found_entryvals = depth.entryvals;
8444 	    }
8445 
8446 	  result = NULL;
8447 	}
8448 
8449       /* Set it up in case we leave the loop.  */
8450       depth.complexity = depth.entryvals = 0;
8451       loc_from = NULL;
8452       result_first_child = first_child;
8453     }
8454 
8455   if (!loc_from && wanted_entryvals < found_entryvals)
8456     {
8457       /* We found entries with ENTRY_VALUEs and skipped them.  Since
8458 	 we could not find any expansions without ENTRY_VALUEs, but we
8459 	 found at least one with them, go back and get an entry with
8460 	 the minimum number ENTRY_VALUE count that we found.  We could
8461 	 avoid looping, but since each sub-loc is already resolved,
8462 	 the re-expansion should be trivial.  ??? Should we record all
8463 	 attempted locs as dependencies, so that we retry the
8464 	 expansion should any of them change, in the hope it can give
8465 	 us a new entry without an ENTRY_VALUE?  */
8466       elcd->expanding.truncate (first_child);
8467       goto retry;
8468     }
8469 
8470   /* Register all encountered dependencies as active.  */
8471   pending_recursion = loc_exp_dep_set
8472     (var, result, elcd->expanding.address () + result_first_child,
8473      last_child - result_first_child, elcd->vars);
8474 
8475   elcd->expanding.truncate (first_child);
8476 
8477   /* Record where the expansion came from.  */
8478   gcc_checking_assert (!result || !pending_recursion);
8479   VAR_LOC_FROM (var) = loc_from;
8480   VAR_LOC_DEPTH (var) = depth;
8481 
8482   gcc_checking_assert (!depth.complexity == !result);
8483 
8484   elcd->depth = update_depth (saved_depth, depth);
8485 
8486   /* Indicate whether any of the dependencies are pending recursion
8487      resolution.  */
8488   if (pendrecp)
8489     *pendrecp = pending_recursion;
8490 
8491   if (!pendrecp || !pending_recursion)
8492     var->var_part[0].cur_loc = result;
8493 
8494   return result;
8495 }
8496 
8497 /* Callback for cselib_expand_value, that looks for expressions
8498    holding the value in the var-tracking hash tables.  Return X for
8499    standard processing, anything else is to be used as-is.  */
8500 
8501 static rtx
vt_expand_loc_callback(rtx x,bitmap regs,int max_depth ATTRIBUTE_UNUSED,void * data)8502 vt_expand_loc_callback (rtx x, bitmap regs,
8503 			int max_depth ATTRIBUTE_UNUSED,
8504 			void *data)
8505 {
8506   class expand_loc_callback_data *elcd
8507     = (class expand_loc_callback_data *) data;
8508   decl_or_value dv;
8509   variable *var;
8510   rtx result, subreg;
8511   bool pending_recursion = false;
8512   bool from_empty = false;
8513 
8514   switch (GET_CODE (x))
8515     {
8516     case SUBREG:
8517       subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
8518 					   EXPR_DEPTH,
8519 					   vt_expand_loc_callback, data);
8520 
8521       if (!subreg)
8522 	return NULL;
8523 
8524       result = simplify_gen_subreg (GET_MODE (x), subreg,
8525 				    GET_MODE (SUBREG_REG (x)),
8526 				    SUBREG_BYTE (x));
8527 
8528       /* Invalid SUBREGs are ok in debug info.  ??? We could try
8529 	 alternate expansions for the VALUE as well.  */
8530       if (!result && GET_MODE (subreg) != VOIDmode)
8531 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
8532 
8533       return result;
8534 
8535     case DEBUG_EXPR:
8536     case VALUE:
8537       dv = dv_from_rtx (x);
8538       break;
8539 
8540     default:
8541       return x;
8542     }
8543 
8544   elcd->expanding.safe_push (x);
8545 
8546   /* Check that VALUE_RECURSED_INTO implies NO_LOC_P.  */
8547   gcc_checking_assert (!VALUE_RECURSED_INTO (x) || NO_LOC_P (x));
8548 
8549   if (NO_LOC_P (x))
8550     {
8551       gcc_checking_assert (VALUE_RECURSED_INTO (x) || !dv_changed_p (dv));
8552       return NULL;
8553     }
8554 
8555   var = elcd->vars->find_with_hash (dv, dv_htab_hash (dv));
8556 
8557   if (!var)
8558     {
8559       from_empty = true;
8560       var = variable_from_dropped (dv, INSERT);
8561     }
8562 
8563   gcc_checking_assert (var);
8564 
8565   if (!dv_changed_p (dv))
8566     {
8567       gcc_checking_assert (!NO_LOC_P (x));
8568       gcc_checking_assert (var->var_part[0].cur_loc);
8569       gcc_checking_assert (VAR_LOC_1PAUX (var));
8570       gcc_checking_assert (VAR_LOC_1PAUX (var)->depth.complexity);
8571 
8572       elcd->depth = update_depth (elcd->depth, VAR_LOC_1PAUX (var)->depth);
8573 
8574       return var->var_part[0].cur_loc;
8575     }
8576 
8577   VALUE_RECURSED_INTO (x) = true;
8578   /* This is tentative, but it makes some tests simpler.  */
8579   NO_LOC_P (x) = true;
8580 
8581   gcc_checking_assert (var->n_var_parts == 1 || from_empty);
8582 
8583   result = vt_expand_var_loc_chain (var, regs, data, &pending_recursion);
8584 
8585   if (pending_recursion)
8586     {
8587       gcc_checking_assert (!result);
8588       elcd->pending.safe_push (x);
8589     }
8590   else
8591     {
8592       NO_LOC_P (x) = !result;
8593       VALUE_RECURSED_INTO (x) = false;
8594       set_dv_changed (dv, false);
8595 
8596       if (result)
8597 	notify_dependents_of_resolved_value (var, elcd->vars);
8598     }
8599 
8600   return result;
8601 }
8602 
8603 /* While expanding variables, we may encounter recursion cycles
8604    because of mutual (possibly indirect) dependencies between two
8605    particular variables (or values), say A and B.  If we're trying to
8606    expand A when we get to B, which in turn attempts to expand A, if
8607    we can't find any other expansion for B, we'll add B to this
8608    pending-recursion stack, and tentatively return NULL for its
8609    location.  This tentative value will be used for any other
8610    occurrences of B, unless A gets some other location, in which case
8611    it will notify B that it is worth another try at computing a
8612    location for it, and it will use the location computed for A then.
8613    At the end of the expansion, the tentative NULL locations become
8614    final for all members of PENDING that didn't get a notification.
8615    This function performs this finalization of NULL locations.  */
8616 
8617 static void
resolve_expansions_pending_recursion(vec<rtx,va_heap> * pending)8618 resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending)
8619 {
8620   while (!pending->is_empty ())
8621     {
8622       rtx x = pending->pop ();
8623       decl_or_value dv;
8624 
8625       if (!VALUE_RECURSED_INTO (x))
8626 	continue;
8627 
8628       gcc_checking_assert (NO_LOC_P (x));
8629       VALUE_RECURSED_INTO (x) = false;
8630       dv = dv_from_rtx (x);
8631       gcc_checking_assert (dv_changed_p (dv));
8632       set_dv_changed (dv, false);
8633     }
8634 }
8635 
8636 /* Initialize expand_loc_callback_data D with variable hash table V.
8637    It must be a macro because of alloca (vec stack).  */
8638 #define INIT_ELCD(d, v)						\
8639   do								\
8640     {								\
8641       (d).vars = (v);						\
8642       (d).depth.complexity = (d).depth.entryvals = 0;		\
8643     }								\
8644   while (0)
8645 /* Finalize expand_loc_callback_data D, resolved to location L.  */
8646 #define FINI_ELCD(d, l)						\
8647   do								\
8648     {								\
8649       resolve_expansions_pending_recursion (&(d).pending);	\
8650       (d).pending.release ();					\
8651       (d).expanding.release ();					\
8652 								\
8653       if ((l) && MEM_P (l))					\
8654 	(l) = targetm.delegitimize_address (l);			\
8655     }								\
8656   while (0)
8657 
8658 /* Expand VALUEs and DEBUG_EXPRs in LOC to a location, using the
8659    equivalences in VARS, updating their CUR_LOCs in the process.  */
8660 
8661 static rtx
vt_expand_loc(rtx loc,variable_table_type * vars)8662 vt_expand_loc (rtx loc, variable_table_type *vars)
8663 {
8664   class expand_loc_callback_data data;
8665   rtx result;
8666 
8667   if (!MAY_HAVE_DEBUG_BIND_INSNS)
8668     return loc;
8669 
8670   INIT_ELCD (data, vars);
8671 
8672   result = cselib_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
8673 				       vt_expand_loc_callback, &data);
8674 
8675   FINI_ELCD (data, result);
8676 
8677   return result;
8678 }
8679 
8680 /* Expand the one-part VARiable to a location, using the equivalences
8681    in VARS, updating their CUR_LOCs in the process.  */
8682 
8683 static rtx
vt_expand_1pvar(variable * var,variable_table_type * vars)8684 vt_expand_1pvar (variable *var, variable_table_type *vars)
8685 {
8686   class expand_loc_callback_data data;
8687   rtx loc;
8688 
8689   gcc_checking_assert (var->onepart && var->n_var_parts == 1);
8690 
8691   if (!dv_changed_p (var->dv))
8692     return var->var_part[0].cur_loc;
8693 
8694   INIT_ELCD (data, vars);
8695 
8696   loc = vt_expand_var_loc_chain (var, scratch_regs, &data, NULL);
8697 
8698   gcc_checking_assert (data.expanding.is_empty ());
8699 
8700   FINI_ELCD (data, loc);
8701 
8702   return loc;
8703 }
8704 
8705 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP.  DATA contains
8706    additional parameters: WHERE specifies whether the note shall be emitted
8707    before or after instruction INSN.  */
8708 
8709 int
emit_note_insn_var_location(variable ** varp,emit_note_data * data)8710 emit_note_insn_var_location (variable **varp, emit_note_data *data)
8711 {
8712   variable *var = *varp;
8713   rtx_insn *insn = data->insn;
8714   enum emit_note_where where = data->where;
8715   variable_table_type *vars = data->vars;
8716   rtx_note *note;
8717   rtx note_vl;
8718   int i, j, n_var_parts;
8719   bool complete;
8720   enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
8721   HOST_WIDE_INT last_limit;
8722   HOST_WIDE_INT offsets[MAX_VAR_PARTS];
8723   rtx loc[MAX_VAR_PARTS];
8724   tree decl;
8725   location_chain *lc;
8726 
8727   gcc_checking_assert (var->onepart == NOT_ONEPART
8728 		       || var->onepart == ONEPART_VDECL);
8729 
8730   decl = dv_as_decl (var->dv);
8731 
8732   complete = true;
8733   last_limit = 0;
8734   n_var_parts = 0;
8735   if (!var->onepart)
8736     for (i = 0; i < var->n_var_parts; i++)
8737       if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
8738 	var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
8739   for (i = 0; i < var->n_var_parts; i++)
8740     {
8741       machine_mode mode, wider_mode;
8742       rtx loc2;
8743       HOST_WIDE_INT offset, size, wider_size;
8744 
8745       if (i == 0 && var->onepart)
8746 	{
8747 	  gcc_checking_assert (var->n_var_parts == 1);
8748 	  offset = 0;
8749 	  initialized = VAR_INIT_STATUS_INITIALIZED;
8750 	  loc2 = vt_expand_1pvar (var, vars);
8751 	}
8752       else
8753 	{
8754 	  if (last_limit < VAR_PART_OFFSET (var, i))
8755 	    {
8756 	      complete = false;
8757 	      break;
8758 	    }
8759 	  else if (last_limit > VAR_PART_OFFSET (var, i))
8760 	    continue;
8761 	  offset = VAR_PART_OFFSET (var, i);
8762 	  loc2 = var->var_part[i].cur_loc;
8763 	  if (loc2 && GET_CODE (loc2) == MEM
8764 	      && GET_CODE (XEXP (loc2, 0)) == VALUE)
8765 	    {
8766 	      rtx depval = XEXP (loc2, 0);
8767 
8768 	      loc2 = vt_expand_loc (loc2, vars);
8769 
8770 	      if (loc2)
8771 		loc_exp_insert_dep (var, depval, vars);
8772 	    }
8773 	  if (!loc2)
8774 	    {
8775 	      complete = false;
8776 	      continue;
8777 	    }
8778 	  gcc_checking_assert (GET_CODE (loc2) != VALUE);
8779 	  for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
8780 	    if (var->var_part[i].cur_loc == lc->loc)
8781 	      {
8782 		initialized = lc->init;
8783 		break;
8784 	      }
8785 	  gcc_assert (lc);
8786 	}
8787 
8788       offsets[n_var_parts] = offset;
8789       if (!loc2)
8790 	{
8791 	  complete = false;
8792 	  continue;
8793 	}
8794       loc[n_var_parts] = loc2;
8795       mode = GET_MODE (var->var_part[i].cur_loc);
8796       if (mode == VOIDmode && var->onepart)
8797 	mode = DECL_MODE (decl);
8798       /* We ony track subparts of constant-sized objects, since at present
8799 	 there's no representation for polynomial pieces.  */
8800       if (!GET_MODE_SIZE (mode).is_constant (&size))
8801 	{
8802 	  complete = false;
8803 	  continue;
8804 	}
8805       last_limit = offsets[n_var_parts] + size;
8806 
8807       /* Attempt to merge adjacent registers or memory.  */
8808       for (j = i + 1; j < var->n_var_parts; j++)
8809 	if (last_limit <= VAR_PART_OFFSET (var, j))
8810 	  break;
8811       if (j < var->n_var_parts
8812 	  && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
8813 	  && GET_MODE_SIZE (wider_mode).is_constant (&wider_size)
8814 	  && var->var_part[j].cur_loc
8815 	  && mode == GET_MODE (var->var_part[j].cur_loc)
8816 	  && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
8817 	  && last_limit == (var->onepart ? 0 : VAR_PART_OFFSET (var, j))
8818 	  && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
8819 	  && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
8820 	{
8821 	  rtx new_loc = NULL;
8822 	  poly_int64 offset2;
8823 
8824 	  if (REG_P (loc[n_var_parts])
8825 	      && hard_regno_nregs (REGNO (loc[n_var_parts]), mode) * 2
8826 		 == hard_regno_nregs (REGNO (loc[n_var_parts]), wider_mode)
8827 	      && end_hard_regno (mode, REGNO (loc[n_var_parts]))
8828 		 == REGNO (loc2))
8829 	    {
8830 	      if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
8831 		new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
8832 					   mode, 0);
8833 	      else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
8834 		new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
8835 	      if (new_loc)
8836 		{
8837 		  if (!REG_P (new_loc)
8838 		      || REGNO (new_loc) != REGNO (loc[n_var_parts]))
8839 		    new_loc = NULL;
8840 		  else
8841 		    REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
8842 		}
8843 	    }
8844 	  else if (MEM_P (loc[n_var_parts])
8845 		   && GET_CODE (XEXP (loc2, 0)) == PLUS
8846 		   && REG_P (XEXP (XEXP (loc2, 0), 0))
8847 		   && poly_int_rtx_p (XEXP (XEXP (loc2, 0), 1), &offset2))
8848 	    {
8849 	      poly_int64 end1 = size;
8850 	      rtx base1 = strip_offset_and_add (XEXP (loc[n_var_parts], 0),
8851 						&end1);
8852 	      if (rtx_equal_p (base1, XEXP (XEXP (loc2, 0), 0))
8853 		  && known_eq (end1, offset2))
8854 		new_loc = adjust_address_nv (loc[n_var_parts],
8855 					     wider_mode, 0);
8856 	    }
8857 
8858 	  if (new_loc)
8859 	    {
8860 	      loc[n_var_parts] = new_loc;
8861 	      mode = wider_mode;
8862 	      last_limit = offsets[n_var_parts] + wider_size;
8863 	      i = j;
8864 	    }
8865 	}
8866       ++n_var_parts;
8867     }
8868   poly_uint64 type_size_unit
8869     = tree_to_poly_uint64 (TYPE_SIZE_UNIT (TREE_TYPE (decl)));
8870   if (maybe_lt (poly_uint64 (last_limit), type_size_unit))
8871     complete = false;
8872 
8873   if (! flag_var_tracking_uninit)
8874     initialized = VAR_INIT_STATUS_INITIALIZED;
8875 
8876   note_vl = NULL_RTX;
8877   if (!complete)
8878     note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX, initialized);
8879   else if (n_var_parts == 1)
8880     {
8881       rtx expr_list;
8882 
8883       if (offsets[0] || GET_CODE (loc[0]) == PARALLEL)
8884 	expr_list = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
8885       else
8886 	expr_list = loc[0];
8887 
8888       note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list, initialized);
8889     }
8890   else if (n_var_parts)
8891     {
8892       rtx parallel;
8893 
8894       for (i = 0; i < n_var_parts; i++)
8895 	loc[i]
8896 	  = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
8897 
8898       parallel = gen_rtx_PARALLEL (VOIDmode,
8899 				   gen_rtvec_v (n_var_parts, loc));
8900       note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl,
8901 				      parallel, initialized);
8902     }
8903 
8904   if (where != EMIT_NOTE_BEFORE_INSN)
8905     {
8906       note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
8907       if (where == EMIT_NOTE_AFTER_CALL_INSN)
8908 	NOTE_DURING_CALL_P (note) = true;
8909     }
8910   else
8911     {
8912       /* Make sure that the call related notes come first.  */
8913       while (NEXT_INSN (insn)
8914 	     && NOTE_P (insn)
8915 	     && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
8916 	     && NOTE_DURING_CALL_P (insn))
8917 	insn = NEXT_INSN (insn);
8918       if (NOTE_P (insn)
8919 	  && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION
8920 	  && NOTE_DURING_CALL_P (insn))
8921 	note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
8922       else
8923 	note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
8924     }
8925   NOTE_VAR_LOCATION (note) = note_vl;
8926 
8927   set_dv_changed (var->dv, false);
8928   gcc_assert (var->in_changed_variables);
8929   var->in_changed_variables = false;
8930   changed_variables->clear_slot (varp);
8931 
8932   /* Continue traversing the hash table.  */
8933   return 1;
8934 }
8935 
8936 /* While traversing changed_variables, push onto DATA (a stack of RTX
8937    values) entries that aren't user variables.  */
8938 
8939 int
var_track_values_to_stack(variable ** slot,vec<rtx,va_heap> * changed_values_stack)8940 var_track_values_to_stack (variable **slot,
8941 			   vec<rtx, va_heap> *changed_values_stack)
8942 {
8943   variable *var = *slot;
8944 
8945   if (var->onepart == ONEPART_VALUE)
8946     changed_values_stack->safe_push (dv_as_value (var->dv));
8947   else if (var->onepart == ONEPART_DEXPR)
8948     changed_values_stack->safe_push (DECL_RTL_KNOWN_SET (dv_as_decl (var->dv)));
8949 
8950   return 1;
8951 }
8952 
8953 /* Remove from changed_variables the entry whose DV corresponds to
8954    value or debug_expr VAL.  */
8955 static void
remove_value_from_changed_variables(rtx val)8956 remove_value_from_changed_variables (rtx val)
8957 {
8958   decl_or_value dv = dv_from_rtx (val);
8959   variable **slot;
8960   variable *var;
8961 
8962   slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
8963 						NO_INSERT);
8964   var = *slot;
8965   var->in_changed_variables = false;
8966   changed_variables->clear_slot (slot);
8967 }
8968 
8969 /* If VAL (a value or debug_expr) has backlinks to variables actively
8970    dependent on it in HTAB or in CHANGED_VARIABLES, mark them as
8971    changed, adding to CHANGED_VALUES_STACK any dependencies that may
8972    have dependencies of their own to notify.  */
8973 
8974 static void
notify_dependents_of_changed_value(rtx val,variable_table_type * htab,vec<rtx,va_heap> * changed_values_stack)8975 notify_dependents_of_changed_value (rtx val, variable_table_type *htab,
8976 				    vec<rtx, va_heap> *changed_values_stack)
8977 {
8978   variable **slot;
8979   variable *var;
8980   loc_exp_dep *led;
8981   decl_or_value dv = dv_from_rtx (val);
8982 
8983   slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
8984 						NO_INSERT);
8985   if (!slot)
8986     slot = htab->find_slot_with_hash (dv, dv_htab_hash (dv), NO_INSERT);
8987   if (!slot)
8988     slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv),
8989 						NO_INSERT);
8990   var = *slot;
8991 
8992   while ((led = VAR_LOC_DEP_LST (var)))
8993     {
8994       decl_or_value ldv = led->dv;
8995       variable *ivar;
8996 
8997       /* Deactivate and remove the backlink, as it was “used up”.  It
8998 	 makes no sense to attempt to notify the same entity again:
8999 	 either it will be recomputed and re-register an active
9000 	 dependency, or it will still have the changed mark.  */
9001       if (led->next)
9002 	led->next->pprev = led->pprev;
9003       if (led->pprev)
9004 	*led->pprev = led->next;
9005       led->next = NULL;
9006       led->pprev = NULL;
9007 
9008       if (dv_changed_p (ldv))
9009 	continue;
9010 
9011       switch (dv_onepart_p (ldv))
9012 	{
9013 	case ONEPART_VALUE:
9014 	case ONEPART_DEXPR:
9015 	  set_dv_changed (ldv, true);
9016 	  changed_values_stack->safe_push (dv_as_rtx (ldv));
9017 	  break;
9018 
9019 	case ONEPART_VDECL:
9020 	  ivar = htab->find_with_hash (ldv, dv_htab_hash (ldv));
9021 	  gcc_checking_assert (!VAR_LOC_DEP_LST (ivar));
9022 	  variable_was_changed (ivar, NULL);
9023 	  break;
9024 
9025 	case NOT_ONEPART:
9026 	  delete led;
9027 	  ivar = htab->find_with_hash (ldv, dv_htab_hash (ldv));
9028 	  if (ivar)
9029 	    {
9030 	      int i = ivar->n_var_parts;
9031 	      while (i--)
9032 		{
9033 		  rtx loc = ivar->var_part[i].cur_loc;
9034 
9035 		  if (loc && GET_CODE (loc) == MEM
9036 		      && XEXP (loc, 0) == val)
9037 		    {
9038 		      variable_was_changed (ivar, NULL);
9039 		      break;
9040 		    }
9041 		}
9042 	    }
9043 	  break;
9044 
9045 	default:
9046 	  gcc_unreachable ();
9047 	}
9048     }
9049 }
9050 
9051 /* Take out of changed_variables any entries that don't refer to use
9052    variables.  Back-propagate change notifications from values and
9053    debug_exprs to their active dependencies in HTAB or in
9054    CHANGED_VARIABLES.  */
9055 
9056 static void
process_changed_values(variable_table_type * htab)9057 process_changed_values (variable_table_type *htab)
9058 {
9059   int i, n;
9060   rtx val;
9061   auto_vec<rtx, 20> changed_values_stack;
9062 
9063   /* Move values from changed_variables to changed_values_stack.  */
9064   changed_variables
9065     ->traverse <vec<rtx, va_heap>*, var_track_values_to_stack>
9066       (&changed_values_stack);
9067 
9068   /* Back-propagate change notifications in values while popping
9069      them from the stack.  */
9070   for (n = i = changed_values_stack.length ();
9071        i > 0; i = changed_values_stack.length ())
9072     {
9073       val = changed_values_stack.pop ();
9074       notify_dependents_of_changed_value (val, htab, &changed_values_stack);
9075 
9076       /* This condition will hold when visiting each of the entries
9077 	 originally in changed_variables.  We can't remove them
9078 	 earlier because this could drop the backlinks before we got a
9079 	 chance to use them.  */
9080       if (i == n)
9081 	{
9082 	  remove_value_from_changed_variables (val);
9083 	  n--;
9084 	}
9085     }
9086 }
9087 
9088 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
9089    CHANGED_VARIABLES and delete this chain.  WHERE specifies whether
9090    the notes shall be emitted before of after instruction INSN.  */
9091 
9092 static void
emit_notes_for_changes(rtx_insn * insn,enum emit_note_where where,shared_hash * vars)9093 emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
9094 			shared_hash *vars)
9095 {
9096   emit_note_data data;
9097   variable_table_type *htab = shared_hash_htab (vars);
9098 
9099   if (changed_variables->is_empty ())
9100     return;
9101 
9102   if (MAY_HAVE_DEBUG_BIND_INSNS)
9103     process_changed_values (htab);
9104 
9105   data.insn = insn;
9106   data.where = where;
9107   data.vars = htab;
9108 
9109   changed_variables
9110     ->traverse <emit_note_data*, emit_note_insn_var_location> (&data);
9111 }
9112 
9113 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
9114    same variable in hash table DATA or is not there at all.  */
9115 
9116 int
emit_notes_for_differences_1(variable ** slot,variable_table_type * new_vars)9117 emit_notes_for_differences_1 (variable **slot, variable_table_type *new_vars)
9118 {
9119   variable *old_var, *new_var;
9120 
9121   old_var = *slot;
9122   new_var = new_vars->find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));
9123 
9124   if (!new_var)
9125     {
9126       /* Variable has disappeared.  */
9127       variable *empty_var = NULL;
9128 
9129       if (old_var->onepart == ONEPART_VALUE
9130 	  || old_var->onepart == ONEPART_DEXPR)
9131 	{
9132 	  empty_var = variable_from_dropped (old_var->dv, NO_INSERT);
9133 	  if (empty_var)
9134 	    {
9135 	      gcc_checking_assert (!empty_var->in_changed_variables);
9136 	      if (!VAR_LOC_1PAUX (old_var))
9137 		{
9138 		  VAR_LOC_1PAUX (old_var) = VAR_LOC_1PAUX (empty_var);
9139 		  VAR_LOC_1PAUX (empty_var) = NULL;
9140 		}
9141 	      else
9142 		gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
9143 	    }
9144 	}
9145 
9146       if (!empty_var)
9147 	{
9148 	  empty_var = onepart_pool_allocate (old_var->onepart);
9149 	  empty_var->dv = old_var->dv;
9150 	  empty_var->refcount = 0;
9151 	  empty_var->n_var_parts = 0;
9152 	  empty_var->onepart = old_var->onepart;
9153 	  empty_var->in_changed_variables = false;
9154 	}
9155 
9156       if (empty_var->onepart)
9157 	{
9158 	  /* Propagate the auxiliary data to (ultimately)
9159 	     changed_variables.  */
9160 	  empty_var->var_part[0].loc_chain = NULL;
9161 	  empty_var->var_part[0].cur_loc = NULL;
9162 	  VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (old_var);
9163 	  VAR_LOC_1PAUX (old_var) = NULL;
9164 	}
9165       variable_was_changed (empty_var, NULL);
9166       /* Continue traversing the hash table.  */
9167       return 1;
9168     }
9169   /* Update cur_loc and one-part auxiliary data, before new_var goes
9170      through variable_was_changed.  */
9171   if (old_var != new_var && new_var->onepart)
9172     {
9173       gcc_checking_assert (VAR_LOC_1PAUX (new_var) == NULL);
9174       VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (old_var);
9175       VAR_LOC_1PAUX (old_var) = NULL;
9176       new_var->var_part[0].cur_loc = old_var->var_part[0].cur_loc;
9177     }
9178   if (variable_different_p (old_var, new_var))
9179     variable_was_changed (new_var, NULL);
9180 
9181   /* Continue traversing the hash table.  */
9182   return 1;
9183 }
9184 
9185 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
9186    table DATA.  */
9187 
9188 int
emit_notes_for_differences_2(variable ** slot,variable_table_type * old_vars)9189 emit_notes_for_differences_2 (variable **slot, variable_table_type *old_vars)
9190 {
9191   variable *old_var, *new_var;
9192 
9193   new_var = *slot;
9194   old_var = old_vars->find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
9195   if (!old_var)
9196     {
9197       int i;
9198       for (i = 0; i < new_var->n_var_parts; i++)
9199 	new_var->var_part[i].cur_loc = NULL;
9200       variable_was_changed (new_var, NULL);
9201     }
9202 
9203   /* Continue traversing the hash table.  */
9204   return 1;
9205 }
9206 
9207 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
9208    NEW_SET.  */
9209 
9210 static void
emit_notes_for_differences(rtx_insn * insn,dataflow_set * old_set,dataflow_set * new_set)9211 emit_notes_for_differences (rtx_insn *insn, dataflow_set *old_set,
9212 			    dataflow_set *new_set)
9213 {
9214   shared_hash_htab (old_set->vars)
9215     ->traverse <variable_table_type *, emit_notes_for_differences_1>
9216       (shared_hash_htab (new_set->vars));
9217   shared_hash_htab (new_set->vars)
9218     ->traverse <variable_table_type *, emit_notes_for_differences_2>
9219       (shared_hash_htab (old_set->vars));
9220   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
9221 }
9222 
9223 /* Return the next insn after INSN that is not a NOTE_INSN_VAR_LOCATION.  */
9224 
9225 static rtx_insn *
next_non_note_insn_var_location(rtx_insn * insn)9226 next_non_note_insn_var_location (rtx_insn *insn)
9227 {
9228   while (insn)
9229     {
9230       insn = NEXT_INSN (insn);
9231       if (insn == 0
9232 	  || !NOTE_P (insn)
9233 	  || NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION)
9234 	break;
9235     }
9236 
9237   return insn;
9238 }
9239 
9240 /* Emit the notes for changes of location parts in the basic block BB.  */
9241 
9242 static void
emit_notes_in_bb(basic_block bb,dataflow_set * set)9243 emit_notes_in_bb (basic_block bb, dataflow_set *set)
9244 {
9245   unsigned int i;
9246   micro_operation *mo;
9247 
9248   dataflow_set_clear (set);
9249   dataflow_set_copy (set, &VTI (bb)->in);
9250 
9251   FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo)
9252     {
9253       rtx_insn *insn = mo->insn;
9254       rtx_insn *next_insn = next_non_note_insn_var_location (insn);
9255 
9256       switch (mo->type)
9257 	{
9258 	  case MO_CALL:
9259 	    dataflow_set_clear_at_call (set, insn);
9260 	    emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
9261 	    {
9262 	      rtx arguments = mo->u.loc, *p = &arguments;
9263 	      while (*p)
9264 		{
9265 		  XEXP (XEXP (*p, 0), 1)
9266 		    = vt_expand_loc (XEXP (XEXP (*p, 0), 1),
9267 				     shared_hash_htab (set->vars));
9268 		  /* If expansion is successful, keep it in the list.  */
9269 		  if (XEXP (XEXP (*p, 0), 1))
9270 		    {
9271 		      XEXP (XEXP (*p, 0), 1)
9272 			= copy_rtx_if_shared (XEXP (XEXP (*p, 0), 1));
9273 		      p = &XEXP (*p, 1);
9274 		    }
9275 		  /* Otherwise, if the following item is data_value for it,
9276 		     drop it too too.  */
9277 		  else if (XEXP (*p, 1)
9278 			   && REG_P (XEXP (XEXP (*p, 0), 0))
9279 			   && MEM_P (XEXP (XEXP (XEXP (*p, 1), 0), 0))
9280 			   && REG_P (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), 0),
9281 					   0))
9282 			   && REGNO (XEXP (XEXP (*p, 0), 0))
9283 			      == REGNO (XEXP (XEXP (XEXP (XEXP (*p, 1), 0),
9284 						    0), 0)))
9285 		    *p = XEXP (XEXP (*p, 1), 1);
9286 		  /* Just drop this item.  */
9287 		  else
9288 		    *p = XEXP (*p, 1);
9289 		}
9290 	      add_reg_note (insn, REG_CALL_ARG_LOCATION, arguments);
9291 	    }
9292 	    break;
9293 
9294 	  case MO_USE:
9295 	    {
9296 	      rtx loc = mo->u.loc;
9297 
9298 	      if (REG_P (loc))
9299 		var_reg_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
9300 	      else
9301 		var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
9302 
9303 	      emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
9304 	    }
9305 	    break;
9306 
9307 	  case MO_VAL_LOC:
9308 	    {
9309 	      rtx loc = mo->u.loc;
9310 	      rtx val, vloc;
9311 	      tree var;
9312 
9313 	      if (GET_CODE (loc) == CONCAT)
9314 		{
9315 		  val = XEXP (loc, 0);
9316 		  vloc = XEXP (loc, 1);
9317 		}
9318 	      else
9319 		{
9320 		  val = NULL_RTX;
9321 		  vloc = loc;
9322 		}
9323 
9324 	      var = PAT_VAR_LOCATION_DECL (vloc);
9325 
9326 	      clobber_variable_part (set, NULL_RTX,
9327 				     dv_from_decl (var), 0, NULL_RTX);
9328 	      if (val)
9329 		{
9330 		  if (VAL_NEEDS_RESOLUTION (loc))
9331 		    val_resolve (set, val, PAT_VAR_LOCATION_LOC (vloc), insn);
9332 		  set_variable_part (set, val, dv_from_decl (var), 0,
9333 				     VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
9334 				     INSERT);
9335 		}
9336 	      else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
9337 		set_variable_part (set, PAT_VAR_LOCATION_LOC (vloc),
9338 				   dv_from_decl (var), 0,
9339 				   VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
9340 				   INSERT);
9341 
9342 	      emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
9343 	    }
9344 	    break;
9345 
9346 	  case MO_VAL_USE:
9347 	    {
9348 	      rtx loc = mo->u.loc;
9349 	      rtx val, vloc, uloc;
9350 
9351 	      vloc = uloc = XEXP (loc, 1);
9352 	      val = XEXP (loc, 0);
9353 
9354 	      if (GET_CODE (val) == CONCAT)
9355 		{
9356 		  uloc = XEXP (val, 1);
9357 		  val = XEXP (val, 0);
9358 		}
9359 
9360 	      if (VAL_NEEDS_RESOLUTION (loc))
9361 		val_resolve (set, val, vloc, insn);
9362 	      else
9363 		val_store (set, val, uloc, insn, false);
9364 
9365 	      if (VAL_HOLDS_TRACK_EXPR (loc))
9366 		{
9367 		  if (GET_CODE (uloc) == REG)
9368 		    var_reg_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
9369 				 NULL);
9370 		  else if (GET_CODE (uloc) == MEM)
9371 		    var_mem_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
9372 				 NULL);
9373 		}
9374 
9375 	      emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
9376 	    }
9377 	    break;
9378 
9379 	  case MO_VAL_SET:
9380 	    {
9381 	      rtx loc = mo->u.loc;
9382 	      rtx val, vloc, uloc;
9383 	      rtx dstv, srcv;
9384 
9385 	      vloc = loc;
9386 	      uloc = XEXP (vloc, 1);
9387 	      val = XEXP (vloc, 0);
9388 	      vloc = uloc;
9389 
9390 	      if (GET_CODE (uloc) == SET)
9391 		{
9392 		  dstv = SET_DEST (uloc);
9393 		  srcv = SET_SRC (uloc);
9394 		}
9395 	      else
9396 		{
9397 		  dstv = uloc;
9398 		  srcv = NULL;
9399 		}
9400 
9401 	      if (GET_CODE (val) == CONCAT)
9402 		{
9403 		  dstv = vloc = XEXP (val, 1);
9404 		  val = XEXP (val, 0);
9405 		}
9406 
9407 	      if (GET_CODE (vloc) == SET)
9408 		{
9409 		  srcv = SET_SRC (vloc);
9410 
9411 		  gcc_assert (val != srcv);
9412 		  gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
9413 
9414 		  dstv = vloc = SET_DEST (vloc);
9415 
9416 		  if (VAL_NEEDS_RESOLUTION (loc))
9417 		    val_resolve (set, val, srcv, insn);
9418 		}
9419 	      else if (VAL_NEEDS_RESOLUTION (loc))
9420 		{
9421 		  gcc_assert (GET_CODE (uloc) == SET
9422 			      && GET_CODE (SET_SRC (uloc)) == REG);
9423 		  val_resolve (set, val, SET_SRC (uloc), insn);
9424 		}
9425 
9426 	      if (VAL_HOLDS_TRACK_EXPR (loc))
9427 		{
9428 		  if (VAL_EXPR_IS_CLOBBERED (loc))
9429 		    {
9430 		      if (REG_P (uloc))
9431 			var_reg_delete (set, uloc, true);
9432 		      else if (MEM_P (uloc))
9433 			{
9434 			  gcc_assert (MEM_P (dstv));
9435 			  gcc_assert (MEM_ATTRS (dstv) == MEM_ATTRS (uloc));
9436 			  var_mem_delete (set, dstv, true);
9437 			}
9438 		    }
9439 		  else
9440 		    {
9441 		      bool copied_p = VAL_EXPR_IS_COPIED (loc);
9442 		      rtx src = NULL, dst = uloc;
9443 		      enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
9444 
9445 		      if (GET_CODE (uloc) == SET)
9446 			{
9447 			  src = SET_SRC (uloc);
9448 			  dst = SET_DEST (uloc);
9449 			}
9450 
9451 		      if (copied_p)
9452 			{
9453 			  status = find_src_status (set, src);
9454 
9455 			  src = find_src_set_src (set, src);
9456 			}
9457 
9458 		      if (REG_P (dst))
9459 			var_reg_delete_and_set (set, dst, !copied_p,
9460 						status, srcv);
9461 		      else if (MEM_P (dst))
9462 			{
9463 			  gcc_assert (MEM_P (dstv));
9464 			  gcc_assert (MEM_ATTRS (dstv) == MEM_ATTRS (dst));
9465 			  var_mem_delete_and_set (set, dstv, !copied_p,
9466 						  status, srcv);
9467 			}
9468 		    }
9469 		}
9470 	      else if (REG_P (uloc))
9471 		var_regno_delete (set, REGNO (uloc));
9472 	      else if (MEM_P (uloc))
9473 		{
9474 		  gcc_checking_assert (GET_CODE (vloc) == MEM);
9475 		  gcc_checking_assert (vloc == dstv);
9476 		  if (vloc != dstv)
9477 		    clobber_overlapping_mems (set, vloc);
9478 		}
9479 
9480 	      val_store (set, val, dstv, insn, true);
9481 
9482 	      emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
9483 				      set->vars);
9484 	    }
9485 	    break;
9486 
9487 	  case MO_SET:
9488 	    {
9489 	      rtx loc = mo->u.loc;
9490 	      rtx set_src = NULL;
9491 
9492 	      if (GET_CODE (loc) == SET)
9493 		{
9494 		  set_src = SET_SRC (loc);
9495 		  loc = SET_DEST (loc);
9496 		}
9497 
9498 	      if (REG_P (loc))
9499 		var_reg_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
9500 					set_src);
9501 	      else
9502 		var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
9503 					set_src);
9504 
9505 	      emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
9506 				      set->vars);
9507 	    }
9508 	    break;
9509 
9510 	  case MO_COPY:
9511 	    {
9512 	      rtx loc = mo->u.loc;
9513 	      enum var_init_status src_status;
9514 	      rtx set_src = NULL;
9515 
9516 	      if (GET_CODE (loc) == SET)
9517 		{
9518 		  set_src = SET_SRC (loc);
9519 		  loc = SET_DEST (loc);
9520 		}
9521 
9522 	      src_status = find_src_status (set, set_src);
9523 	      set_src = find_src_set_src (set, set_src);
9524 
9525 	      if (REG_P (loc))
9526 		var_reg_delete_and_set (set, loc, false, src_status, set_src);
9527 	      else
9528 		var_mem_delete_and_set (set, loc, false, src_status, set_src);
9529 
9530 	      emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
9531 				      set->vars);
9532 	    }
9533 	    break;
9534 
9535 	  case MO_USE_NO_VAR:
9536 	    {
9537 	      rtx loc = mo->u.loc;
9538 
9539 	      if (REG_P (loc))
9540 		var_reg_delete (set, loc, false);
9541 	      else
9542 		var_mem_delete (set, loc, false);
9543 
9544 	      emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
9545 	    }
9546 	    break;
9547 
9548 	  case MO_CLOBBER:
9549 	    {
9550 	      rtx loc = mo->u.loc;
9551 
9552 	      if (REG_P (loc))
9553 		var_reg_delete (set, loc, true);
9554 	      else
9555 		var_mem_delete (set, loc, true);
9556 
9557 	      emit_notes_for_changes (next_insn, EMIT_NOTE_BEFORE_INSN,
9558 				      set->vars);
9559 	    }
9560 	    break;
9561 
9562 	  case MO_ADJUST:
9563 	    set->stack_adjust += mo->u.adjust;
9564 	    break;
9565 	}
9566     }
9567 }
9568 
9569 /* Emit notes for the whole function.  */
9570 
9571 static void
vt_emit_notes(void)9572 vt_emit_notes (void)
9573 {
9574   basic_block bb;
9575   dataflow_set cur;
9576 
9577   gcc_assert (changed_variables->is_empty ());
9578 
9579   /* Free memory occupied by the out hash tables, as they aren't used
9580      anymore.  */
9581   FOR_EACH_BB_FN (bb, cfun)
9582     dataflow_set_clear (&VTI (bb)->out);
9583 
9584   /* Enable emitting notes by functions (mainly by set_variable_part and
9585      delete_variable_part).  */
9586   emit_notes = true;
9587 
9588   if (MAY_HAVE_DEBUG_BIND_INSNS)
9589     dropped_values = new variable_table_type (cselib_get_next_uid () * 2);
9590 
9591   dataflow_set_init (&cur);
9592 
9593   FOR_EACH_BB_FN (bb, cfun)
9594     {
9595       /* Emit the notes for changes of variable locations between two
9596 	 subsequent basic blocks.  */
9597       emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
9598 
9599       if (MAY_HAVE_DEBUG_BIND_INSNS)
9600 	local_get_addr_cache = new hash_map<rtx, rtx>;
9601 
9602       /* Emit the notes for the changes in the basic block itself.  */
9603       emit_notes_in_bb (bb, &cur);
9604 
9605       if (MAY_HAVE_DEBUG_BIND_INSNS)
9606 	delete local_get_addr_cache;
9607       local_get_addr_cache = NULL;
9608 
9609       /* Free memory occupied by the in hash table, we won't need it
9610 	 again.  */
9611       dataflow_set_clear (&VTI (bb)->in);
9612     }
9613 
9614   if (flag_checking)
9615     shared_hash_htab (cur.vars)
9616       ->traverse <variable_table_type *, emit_notes_for_differences_1>
9617 	(shared_hash_htab (empty_shared_hash));
9618 
9619   dataflow_set_destroy (&cur);
9620 
9621   if (MAY_HAVE_DEBUG_BIND_INSNS)
9622     delete dropped_values;
9623   dropped_values = NULL;
9624 
9625   emit_notes = false;
9626 }
9627 
9628 /* If there is a declaration and offset associated with register/memory RTL
9629    assign declaration to *DECLP and offset to *OFFSETP, and return true.  */
9630 
9631 static bool
vt_get_decl_and_offset(rtx rtl,tree * declp,poly_int64 * offsetp)9632 vt_get_decl_and_offset (rtx rtl, tree *declp, poly_int64 *offsetp)
9633 {
9634   if (REG_P (rtl))
9635     {
9636       if (REG_ATTRS (rtl))
9637 	{
9638 	  *declp = REG_EXPR (rtl);
9639 	  *offsetp = REG_OFFSET (rtl);
9640 	  return true;
9641 	}
9642     }
9643   else if (GET_CODE (rtl) == PARALLEL)
9644     {
9645       tree decl = NULL_TREE;
9646       HOST_WIDE_INT offset = MAX_VAR_PARTS;
9647       int len = XVECLEN (rtl, 0), i;
9648 
9649       for (i = 0; i < len; i++)
9650 	{
9651 	  rtx reg = XEXP (XVECEXP (rtl, 0, i), 0);
9652 	  if (!REG_P (reg) || !REG_ATTRS (reg))
9653 	    break;
9654 	  if (!decl)
9655 	    decl = REG_EXPR (reg);
9656 	  if (REG_EXPR (reg) != decl)
9657 	    break;
9658 	  HOST_WIDE_INT this_offset;
9659 	  if (!track_offset_p (REG_OFFSET (reg), &this_offset))
9660 	    break;
9661 	  offset = MIN (offset, this_offset);
9662 	}
9663 
9664       if (i == len)
9665 	{
9666 	  *declp = decl;
9667 	  *offsetp = offset;
9668 	  return true;
9669 	}
9670     }
9671   else if (MEM_P (rtl))
9672     {
9673       if (MEM_ATTRS (rtl))
9674 	{
9675 	  *declp = MEM_EXPR (rtl);
9676 	  *offsetp = int_mem_offset (rtl);
9677 	  return true;
9678 	}
9679     }
9680   return false;
9681 }
9682 
9683 /* Record the value for the ENTRY_VALUE of RTL as a global equivalence
9684    of VAL.  */
9685 
9686 static void
record_entry_value(cselib_val * val,rtx rtl)9687 record_entry_value (cselib_val *val, rtx rtl)
9688 {
9689   rtx ev = gen_rtx_ENTRY_VALUE (GET_MODE (rtl));
9690 
9691   ENTRY_VALUE_EXP (ev) = rtl;
9692 
9693   cselib_add_permanent_equiv (val, ev, get_insns ());
9694 }
9695 
9696 /* Insert function parameter PARM in IN and OUT sets of ENTRY_BLOCK.  */
9697 
9698 static void
vt_add_function_parameter(tree parm)9699 vt_add_function_parameter (tree parm)
9700 {
9701   rtx decl_rtl = DECL_RTL_IF_SET (parm);
9702   rtx incoming = DECL_INCOMING_RTL (parm);
9703   tree decl;
9704   machine_mode mode;
9705   poly_int64 offset;
9706   dataflow_set *out;
9707   decl_or_value dv;
9708   bool incoming_ok = true;
9709 
9710   if (TREE_CODE (parm) != PARM_DECL)
9711     return;
9712 
9713   if (!decl_rtl || !incoming)
9714     return;
9715 
9716   if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
9717     return;
9718 
9719   /* If there is a DRAP register or a pseudo in internal_arg_pointer,
9720      rewrite the incoming location of parameters passed on the stack
9721      into MEMs based on the argument pointer, so that incoming doesn't
9722      depend on a pseudo.  */
9723   poly_int64 incoming_offset = 0;
9724   if (MEM_P (incoming)
9725       && (strip_offset (XEXP (incoming, 0), &incoming_offset)
9726 	  == crtl->args.internal_arg_pointer))
9727     {
9728       HOST_WIDE_INT off = -FIRST_PARM_OFFSET (current_function_decl);
9729       incoming
9730 	= replace_equiv_address_nv (incoming,
9731 				    plus_constant (Pmode,
9732 						   arg_pointer_rtx,
9733 						   off + incoming_offset));
9734     }
9735 
9736 #ifdef HAVE_window_save
9737   /* DECL_INCOMING_RTL uses the INCOMING_REGNO of parameter registers.
9738      If the target machine has an explicit window save instruction, the
9739      actual entry value is the corresponding OUTGOING_REGNO instead.  */
9740   if (HAVE_window_save && !crtl->uses_only_leaf_regs)
9741     {
9742       if (REG_P (incoming)
9743 	  && HARD_REGISTER_P (incoming)
9744 	  && OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
9745 	{
9746 	  parm_reg p;
9747 	  p.incoming = incoming;
9748 	  incoming
9749 	    = gen_rtx_REG_offset (incoming, GET_MODE (incoming),
9750 				  OUTGOING_REGNO (REGNO (incoming)), 0);
9751 	  p.outgoing = incoming;
9752 	  vec_safe_push (windowed_parm_regs, p);
9753 	}
9754       else if (GET_CODE (incoming) == PARALLEL)
9755 	{
9756 	  rtx outgoing
9757 	    = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (XVECLEN (incoming, 0)));
9758 	  int i;
9759 
9760 	  for (i = 0; i < XVECLEN (incoming, 0); i++)
9761 	    {
9762 	      rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
9763 	      parm_reg p;
9764 	      p.incoming = reg;
9765 	      reg = gen_rtx_REG_offset (reg, GET_MODE (reg),
9766 					OUTGOING_REGNO (REGNO (reg)), 0);
9767 	      p.outgoing = reg;
9768 	      XVECEXP (outgoing, 0, i)
9769 		= gen_rtx_EXPR_LIST (VOIDmode, reg,
9770 				     XEXP (XVECEXP (incoming, 0, i), 1));
9771 	      vec_safe_push (windowed_parm_regs, p);
9772 	    }
9773 
9774 	  incoming = outgoing;
9775 	}
9776       else if (MEM_P (incoming)
9777 	       && REG_P (XEXP (incoming, 0))
9778 	       && HARD_REGISTER_P (XEXP (incoming, 0)))
9779 	{
9780 	  rtx reg = XEXP (incoming, 0);
9781 	  if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
9782 	    {
9783 	      parm_reg p;
9784 	      p.incoming = reg;
9785 	      reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
9786 	      p.outgoing = reg;
9787 	      vec_safe_push (windowed_parm_regs, p);
9788 	      incoming = replace_equiv_address_nv (incoming, reg);
9789 	    }
9790 	}
9791     }
9792 #endif
9793 
9794   if (!vt_get_decl_and_offset (incoming, &decl, &offset))
9795     {
9796       incoming_ok = false;
9797       if (MEM_P (incoming))
9798 	{
9799 	  /* This means argument is passed by invisible reference.  */
9800 	  offset = 0;
9801 	  decl = parm;
9802 	}
9803       else
9804 	{
9805 	  if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
9806 	    return;
9807 	  offset += byte_lowpart_offset (GET_MODE (incoming),
9808 					 GET_MODE (decl_rtl));
9809 	}
9810     }
9811 
9812   if (!decl)
9813     return;
9814 
9815   if (parm != decl)
9816     {
9817       /* If that DECL_RTL wasn't a pseudo that got spilled to
9818 	 memory, bail out.  Otherwise, the spill slot sharing code
9819 	 will force the memory to reference spill_slot_decl (%sfp),
9820 	 so we don't match above.  That's ok, the pseudo must have
9821 	 referenced the entire parameter, so just reset OFFSET.  */
9822       if (decl != get_spill_slot_decl (false))
9823         return;
9824       offset = 0;
9825     }
9826 
9827   HOST_WIDE_INT const_offset;
9828   if (!track_loc_p (incoming, parm, offset, false, &mode, &const_offset))
9829     return;
9830 
9831   out = &VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out;
9832 
9833   dv = dv_from_decl (parm);
9834 
9835   if (target_for_debug_bind (parm)
9836       /* We can't deal with these right now, because this kind of
9837 	 variable is single-part.  ??? We could handle parallels
9838 	 that describe multiple locations for the same single
9839 	 value, but ATM we don't.  */
9840       && GET_CODE (incoming) != PARALLEL)
9841     {
9842       cselib_val *val;
9843       rtx lowpart;
9844 
9845       /* ??? We shouldn't ever hit this, but it may happen because
9846 	 arguments passed by invisible reference aren't dealt with
9847 	 above: incoming-rtl will have Pmode rather than the
9848 	 expected mode for the type.  */
9849       if (const_offset)
9850 	return;
9851 
9852       lowpart = var_lowpart (mode, incoming);
9853       if (!lowpart)
9854 	return;
9855 
9856       val = cselib_lookup_from_insn (lowpart, mode, true,
9857 				     VOIDmode, get_insns ());
9858 
9859       /* ??? Float-typed values in memory are not handled by
9860 	 cselib.  */
9861       if (val)
9862 	{
9863 	  preserve_value (val);
9864 	  set_variable_part (out, val->val_rtx, dv, const_offset,
9865 			     VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
9866 	  dv = dv_from_value (val->val_rtx);
9867 	}
9868 
9869       if (MEM_P (incoming))
9870 	{
9871 	  val = cselib_lookup_from_insn (XEXP (incoming, 0), mode, true,
9872 					 VOIDmode, get_insns ());
9873 	  if (val)
9874 	    {
9875 	      preserve_value (val);
9876 	      incoming = replace_equiv_address_nv (incoming, val->val_rtx);
9877 	    }
9878 	}
9879     }
9880 
9881   if (REG_P (incoming))
9882     {
9883       incoming = var_lowpart (mode, incoming);
9884       gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
9885       attrs_list_insert (&out->regs[REGNO (incoming)], dv, const_offset,
9886 			 incoming);
9887       set_variable_part (out, incoming, dv, const_offset,
9888 			 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
9889       if (dv_is_value_p (dv))
9890 	{
9891 	  record_entry_value (CSELIB_VAL_PTR (dv_as_value (dv)), incoming);
9892 	  if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
9893 	      && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
9894 	    {
9895 	      machine_mode indmode
9896 		= TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
9897 	      rtx mem = gen_rtx_MEM (indmode, incoming);
9898 	      cselib_val *val = cselib_lookup_from_insn (mem, indmode, true,
9899 							 VOIDmode,
9900 							 get_insns ());
9901 	      if (val)
9902 		{
9903 		  preserve_value (val);
9904 		  record_entry_value (val, mem);
9905 		  set_variable_part (out, mem, dv_from_value (val->val_rtx), 0,
9906 				     VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
9907 		}
9908 	    }
9909 	}
9910     }
9911   else if (GET_CODE (incoming) == PARALLEL && !dv_onepart_p (dv))
9912     {
9913       int i;
9914 
9915       /* The following code relies on vt_get_decl_and_offset returning true for
9916 	 incoming, which might not be always the case.  */
9917       if (!incoming_ok)
9918 	return;
9919       for (i = 0; i < XVECLEN (incoming, 0); i++)
9920 	{
9921 	  rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
9922 	  /* vt_get_decl_and_offset has already checked that the offset
9923 	     is a valid variable part.  */
9924 	  const_offset = get_tracked_reg_offset (reg);
9925 	  gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
9926 	  attrs_list_insert (&out->regs[REGNO (reg)], dv, const_offset, reg);
9927 	  set_variable_part (out, reg, dv, const_offset,
9928 			     VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
9929 	}
9930     }
9931   else if (MEM_P (incoming))
9932     {
9933       incoming = var_lowpart (mode, incoming);
9934       set_variable_part (out, incoming, dv, const_offset,
9935 			 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
9936     }
9937 }
9938 
9939 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK.  */
9940 
9941 static void
vt_add_function_parameters(void)9942 vt_add_function_parameters (void)
9943 {
9944   tree parm;
9945 
9946   for (parm = DECL_ARGUMENTS (current_function_decl);
9947        parm; parm = DECL_CHAIN (parm))
9948     vt_add_function_parameter (parm);
9949 
9950   if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
9951     {
9952       tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl));
9953 
9954       if (TREE_CODE (vexpr) == INDIRECT_REF)
9955 	vexpr = TREE_OPERAND (vexpr, 0);
9956 
9957       if (TREE_CODE (vexpr) == PARM_DECL
9958 	  && DECL_ARTIFICIAL (vexpr)
9959 	  && !DECL_IGNORED_P (vexpr)
9960 	  && DECL_NAMELESS (vexpr))
9961 	vt_add_function_parameter (vexpr);
9962     }
9963 }
9964 
9965 /* Initialize cfa_base_rtx, create a preserved VALUE for it and
9966    ensure it isn't flushed during cselib_reset_table.
9967    Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
9968    has been eliminated.  */
9969 
9970 static void
vt_init_cfa_base(void)9971 vt_init_cfa_base (void)
9972 {
9973   cselib_val *val;
9974 
9975 #ifdef FRAME_POINTER_CFA_OFFSET
9976   cfa_base_rtx = frame_pointer_rtx;
9977   cfa_base_offset = -FRAME_POINTER_CFA_OFFSET (current_function_decl);
9978 #else
9979   cfa_base_rtx = arg_pointer_rtx;
9980   cfa_base_offset = -ARG_POINTER_CFA_OFFSET (current_function_decl);
9981 #endif
9982   if (cfa_base_rtx == hard_frame_pointer_rtx
9983       || !fixed_regs[REGNO (cfa_base_rtx)])
9984     {
9985       cfa_base_rtx = NULL_RTX;
9986       return;
9987     }
9988   if (!MAY_HAVE_DEBUG_BIND_INSNS)
9989     return;
9990 
9991   /* Tell alias analysis that cfa_base_rtx should share
9992      find_base_term value with stack pointer or hard frame pointer.  */
9993   if (!frame_pointer_needed)
9994     vt_equate_reg_base_value (cfa_base_rtx, stack_pointer_rtx);
9995   else if (!crtl->stack_realign_tried)
9996     vt_equate_reg_base_value (cfa_base_rtx, hard_frame_pointer_rtx);
9997 
9998   val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1,
9999 				 VOIDmode, get_insns ());
10000   preserve_value (val);
10001   cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx));
10002 }
10003 
10004 /* Reemit INSN, a MARKER_DEBUG_INSN, as a note.  */
10005 
10006 static rtx_insn *
reemit_marker_as_note(rtx_insn * insn)10007 reemit_marker_as_note (rtx_insn *insn)
10008 {
10009   gcc_checking_assert (DEBUG_MARKER_INSN_P (insn));
10010 
10011   enum insn_note kind = INSN_DEBUG_MARKER_KIND (insn);
10012 
10013   switch (kind)
10014     {
10015     case NOTE_INSN_BEGIN_STMT:
10016     case NOTE_INSN_INLINE_ENTRY:
10017       {
10018 	rtx_insn *note = NULL;
10019 	if (cfun->debug_nonbind_markers)
10020 	  {
10021 	    note = emit_note_before (kind, insn);
10022 	    NOTE_MARKER_LOCATION (note) = INSN_LOCATION (insn);
10023 	  }
10024 	delete_insn (insn);
10025 	return note;
10026       }
10027 
10028     default:
10029       gcc_unreachable ();
10030     }
10031 }
10032 
10033 /* Allocate and initialize the data structures for variable tracking
10034    and parse the RTL to get the micro operations.  */
10035 
10036 static bool
vt_initialize(void)10037 vt_initialize (void)
10038 {
10039   basic_block bb;
10040   poly_int64 fp_cfa_offset = -1;
10041 
10042   alloc_aux_for_blocks (sizeof (variable_tracking_info));
10043 
10044   empty_shared_hash = shared_hash_pool.allocate ();
10045   empty_shared_hash->refcount = 1;
10046   empty_shared_hash->htab = new variable_table_type (1);
10047   changed_variables = new variable_table_type (10);
10048 
10049   /* Init the IN and OUT sets.  */
10050   FOR_ALL_BB_FN (bb, cfun)
10051     {
10052       VTI (bb)->visited = false;
10053       VTI (bb)->flooded = false;
10054       dataflow_set_init (&VTI (bb)->in);
10055       dataflow_set_init (&VTI (bb)->out);
10056       VTI (bb)->permp = NULL;
10057     }
10058 
10059   if (MAY_HAVE_DEBUG_BIND_INSNS)
10060     {
10061       cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
10062       scratch_regs = BITMAP_ALLOC (NULL);
10063       preserved_values.create (256);
10064       global_get_addr_cache = new hash_map<rtx, rtx>;
10065     }
10066   else
10067     {
10068       scratch_regs = NULL;
10069       global_get_addr_cache = NULL;
10070     }
10071 
10072   if (MAY_HAVE_DEBUG_BIND_INSNS)
10073     {
10074       rtx reg, expr;
10075       int ofst;
10076       cselib_val *val;
10077 
10078 #ifdef FRAME_POINTER_CFA_OFFSET
10079       reg = frame_pointer_rtx;
10080       ofst = FRAME_POINTER_CFA_OFFSET (current_function_decl);
10081 #else
10082       reg = arg_pointer_rtx;
10083       ofst = ARG_POINTER_CFA_OFFSET (current_function_decl);
10084 #endif
10085 
10086       ofst -= INCOMING_FRAME_SP_OFFSET;
10087 
10088       val = cselib_lookup_from_insn (reg, GET_MODE (reg), 1,
10089 				     VOIDmode, get_insns ());
10090       preserve_value (val);
10091       if (reg != hard_frame_pointer_rtx && fixed_regs[REGNO (reg)])
10092 	cselib_preserve_cfa_base_value (val, REGNO (reg));
10093       if (ofst)
10094 	{
10095 	  cselib_val *valsp
10096 	    = cselib_lookup_from_insn (stack_pointer_rtx,
10097 				       GET_MODE (stack_pointer_rtx), 1,
10098 				       VOIDmode, get_insns ());
10099 	  preserve_value (valsp);
10100 	  expr = plus_constant (GET_MODE (reg), reg, ofst);
10101 	  /* This cselib_add_permanent_equiv call needs to be done before
10102 	     the other cselib_add_permanent_equiv a few lines later,
10103 	     because after that one is done, cselib_lookup on this expr
10104 	     will due to the cselib SP_DERIVED_VALUE_P optimizations
10105 	     return valsp and so no permanent equivalency will be added.  */
10106 	  cselib_add_permanent_equiv (valsp, expr, get_insns ());
10107 	}
10108 
10109       expr = plus_constant (GET_MODE (stack_pointer_rtx),
10110 			    stack_pointer_rtx, -ofst);
10111       cselib_add_permanent_equiv (val, expr, get_insns ());
10112     }
10113 
10114   /* In order to factor out the adjustments made to the stack pointer or to
10115      the hard frame pointer and thus be able to use DW_OP_fbreg operations
10116      instead of individual location lists, we're going to rewrite MEMs based
10117      on them into MEMs based on the CFA by de-eliminating stack_pointer_rtx
10118      or hard_frame_pointer_rtx to the virtual CFA pointer frame_pointer_rtx
10119      resp. arg_pointer_rtx.  We can do this either when there is no frame
10120      pointer in the function and stack adjustments are consistent for all
10121      basic blocks or when there is a frame pointer and no stack realignment.
10122      But we first have to check that frame_pointer_rtx resp. arg_pointer_rtx
10123      has been eliminated.  */
10124   if (!frame_pointer_needed)
10125     {
10126       rtx reg, elim;
10127 
10128       if (!vt_stack_adjustments ())
10129 	return false;
10130 
10131 #ifdef FRAME_POINTER_CFA_OFFSET
10132       reg = frame_pointer_rtx;
10133 #else
10134       reg = arg_pointer_rtx;
10135 #endif
10136       elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
10137       if (elim != reg)
10138 	{
10139 	  if (GET_CODE (elim) == PLUS)
10140 	    elim = XEXP (elim, 0);
10141 	  if (elim == stack_pointer_rtx)
10142 	    vt_init_cfa_base ();
10143 	}
10144     }
10145   else if (!crtl->stack_realign_tried)
10146     {
10147       rtx reg, elim;
10148 
10149 #ifdef FRAME_POINTER_CFA_OFFSET
10150       reg = frame_pointer_rtx;
10151       fp_cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
10152 #else
10153       reg = arg_pointer_rtx;
10154       fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
10155 #endif
10156       elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
10157       if (elim != reg)
10158 	{
10159 	  if (GET_CODE (elim) == PLUS)
10160 	    {
10161 	      fp_cfa_offset -= rtx_to_poly_int64 (XEXP (elim, 1));
10162 	      elim = XEXP (elim, 0);
10163 	    }
10164 	  if (elim != hard_frame_pointer_rtx)
10165 	    fp_cfa_offset = -1;
10166 	}
10167       else
10168 	fp_cfa_offset = -1;
10169     }
10170 
10171   /* If the stack is realigned and a DRAP register is used, we're going to
10172      rewrite MEMs based on it representing incoming locations of parameters
10173      passed on the stack into MEMs based on the argument pointer.  Although
10174      we aren't going to rewrite other MEMs, we still need to initialize the
10175      virtual CFA pointer in order to ensure that the argument pointer will
10176      be seen as a constant throughout the function.
10177 
10178      ??? This doesn't work if FRAME_POINTER_CFA_OFFSET is defined.  */
10179   else if (stack_realign_drap)
10180     {
10181       rtx reg, elim;
10182 
10183 #ifdef FRAME_POINTER_CFA_OFFSET
10184       reg = frame_pointer_rtx;
10185 #else
10186       reg = arg_pointer_rtx;
10187 #endif
10188       elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
10189       if (elim != reg)
10190 	{
10191 	  if (GET_CODE (elim) == PLUS)
10192 	    elim = XEXP (elim, 0);
10193 	  if (elim == hard_frame_pointer_rtx)
10194 	    vt_init_cfa_base ();
10195 	}
10196     }
10197 
10198   hard_frame_pointer_adjustment = -1;
10199 
10200   vt_add_function_parameters ();
10201 
10202   bool record_sp_value = false;
10203   FOR_EACH_BB_FN (bb, cfun)
10204     {
10205       rtx_insn *insn;
10206       basic_block first_bb, last_bb;
10207 
10208       if (MAY_HAVE_DEBUG_BIND_INSNS)
10209 	{
10210 	  cselib_record_sets_hook = add_with_sets;
10211 	  if (dump_file && (dump_flags & TDF_DETAILS))
10212 	    fprintf (dump_file, "first value: %i\n",
10213 		     cselib_get_next_uid ());
10214 	}
10215 
10216       if (MAY_HAVE_DEBUG_BIND_INSNS
10217 	  && cfa_base_rtx
10218 	  && !frame_pointer_needed
10219 	  && record_sp_value)
10220 	cselib_record_sp_cfa_base_equiv (-cfa_base_offset
10221 					 - VTI (bb)->in.stack_adjust,
10222 					 BB_HEAD (bb));
10223       record_sp_value = true;
10224 
10225       first_bb = bb;
10226       for (;;)
10227 	{
10228 	  edge e;
10229 	  if (bb->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
10230 	      || ! single_pred_p (bb->next_bb))
10231 	    break;
10232 	  e = find_edge (bb, bb->next_bb);
10233 	  if (! e || (e->flags & EDGE_FALLTHRU) == 0)
10234 	    break;
10235 	  bb = bb->next_bb;
10236 	}
10237       last_bb = bb;
10238 
10239       /* Add the micro-operations to the vector.  */
10240       FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb)
10241 	{
10242 	  HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
10243 	  VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
10244 
10245 	  rtx_insn *next;
10246 	  FOR_BB_INSNS_SAFE (bb, insn, next)
10247 	    {
10248 	      if (INSN_P (insn))
10249 		{
10250 		  HOST_WIDE_INT pre = 0, post = 0;
10251 
10252 		  if (!frame_pointer_needed)
10253 		    {
10254 		      insn_stack_adjust_offset_pre_post (insn, &pre, &post);
10255 		      if (pre)
10256 			{
10257 			  micro_operation mo;
10258 			  mo.type = MO_ADJUST;
10259 			  mo.u.adjust = pre;
10260 			  mo.insn = insn;
10261 			  if (dump_file && (dump_flags & TDF_DETAILS))
10262 			    log_op_type (PATTERN (insn), bb, insn,
10263 					 MO_ADJUST, dump_file);
10264 			  VTI (bb)->mos.safe_push (mo);
10265 			}
10266 		    }
10267 
10268 		  cselib_hook_called = false;
10269 		  adjust_insn (bb, insn);
10270 
10271 		  if (pre)
10272 		    VTI (bb)->out.stack_adjust += pre;
10273 
10274 		  if (DEBUG_MARKER_INSN_P (insn))
10275 		    {
10276 		      reemit_marker_as_note (insn);
10277 		      continue;
10278 		    }
10279 
10280 		  if (MAY_HAVE_DEBUG_BIND_INSNS)
10281 		    {
10282 		      if (CALL_P (insn))
10283 			prepare_call_arguments (bb, insn);
10284 		      cselib_process_insn (insn);
10285 		      if (dump_file && (dump_flags & TDF_DETAILS))
10286 			{
10287 			  if (dump_flags & TDF_SLIM)
10288 			    dump_insn_slim (dump_file, insn);
10289 			  else
10290 			    print_rtl_single (dump_file, insn);
10291 			  dump_cselib_table (dump_file);
10292 			}
10293 		    }
10294 		  if (!cselib_hook_called)
10295 		    add_with_sets (insn, 0, 0);
10296 		  cancel_changes (0);
10297 
10298 		  if (post)
10299 		    {
10300 		      micro_operation mo;
10301 		      mo.type = MO_ADJUST;
10302 		      mo.u.adjust = post;
10303 		      mo.insn = insn;
10304 		      if (dump_file && (dump_flags & TDF_DETAILS))
10305 			log_op_type (PATTERN (insn), bb, insn,
10306 				     MO_ADJUST, dump_file);
10307 		      VTI (bb)->mos.safe_push (mo);
10308 		      VTI (bb)->out.stack_adjust += post;
10309 		    }
10310 
10311 		  if (maybe_ne (fp_cfa_offset, -1)
10312 		      && known_eq (hard_frame_pointer_adjustment, -1)
10313 		      && fp_setter_insn (insn))
10314 		    {
10315 		      vt_init_cfa_base ();
10316 		      hard_frame_pointer_adjustment = fp_cfa_offset;
10317 		      /* Disassociate sp from fp now.  */
10318 		      if (MAY_HAVE_DEBUG_BIND_INSNS)
10319 			{
10320 			  cselib_val *v;
10321 			  cselib_invalidate_rtx (stack_pointer_rtx);
10322 			  v = cselib_lookup (stack_pointer_rtx, Pmode, 1,
10323 					     VOIDmode);
10324 			  if (v && !cselib_preserved_value_p (v))
10325 			    {
10326 			      cselib_set_value_sp_based (v);
10327 			      preserve_value (v);
10328 			    }
10329 			}
10330 		    }
10331 		}
10332 	    }
10333 	  gcc_assert (offset == VTI (bb)->out.stack_adjust);
10334 	}
10335 
10336       bb = last_bb;
10337 
10338       if (MAY_HAVE_DEBUG_BIND_INSNS)
10339 	{
10340 	  cselib_preserve_only_values ();
10341 	  cselib_reset_table (cselib_get_next_uid ());
10342 	  cselib_record_sets_hook = NULL;
10343 	}
10344     }
10345 
10346   hard_frame_pointer_adjustment = -1;
10347   VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->flooded = true;
10348   cfa_base_rtx = NULL_RTX;
10349   return true;
10350 }
10351 
10352 /* This is *not* reset after each function.  It gives each
10353    NOTE_INSN_DELETED_DEBUG_LABEL in the entire compilation
10354    a unique label number.  */
10355 
10356 static int debug_label_num = 1;
10357 
10358 /* Remove from the insn stream a single debug insn used for
10359    variable tracking at assignments.  */
10360 
10361 static inline void
delete_vta_debug_insn(rtx_insn * insn)10362 delete_vta_debug_insn (rtx_insn *insn)
10363 {
10364   if (DEBUG_MARKER_INSN_P (insn))
10365     {
10366       reemit_marker_as_note (insn);
10367       return;
10368     }
10369 
10370   tree decl = INSN_VAR_LOCATION_DECL (insn);
10371   if (TREE_CODE (decl) == LABEL_DECL
10372       && DECL_NAME (decl)
10373       && !DECL_RTL_SET_P (decl))
10374     {
10375       PUT_CODE (insn, NOTE);
10376       NOTE_KIND (insn) = NOTE_INSN_DELETED_DEBUG_LABEL;
10377       NOTE_DELETED_LABEL_NAME (insn)
10378 	= IDENTIFIER_POINTER (DECL_NAME (decl));
10379       SET_DECL_RTL (decl, insn);
10380       CODE_LABEL_NUMBER (insn) = debug_label_num++;
10381     }
10382   else
10383     delete_insn (insn);
10384 }
10385 
10386 /* Remove from the insn stream all debug insns used for variable
10387    tracking at assignments.  USE_CFG should be false if the cfg is no
10388    longer usable.  */
10389 
10390 void
delete_vta_debug_insns(bool use_cfg)10391 delete_vta_debug_insns (bool use_cfg)
10392 {
10393   basic_block bb;
10394   rtx_insn *insn, *next;
10395 
10396   if (!MAY_HAVE_DEBUG_INSNS)
10397     return;
10398 
10399   if (use_cfg)
10400     FOR_EACH_BB_FN (bb, cfun)
10401       {
10402 	FOR_BB_INSNS_SAFE (bb, insn, next)
10403 	  if (DEBUG_INSN_P (insn))
10404 	    delete_vta_debug_insn (insn);
10405       }
10406   else
10407     for (insn = get_insns (); insn; insn = next)
10408       {
10409 	next = NEXT_INSN (insn);
10410 	if (DEBUG_INSN_P (insn))
10411 	  delete_vta_debug_insn (insn);
10412       }
10413 }
10414 
10415 /* Run a fast, BB-local only version of var tracking, to take care of
10416    information that we don't do global analysis on, such that not all
10417    information is lost.  If SKIPPED holds, we're skipping the global
10418    pass entirely, so we should try to use information it would have
10419    handled as well..  */
10420 
10421 static void
vt_debug_insns_local(bool skipped ATTRIBUTE_UNUSED)10422 vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
10423 {
10424   /* ??? Just skip it all for now.  */
10425   delete_vta_debug_insns (true);
10426 }
10427 
10428 /* Free the data structures needed for variable tracking.  */
10429 
10430 static void
vt_finalize(void)10431 vt_finalize (void)
10432 {
10433   basic_block bb;
10434 
10435   FOR_EACH_BB_FN (bb, cfun)
10436     {
10437       VTI (bb)->mos.release ();
10438     }
10439 
10440   FOR_ALL_BB_FN (bb, cfun)
10441     {
10442       dataflow_set_destroy (&VTI (bb)->in);
10443       dataflow_set_destroy (&VTI (bb)->out);
10444       if (VTI (bb)->permp)
10445 	{
10446 	  dataflow_set_destroy (VTI (bb)->permp);
10447 	  XDELETE (VTI (bb)->permp);
10448 	}
10449     }
10450   free_aux_for_blocks ();
10451   delete empty_shared_hash->htab;
10452   empty_shared_hash->htab = NULL;
10453   delete changed_variables;
10454   changed_variables = NULL;
10455   attrs_pool.release ();
10456   var_pool.release ();
10457   location_chain_pool.release ();
10458   shared_hash_pool.release ();
10459 
10460   if (MAY_HAVE_DEBUG_BIND_INSNS)
10461     {
10462       if (global_get_addr_cache)
10463 	delete global_get_addr_cache;
10464       global_get_addr_cache = NULL;
10465       loc_exp_dep_pool.release ();
10466       valvar_pool.release ();
10467       preserved_values.release ();
10468       cselib_finish ();
10469       BITMAP_FREE (scratch_regs);
10470       scratch_regs = NULL;
10471     }
10472 
10473 #ifdef HAVE_window_save
10474   vec_free (windowed_parm_regs);
10475 #endif
10476 
10477   if (vui_vec)
10478     XDELETEVEC (vui_vec);
10479   vui_vec = NULL;
10480   vui_allocated = 0;
10481 }
10482 
10483 /* The entry point to variable tracking pass.  */
10484 
10485 static inline unsigned int
variable_tracking_main_1(void)10486 variable_tracking_main_1 (void)
10487 {
10488   bool success;
10489 
10490   /* We won't be called as a separate pass if flag_var_tracking is not
10491      set, but final may call us to turn debug markers into notes.  */
10492   if ((!flag_var_tracking && MAY_HAVE_DEBUG_INSNS)
10493       || flag_var_tracking_assignments < 0
10494       /* Var-tracking right now assumes the IR doesn't contain
10495 	 any pseudos at this point.  */
10496       || targetm.no_register_allocation)
10497     {
10498       delete_vta_debug_insns (true);
10499       return 0;
10500     }
10501 
10502   if (!flag_var_tracking)
10503     return 0;
10504 
10505   if (n_basic_blocks_for_fn (cfun) > 500
10506       && n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun) >= 20)
10507     {
10508       vt_debug_insns_local (true);
10509       return 0;
10510     }
10511 
10512   if (!vt_initialize ())
10513     {
10514       vt_finalize ();
10515       vt_debug_insns_local (true);
10516       return 0;
10517     }
10518 
10519   success = vt_find_locations ();
10520 
10521   if (!success && flag_var_tracking_assignments > 0)
10522     {
10523       vt_finalize ();
10524 
10525       delete_vta_debug_insns (true);
10526 
10527       /* This is later restored by our caller.  */
10528       flag_var_tracking_assignments = 0;
10529 
10530       success = vt_initialize ();
10531       gcc_assert (success);
10532 
10533       success = vt_find_locations ();
10534     }
10535 
10536   if (!success)
10537     {
10538       vt_finalize ();
10539       vt_debug_insns_local (false);
10540       return 0;
10541     }
10542 
10543   if (dump_file && (dump_flags & TDF_DETAILS))
10544     {
10545       dump_dataflow_sets ();
10546       dump_reg_info (dump_file);
10547       dump_flow_info (dump_file, dump_flags);
10548     }
10549 
10550   timevar_push (TV_VAR_TRACKING_EMIT);
10551   vt_emit_notes ();
10552   timevar_pop (TV_VAR_TRACKING_EMIT);
10553 
10554   vt_finalize ();
10555   vt_debug_insns_local (false);
10556   return 0;
10557 }
10558 
10559 unsigned int
variable_tracking_main(void)10560 variable_tracking_main (void)
10561 {
10562   unsigned int ret;
10563   int save = flag_var_tracking_assignments;
10564 
10565   ret = variable_tracking_main_1 ();
10566 
10567   flag_var_tracking_assignments = save;
10568 
10569   return ret;
10570 }
10571 
10572 namespace {
10573 
10574 const pass_data pass_data_variable_tracking =
10575 {
10576   RTL_PASS, /* type */
10577   "vartrack", /* name */
10578   OPTGROUP_NONE, /* optinfo_flags */
10579   TV_VAR_TRACKING, /* tv_id */
10580   0, /* properties_required */
10581   0, /* properties_provided */
10582   0, /* properties_destroyed */
10583   0, /* todo_flags_start */
10584   0, /* todo_flags_finish */
10585 };
10586 
10587 class pass_variable_tracking : public rtl_opt_pass
10588 {
10589 public:
pass_variable_tracking(gcc::context * ctxt)10590   pass_variable_tracking (gcc::context *ctxt)
10591     : rtl_opt_pass (pass_data_variable_tracking, ctxt)
10592   {}
10593 
10594   /* opt_pass methods: */
gate(function *)10595   virtual bool gate (function *)
10596     {
10597       return (flag_var_tracking && !targetm.delay_vartrack);
10598     }
10599 
execute(function *)10600   virtual unsigned int execute (function *)
10601     {
10602       return variable_tracking_main ();
10603     }
10604 
10605 }; // class pass_variable_tracking
10606 
10607 } // anon namespace
10608 
10609 rtl_opt_pass *
make_pass_variable_tracking(gcc::context * ctxt)10610 make_pass_variable_tracking (gcc::context *ctxt)
10611 {
10612   return new pass_variable_tracking (ctxt);
10613 }
10614