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