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