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