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