]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/var-tracking.c
tm.texi (TARGET_ADDR_SPACE_POINTER_MODE): Document.
[thirdparty/gcc.git] / gcc / var-tracking.c
CommitLineData
014a1138 1/* Variable tracking routines for the GNU compiler.
32e8bb8e 2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
66647d44 3 Free Software Foundation, Inc.
014a1138
JZ
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9dcd6f09 9 the Free Software Foundation; either version 3, or (at your option)
014a1138
JZ
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
9dcd6f09
NC
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
014a1138
JZ
20
21/* This file contains the variable tracking pass. It computes where
22 variables are located (which registers or where in memory) at each position
23 in instruction stream and emits notes describing the locations.
24 Debug information (DWARF2 location lists) is finally generated from
25 these notes.
26 With this debug information, it is possible to show variables
27 even when debugging optimized code.
28
29 How does the variable tracking pass work?
30
31 First, it scans RTL code for uses, stores and clobbers (register/memory
32 references in instructions), for call insns and for stack adjustments
33 separately for each basic block and saves them to an array of micro
34 operations.
35 The micro operations of one instruction are ordered so that
36 pre-modifying stack adjustment < use < use with no var < call insn <
37 < set < clobber < post-modifying stack adjustment
38
39 Then, a forward dataflow analysis is performed to find out how locations
40 of variables change through code and to propagate the variable locations
41 along control flow graph.
42 The IN set for basic block BB is computed as a union of OUT sets of BB's
43 predecessors, the OUT set for BB is copied from the IN set for BB and
44 is changed according to micro operations in BB.
45
46 The IN and OUT sets for basic blocks consist of a current stack adjustment
47 (used for adjusting offset of variables addressed using stack pointer),
48 the table of structures describing the locations of parts of a variable
49 and for each physical register a linked list for each physical register.
50 The linked list is a list of variable parts stored in the register,
51 i.e. it is a list of triplets (reg, decl, offset) where decl is
52 REG_EXPR (reg) and offset is REG_OFFSET (reg). The linked list is used for
53 effective deleting appropriate variable parts when we set or clobber the
54 register.
55
56 There may be more than one variable part in a register. The linked lists
57 should be pretty short so it is a good data structure here.
58 For example in the following code, register allocator may assign same
59 register to variables A and B, and both of them are stored in the same
60 register in CODE:
61
62 if (cond)
63 set A;
64 else
65 set B;
66 CODE;
67 if (cond)
68 use A;
69 else
70 use B;
71
72 Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
73 are emitted to appropriate positions in RTL code. Each such a note describes
74 the location of one variable at the point in instruction stream where the
75 note is. There is no need to emit a note for each variable before each
76 instruction, we only emit these notes where the location of variable changes
77 (this means that we also emit notes for changes between the OUT set of the
78 previous block and the IN set of the current block).
79
80 The notes consist of two parts:
81 1. the declaration (from REG_EXPR or MEM_EXPR)
82 2. the location of a variable - it is either a simple register/memory
83 reference (for simple variables, for example int),
84 or a parallel of register/memory references (for a large variables
85 which consist of several parts, for example long long).
86
87*/
88
89#include "config.h"
90#include "system.h"
91#include "coretypes.h"
92#include "tm.h"
93#include "rtl.h"
94#include "tree.h"
95#include "hard-reg-set.h"
96#include "basic-block.h"
97#include "flags.h"
98#include "output.h"
99#include "insn-config.h"
100#include "reload.h"
101#include "sbitmap.h"
102#include "alloc-pool.h"
103#include "fibheap.h"
104#include "hashtab.h"
c938250d
JJ
105#include "regs.h"
106#include "expr.h"
ef330312
PB
107#include "timevar.h"
108#include "tree-pass.h"
b5b8b0ac
AO
109#include "cselib.h"
110#include "target.h"
014a1138
JZ
111
112/* Type of micro operation. */
113enum micro_operation_type
114{
115 MO_USE, /* Use location (REG or MEM). */
116 MO_USE_NO_VAR,/* Use location which is not associated with a variable
117 or the variable is not trackable. */
b5b8b0ac
AO
118 MO_VAL_USE, /* Use location which is associated with a value. */
119 MO_VAL_LOC, /* Use location which appears in a debug insn. */
120 MO_VAL_SET, /* Set location associated with a value. */
014a1138 121 MO_SET, /* Set location. */
ca787200 122 MO_COPY, /* Copy the same portion of a variable from one
96ff6c8c 123 location to another. */
014a1138
JZ
124 MO_CLOBBER, /* Clobber location. */
125 MO_CALL, /* Call insn. */
9ac97460 126 MO_ADJUST /* Adjust stack pointer. */
b5b8b0ac
AO
127
128};
129
130static const char * const ATTRIBUTE_UNUSED
131micro_operation_type_name[] = {
132 "MO_USE",
133 "MO_USE_NO_VAR",
134 "MO_VAL_USE",
135 "MO_VAL_LOC",
136 "MO_VAL_SET",
137 "MO_SET",
138 "MO_COPY",
139 "MO_CLOBBER",
140 "MO_CALL",
141 "MO_ADJUST"
014a1138
JZ
142};
143
b5b8b0ac
AO
144/* Where shall the note be emitted? BEFORE or AFTER the instruction.
145 Notes emitted as AFTER_CALL are to take effect during the call,
146 rather than after the call. */
014a1138
JZ
147enum emit_note_where
148{
149 EMIT_NOTE_BEFORE_INSN,
b5b8b0ac
AO
150 EMIT_NOTE_AFTER_INSN,
151 EMIT_NOTE_AFTER_CALL_INSN
014a1138
JZ
152};
153
154/* Structure holding information about micro operation. */
155typedef struct micro_operation_def
156{
157 /* Type of micro operation. */
158 enum micro_operation_type type;
159
160 union {
b5b8b0ac
AO
161 /* Location. For MO_SET and MO_COPY, this is the SET that
162 performs the assignment, if known, otherwise it is the target
163 of the assignment. For MO_VAL_USE and MO_VAL_SET, it is a
164 CONCAT of the VALUE and the LOC associated with it. For
165 MO_VAL_LOC, it is a CONCAT of the VALUE and the VAR_LOCATION
166 associated with it. */
014a1138
JZ
167 rtx loc;
168
169 /* Stack adjustment. */
170 HOST_WIDE_INT adjust;
171 } u;
172
dedc1e6d
AO
173 /* The instruction which the micro operation is in, for MO_USE,
174 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
175 instruction or note in the original flow (before any var-tracking
176 notes are inserted, to simplify emission of notes), for MO_SET
177 and MO_CLOBBER. */
014a1138
JZ
178 rtx insn;
179} micro_operation;
180
b5b8b0ac
AO
181/* A declaration of a variable, or an RTL value being handled like a
182 declaration. */
183typedef void *decl_or_value;
184
014a1138
JZ
185/* Structure for passing some other parameters to function
186 emit_note_insn_var_location. */
187typedef struct emit_note_data_def
188{
189 /* The instruction which the note will be emitted before/after. */
190 rtx insn;
191
192 /* Where the note will be emitted (before/after insn)? */
193 enum emit_note_where where;
b5b8b0ac
AO
194
195 /* The variables and values active at this point. */
196 htab_t vars;
014a1138
JZ
197} emit_note_data;
198
199/* Description of location of a part of a variable. The content of a physical
200 register is described by a chain of these structures.
201 The chains are pretty short (usually 1 or 2 elements) and thus
202 chain is the best data structure. */
203typedef struct attrs_def
204{
205 /* Pointer to next member of the list. */
206 struct attrs_def *next;
207
208 /* The rtx of register. */
209 rtx loc;
210
211 /* The declaration corresponding to LOC. */
b5b8b0ac 212 decl_or_value dv;
014a1138
JZ
213
214 /* Offset from start of DECL. */
215 HOST_WIDE_INT offset;
216} *attrs;
217
d24686d7
JJ
218/* Structure holding a refcounted hash table. If refcount > 1,
219 it must be first unshared before modified. */
220typedef struct shared_hash_def
221{
222 /* Reference count. */
223 int refcount;
224
225 /* Actual hash table. */
226 htab_t htab;
227} *shared_hash;
228
014a1138
JZ
229/* Structure holding the IN or OUT set for a basic block. */
230typedef struct dataflow_set_def
231{
232 /* Adjustment of stack offset. */
233 HOST_WIDE_INT stack_adjust;
234
235 /* Attributes for registers (lists of attrs). */
236 attrs regs[FIRST_PSEUDO_REGISTER];
237
238 /* Variable locations. */
d24686d7 239 shared_hash vars;
b5b8b0ac
AO
240
241 /* Vars that is being traversed. */
242 shared_hash traversed_vars;
014a1138
JZ
243} dataflow_set;
244
245/* The structure (one for each basic block) containing the information
246 needed for variable tracking. */
247typedef struct variable_tracking_info_def
248{
249 /* Number of micro operations stored in the MOS array. */
250 int n_mos;
251
252 /* The array of micro operations. */
253 micro_operation *mos;
254
255 /* The IN and OUT set for dataflow analysis. */
256 dataflow_set in;
257 dataflow_set out;
258
b5b8b0ac
AO
259 /* The permanent-in dataflow set for this block. This is used to
260 hold values for which we had to compute entry values. ??? This
261 should probably be dynamically allocated, to avoid using more
262 memory in non-debug builds. */
263 dataflow_set *permp;
264
014a1138
JZ
265 /* Has the block been visited in DFS? */
266 bool visited;
b5b8b0ac
AO
267
268 /* Has the block been flooded in VTA? */
269 bool flooded;
270
014a1138
JZ
271} *variable_tracking_info;
272
273/* Structure for chaining the locations. */
274typedef struct location_chain_def
275{
276 /* Next element in the chain. */
277 struct location_chain_def *next;
278
b5b8b0ac 279 /* The location (REG, MEM or VALUE). */
014a1138 280 rtx loc;
62760ffd
CT
281
282 /* The "value" stored in this location. */
283 rtx set_src;
284
285 /* Initialized? */
286 enum var_init_status init;
014a1138
JZ
287} *location_chain;
288
289/* Structure describing one part of variable. */
290typedef struct variable_part_def
291{
292 /* Chain of locations of the part. */
293 location_chain loc_chain;
294
295 /* Location which was last emitted to location list. */
296 rtx cur_loc;
297
298 /* The offset in the variable. */
299 HOST_WIDE_INT offset;
300} variable_part;
301
302/* Maximum number of location parts. */
303#define MAX_VAR_PARTS 16
304
305/* Structure describing where the variable is located. */
306typedef struct variable_def
307{
b5b8b0ac
AO
308 /* The declaration of the variable, or an RTL value being handled
309 like a declaration. */
310 decl_or_value dv;
014a1138 311
81f2eadb
JZ
312 /* Reference count. */
313 int refcount;
314
014a1138
JZ
315 /* Number of variable parts. */
316 int n_var_parts;
317
318 /* The variable parts. */
b5b8b0ac 319 variable_part var_part[1];
014a1138 320} *variable;
741ac903 321typedef const struct variable_def *const_variable;
014a1138 322
b5b8b0ac
AO
323/* Structure for chaining backlinks from referenced VALUEs to
324 DVs that are referencing them. */
325typedef struct value_chain_def
326{
327 /* Next value_chain entry. */
328 struct value_chain_def *next;
329
330 /* The declaration of the variable, or an RTL value
331 being handled like a declaration, whose var_parts[0].loc_chain
332 references the VALUE owning this value_chain. */
333 decl_or_value dv;
334
335 /* Reference count. */
336 int refcount;
337} *value_chain;
338typedef const struct value_chain_def *const_value_chain;
339
014a1138 340/* Hash function for DECL for VARIABLE_HTAB. */
ac3bfd86 341#define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
014a1138
JZ
342
343/* Pointer to the BB's information specific to variable tracking pass. */
344#define VTI(BB) ((variable_tracking_info) (BB)->aux)
345
8c6c36a3
EB
346/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
347#define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
348
014a1138
JZ
349/* Alloc pool for struct attrs_def. */
350static alloc_pool attrs_pool;
351
b5b8b0ac 352/* Alloc pool for struct variable_def with MAX_VAR_PARTS entries. */
014a1138
JZ
353static alloc_pool var_pool;
354
b5b8b0ac
AO
355/* Alloc pool for struct variable_def with a single var_part entry. */
356static alloc_pool valvar_pool;
357
014a1138
JZ
358/* Alloc pool for struct location_chain_def. */
359static alloc_pool loc_chain_pool;
360
d24686d7
JJ
361/* Alloc pool for struct shared_hash_def. */
362static alloc_pool shared_hash_pool;
363
b5b8b0ac
AO
364/* Alloc pool for struct value_chain_def. */
365static alloc_pool value_chain_pool;
366
014a1138
JZ
367/* Changed variables, notes will be emitted for them. */
368static htab_t changed_variables;
369
b5b8b0ac
AO
370/* Links from VALUEs to DVs referencing them in their current loc_chains. */
371static htab_t value_chains;
372
014a1138
JZ
373/* Shall notes be emitted? */
374static bool emit_notes;
375
d24686d7
JJ
376/* Empty shared hashtable. */
377static shared_hash empty_shared_hash;
378
b5b8b0ac
AO
379/* Scratch register bitmap used by cselib_expand_value_rtx. */
380static bitmap scratch_regs = NULL;
381
382/* Variable used to tell whether cselib_process_insn called our hook. */
383static bool cselib_hook_called;
384
014a1138
JZ
385/* Local function prototypes. */
386static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
387 HOST_WIDE_INT *);
388static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
389 HOST_WIDE_INT *);
390static void bb_stack_adjust_offset (basic_block);
014a1138
JZ
391static bool vt_stack_adjustments (void);
392static rtx adjust_stack_reference (rtx, HOST_WIDE_INT);
393static hashval_t variable_htab_hash (const void *);
394static int variable_htab_eq (const void *, const void *);
395static void variable_htab_free (void *);
396
397static void init_attrs_list_set (attrs *);
398static void attrs_list_clear (attrs *);
b5b8b0ac
AO
399static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
400static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
014a1138
JZ
401static void attrs_list_copy (attrs *, attrs);
402static void attrs_list_union (attrs *, attrs);
403
b5b8b0ac
AO
404static void **unshare_variable (dataflow_set *set, void **slot, variable var,
405 enum var_init_status);
014a1138
JZ
406static int vars_copy_1 (void **, void *);
407static void vars_copy (htab_t, htab_t);
ca787200 408static tree var_debug_decl (tree);
62760ffd
CT
409static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
410static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
411 enum var_init_status, rtx);
ca787200 412static void var_reg_delete (dataflow_set *, rtx, bool);
014a1138 413static void var_regno_delete (dataflow_set *, int);
62760ffd
CT
414static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
415static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
416 enum var_init_status, rtx);
ca787200 417static void var_mem_delete (dataflow_set *, rtx, bool);
014a1138 418
d24686d7 419static void dataflow_set_init (dataflow_set *);
014a1138
JZ
420static void dataflow_set_clear (dataflow_set *);
421static void dataflow_set_copy (dataflow_set *, dataflow_set *);
422static int variable_union_info_cmp_pos (const void *, const void *);
423static int variable_union (void **, void *);
d24686d7 424static int variable_canonicalize (void **, void *);
014a1138 425static void dataflow_set_union (dataflow_set *, dataflow_set *);
b5b8b0ac
AO
426static location_chain find_loc_in_1pdv (rtx, variable, htab_t);
427static bool canon_value_cmp (rtx, rtx);
428static int loc_cmp (rtx, rtx);
014a1138 429static bool variable_part_different_p (variable_part *, variable_part *);
b5b8b0ac 430static bool onepart_variable_different_p (variable, variable);
83532fb7 431static bool variable_different_p (variable, variable, bool);
014a1138 432static int dataflow_set_different_1 (void **, void *);
014a1138
JZ
433static bool dataflow_set_different (dataflow_set *, dataflow_set *);
434static void dataflow_set_destroy (dataflow_set *);
435
436static bool contains_symbol_ref (rtx);
b5b8b0ac 437static bool track_expr_p (tree, bool);
ca787200 438static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
014a1138
JZ
439static int count_uses (rtx *, void *);
440static void count_uses_1 (rtx *, void *);
7bc980e1 441static void count_stores (rtx, const_rtx, void *);
014a1138
JZ
442static int add_uses (rtx *, void *);
443static void add_uses_1 (rtx *, void *);
7bc980e1 444static void add_stores (rtx, const_rtx, void *);
014a1138
JZ
445static bool compute_bb_dataflow (basic_block);
446static void vt_find_locations (void);
447
448static void dump_attrs_list (attrs);
b5b8b0ac
AO
449static int dump_variable_slot (void **, void *);
450static void dump_variable (variable);
014a1138
JZ
451static void dump_vars (htab_t);
452static void dump_dataflow_set (dataflow_set *);
453static void dump_dataflow_sets (void);
454
d24686d7 455static void variable_was_changed (variable, dataflow_set *);
b5b8b0ac
AO
456static void **set_slot_part (dataflow_set *, rtx, void **,
457 decl_or_value, HOST_WIDE_INT,
458 enum var_init_status, rtx);
459static void set_variable_part (dataflow_set *, rtx,
460 decl_or_value, HOST_WIDE_INT,
461 enum var_init_status, rtx, enum insert_option);
462static void **clobber_slot_part (dataflow_set *, rtx,
463 void **, HOST_WIDE_INT, rtx);
464static void clobber_variable_part (dataflow_set *, rtx,
465 decl_or_value, HOST_WIDE_INT, rtx);
466static void **delete_slot_part (dataflow_set *, rtx, void **, HOST_WIDE_INT);
467static void delete_variable_part (dataflow_set *, rtx,
468 decl_or_value, HOST_WIDE_INT);
014a1138 469static int emit_note_insn_var_location (void **, void *);
b5b8b0ac 470static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash);
014a1138
JZ
471static int emit_notes_for_differences_1 (void **, void *);
472static int emit_notes_for_differences_2 (void **, void *);
473static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
b5b8b0ac 474static void emit_notes_in_bb (basic_block, dataflow_set *);
014a1138
JZ
475static void vt_emit_notes (void);
476
477static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
478static void vt_add_function_parameters (void);
479static void vt_initialize (void);
480static void vt_finalize (void);
481
482/* Given a SET, calculate the amount of stack adjustment it contains
483 PRE- and POST-modifying stack pointer.
484 This function is similar to stack_adjust_offset. */
485
486static void
487stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
488 HOST_WIDE_INT *post)
489{
490 rtx src = SET_SRC (pattern);
491 rtx dest = SET_DEST (pattern);
492 enum rtx_code code;
493
494 if (dest == stack_pointer_rtx)
495 {
496 /* (set (reg sp) (plus (reg sp) (const_int))) */
497 code = GET_CODE (src);
498 if (! (code == PLUS || code == MINUS)
499 || XEXP (src, 0) != stack_pointer_rtx
481683e1 500 || !CONST_INT_P (XEXP (src, 1)))
014a1138
JZ
501 return;
502
503 if (code == MINUS)
504 *post += INTVAL (XEXP (src, 1));
505 else
506 *post -= INTVAL (XEXP (src, 1));
507 }
3c0cb5de 508 else if (MEM_P (dest))
014a1138
JZ
509 {
510 /* (set (mem (pre_dec (reg sp))) (foo)) */
511 src = XEXP (dest, 0);
512 code = GET_CODE (src);
513
514 switch (code)
515 {
516 case PRE_MODIFY:
517 case POST_MODIFY:
518 if (XEXP (src, 0) == stack_pointer_rtx)
519 {
520 rtx val = XEXP (XEXP (src, 1), 1);
521 /* We handle only adjustments by constant amount. */
fbc848cc 522 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
481683e1 523 CONST_INT_P (val));
fbc848cc 524
014a1138
JZ
525 if (code == PRE_MODIFY)
526 *pre -= INTVAL (val);
527 else
528 *post -= INTVAL (val);
529 break;
530 }
531 return;
532
533 case PRE_DEC:
534 if (XEXP (src, 0) == stack_pointer_rtx)
535 {
536 *pre += GET_MODE_SIZE (GET_MODE (dest));
537 break;
538 }
539 return;
540
541 case POST_DEC:
542 if (XEXP (src, 0) == stack_pointer_rtx)
543 {
544 *post += GET_MODE_SIZE (GET_MODE (dest));
545 break;
546 }
547 return;
548
549 case PRE_INC:
550 if (XEXP (src, 0) == stack_pointer_rtx)
551 {
552 *pre -= GET_MODE_SIZE (GET_MODE (dest));
553 break;
554 }
555 return;
556
557 case POST_INC:
558 if (XEXP (src, 0) == stack_pointer_rtx)
559 {
560 *post -= GET_MODE_SIZE (GET_MODE (dest));
561 break;
562 }
563 return;
564
565 default:
566 return;
567 }
568 }
569}
570
571/* Given an INSN, calculate the amount of stack adjustment it contains
572 PRE- and POST-modifying stack pointer. */
573
574static void
575insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
576 HOST_WIDE_INT *post)
577{
7d407433
BW
578 rtx pattern;
579
014a1138
JZ
580 *pre = 0;
581 *post = 0;
582
7d407433
BW
583 pattern = PATTERN (insn);
584 if (RTX_FRAME_RELATED_P (insn))
585 {
586 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
587 if (expr)
588 pattern = XEXP (expr, 0);
589 }
590
591 if (GET_CODE (pattern) == SET)
592 stack_adjust_offset_pre_post (pattern, pre, post);
593 else if (GET_CODE (pattern) == PARALLEL
594 || GET_CODE (pattern) == SEQUENCE)
014a1138
JZ
595 {
596 int i;
597
598 /* There may be stack adjustments inside compound insns. Search
599 for them. */
7d407433
BW
600 for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
601 if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
602 stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
014a1138
JZ
603 }
604}
605
fb0840fc 606/* Compute stack adjustment in basic block BB. */
014a1138
JZ
607
608static void
609bb_stack_adjust_offset (basic_block bb)
610{
611 HOST_WIDE_INT offset;
612 int i;
613
614 offset = VTI (bb)->in.stack_adjust;
615 for (i = 0; i < VTI (bb)->n_mos; i++)
616 {
617 if (VTI (bb)->mos[i].type == MO_ADJUST)
618 offset += VTI (bb)->mos[i].u.adjust;
619 else if (VTI (bb)->mos[i].type != MO_CALL)
620 {
3c0cb5de 621 if (MEM_P (VTI (bb)->mos[i].u.loc))
014a1138
JZ
622 {
623 VTI (bb)->mos[i].u.loc
624 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
625 }
626 }
627 }
628 VTI (bb)->out.stack_adjust = offset;
629}
630
014a1138
JZ
631/* Compute stack adjustments for all blocks by traversing DFS tree.
632 Return true when the adjustments on all incoming edges are consistent.
f91a0beb 633 Heavily borrowed from pre_and_rev_post_order_compute. */
014a1138
JZ
634
635static bool
636vt_stack_adjustments (void)
637{
628f6a4e 638 edge_iterator *stack;
014a1138
JZ
639 int sp;
640
fb0840fc 641 /* Initialize entry block. */
014a1138 642 VTI (ENTRY_BLOCK_PTR)->visited = true;
30e6f306 643 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
014a1138
JZ
644
645 /* Allocate stack for back-tracking up CFG. */
5ed6ace5 646 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
014a1138
JZ
647 sp = 0;
648
649 /* Push the first edge on to the stack. */
628f6a4e 650 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
014a1138
JZ
651
652 while (sp)
653 {
628f6a4e 654 edge_iterator ei;
014a1138
JZ
655 basic_block src;
656 basic_block dest;
657
658 /* Look at the edge on the top of the stack. */
628f6a4e
BE
659 ei = stack[sp - 1];
660 src = ei_edge (ei)->src;
661 dest = ei_edge (ei)->dest;
014a1138
JZ
662
663 /* Check if the edge destination has been visited yet. */
664 if (!VTI (dest)->visited)
665 {
666 VTI (dest)->visited = true;
667 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
668 bb_stack_adjust_offset (dest);
669
628f6a4e 670 if (EDGE_COUNT (dest->succs) > 0)
014a1138
JZ
671 /* Since the DEST node has been visited for the first
672 time, check its successors. */
628f6a4e 673 stack[sp++] = ei_start (dest->succs);
014a1138
JZ
674 }
675 else
676 {
677 /* Check whether the adjustments on the edges are the same. */
678 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
679 {
680 free (stack);
681 return false;
682 }
683
628f6a4e 684 if (! ei_one_before_end_p (ei))
014a1138 685 /* Go to the next edge. */
628f6a4e 686 ei_next (&stack[sp - 1]);
014a1138
JZ
687 else
688 /* Return to previous level if there are no more edges. */
689 sp--;
690 }
691 }
692
693 free (stack);
694 return true;
695}
696
30e6f306
RH
697/* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
698 to the argument pointer. Return the new rtx. */
014a1138
JZ
699
700static rtx
701adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
702{
30e6f306 703 rtx addr, cfa, tmp;
014a1138 704
f6672e8e
RH
705#ifdef FRAME_POINTER_CFA_OFFSET
706 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
707 cfa = plus_constant (frame_pointer_rtx, adjustment);
708#else
30e6f306
RH
709 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
710 cfa = plus_constant (arg_pointer_rtx, adjustment);
f6672e8e 711#endif
feb61729 712
30e6f306
RH
713 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
714 tmp = simplify_rtx (addr);
014a1138 715 if (tmp)
30e6f306 716 addr = tmp;
014a1138 717
30e6f306 718 return replace_equiv_address_nv (mem, addr);
014a1138
JZ
719}
720
b5b8b0ac
AO
721/* Return true if a decl_or_value DV is a DECL or NULL. */
722static inline bool
723dv_is_decl_p (decl_or_value dv)
724{
725 if (!dv)
24277d34 726 return true;
b5b8b0ac 727
24277d34
AO
728 /* Make sure relevant codes don't overlap. */
729 switch ((int)TREE_CODE ((tree)dv))
730 {
731 case (int)VAR_DECL:
732 case (int)PARM_DECL:
733 case (int)RESULT_DECL:
734 case (int)FUNCTION_DECL:
0ca5af51 735 case (int)DEBUG_EXPR_DECL:
24277d34
AO
736 case (int)COMPONENT_REF:
737 return true;
738
739 case (int)VALUE:
740 return false;
741
742 default:
743 gcc_unreachable ();
744 }
b5b8b0ac
AO
745}
746
747/* Return true if a decl_or_value is a VALUE rtl. */
748static inline bool
749dv_is_value_p (decl_or_value dv)
750{
751 return dv && !dv_is_decl_p (dv);
752}
753
754/* Return the decl in the decl_or_value. */
755static inline tree
756dv_as_decl (decl_or_value dv)
757{
758 gcc_assert (dv_is_decl_p (dv));
759 return (tree) dv;
760}
761
762/* Return the value in the decl_or_value. */
763static inline rtx
764dv_as_value (decl_or_value dv)
765{
766 gcc_assert (dv_is_value_p (dv));
767 return (rtx)dv;
768}
769
770/* Return the opaque pointer in the decl_or_value. */
771static inline void *
772dv_as_opaque (decl_or_value dv)
773{
774 return dv;
775}
776
777/* Return true if a decl_or_value must not have more than one variable
778 part. */
779static inline bool
780dv_onepart_p (decl_or_value dv)
781{
782 tree decl;
783
784 if (!MAY_HAVE_DEBUG_INSNS)
785 return false;
786
787 if (dv_is_value_p (dv))
788 return true;
789
790 decl = dv_as_decl (dv);
791
792 if (!decl)
793 return true;
794
795 return (target_for_debug_bind (decl) != NULL_TREE);
796}
797
798/* Return the variable pool to be used for dv, depending on whether it
799 can have multiple parts or not. */
800static inline alloc_pool
801dv_pool (decl_or_value dv)
802{
803 return dv_onepart_p (dv) ? valvar_pool : var_pool;
804}
805
b5b8b0ac
AO
806/* Build a decl_or_value out of a decl. */
807static inline decl_or_value
808dv_from_decl (tree decl)
809{
810 decl_or_value dv;
b5b8b0ac 811 dv = decl;
24277d34 812 gcc_assert (dv_is_decl_p (dv));
b5b8b0ac
AO
813 return dv;
814}
815
816/* Build a decl_or_value out of a value. */
817static inline decl_or_value
818dv_from_value (rtx value)
819{
820 decl_or_value dv;
b5b8b0ac 821 dv = value;
24277d34 822 gcc_assert (dv_is_value_p (dv));
b5b8b0ac
AO
823 return dv;
824}
825
826static inline hashval_t
827dv_htab_hash (decl_or_value dv)
828{
829 if (dv_is_value_p (dv))
830 return -(hashval_t)(CSELIB_VAL_PTR (dv_as_value (dv))->value);
831 else
832 return (VARIABLE_HASH_VAL (dv_as_decl (dv)));
833}
834
014a1138
JZ
835/* The hash function for variable_htab, computes the hash value
836 from the declaration of variable X. */
837
838static hashval_t
839variable_htab_hash (const void *x)
840{
741ac903 841 const_variable const v = (const_variable) x;
014a1138 842
b5b8b0ac 843 return dv_htab_hash (v->dv);
014a1138
JZ
844}
845
846/* Compare the declaration of variable X with declaration Y. */
847
848static int
849variable_htab_eq (const void *x, const void *y)
850{
741ac903 851 const_variable const v = (const_variable) x;
b5b8b0ac
AO
852 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
853
854 if (dv_as_opaque (v->dv) == dv_as_opaque (dv))
855 return true;
856
857#if ENABLE_CHECKING
858 {
859 bool visv, dvisv;
860
861 visv = dv_is_value_p (v->dv);
862 dvisv = dv_is_value_p (dv);
863
864 if (visv != dvisv)
865 return false;
014a1138 866
b5b8b0ac
AO
867 if (visv)
868 gcc_assert (CSELIB_VAL_PTR (dv_as_value (v->dv))
869 != CSELIB_VAL_PTR (dv_as_value (dv)));
870 else
871 gcc_assert (VARIABLE_HASH_VAL (dv_as_decl (v->dv))
872 != VARIABLE_HASH_VAL (dv_as_decl (dv)));
873 }
874#endif
875
876 return false;
014a1138
JZ
877}
878
879/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
880
881static void
882variable_htab_free (void *elem)
883{
884 int i;
885 variable var = (variable) elem;
886 location_chain node, next;
887
fbc848cc 888 gcc_assert (var->refcount > 0);
81f2eadb
JZ
889
890 var->refcount--;
891 if (var->refcount > 0)
892 return;
893
014a1138
JZ
894 for (i = 0; i < var->n_var_parts; i++)
895 {
896 for (node = var->var_part[i].loc_chain; node; node = next)
897 {
898 next = node->next;
899 pool_free (loc_chain_pool, node);
900 }
901 var->var_part[i].loc_chain = NULL;
902 }
b5b8b0ac
AO
903 pool_free (dv_pool (var->dv), var);
904}
905
906/* The hash function for value_chains htab, computes the hash value
907 from the VALUE. */
908
909static hashval_t
910value_chain_htab_hash (const void *x)
911{
912 const_value_chain const v = (const_value_chain) x;
913
914 return dv_htab_hash (v->dv);
915}
916
917/* Compare the VALUE X with VALUE Y. */
918
919static int
920value_chain_htab_eq (const void *x, const void *y)
921{
922 const_value_chain const v = (const_value_chain) x;
923 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
924
925 return dv_as_opaque (v->dv) == dv_as_opaque (dv);
014a1138
JZ
926}
927
928/* Initialize the set (array) SET of attrs to empty lists. */
929
930static void
931init_attrs_list_set (attrs *set)
932{
933 int i;
934
935 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
936 set[i] = NULL;
937}
938
939/* Make the list *LISTP empty. */
940
941static void
942attrs_list_clear (attrs *listp)
943{
944 attrs list, next;
945
946 for (list = *listp; list; list = next)
947 {
948 next = list->next;
949 pool_free (attrs_pool, list);
950 }
951 *listp = NULL;
952}
953
954/* Return true if the pair of DECL and OFFSET is the member of the LIST. */
955
956static attrs
b5b8b0ac 957attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
014a1138
JZ
958{
959 for (; list; list = list->next)
b5b8b0ac 960 if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
014a1138
JZ
961 return list;
962 return NULL;
963}
964
965/* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
966
967static void
b5b8b0ac
AO
968attrs_list_insert (attrs *listp, decl_or_value dv,
969 HOST_WIDE_INT offset, rtx loc)
014a1138
JZ
970{
971 attrs list;
972
3d9a9f94 973 list = (attrs) pool_alloc (attrs_pool);
014a1138 974 list->loc = loc;
b5b8b0ac 975 list->dv = dv;
014a1138
JZ
976 list->offset = offset;
977 list->next = *listp;
978 *listp = list;
979}
980
981/* Copy all nodes from SRC and create a list *DSTP of the copies. */
982
983static void
984attrs_list_copy (attrs *dstp, attrs src)
985{
986 attrs n;
987
988 attrs_list_clear (dstp);
989 for (; src; src = src->next)
990 {
3d9a9f94 991 n = (attrs) pool_alloc (attrs_pool);
014a1138 992 n->loc = src->loc;
b5b8b0ac 993 n->dv = src->dv;
014a1138
JZ
994 n->offset = src->offset;
995 n->next = *dstp;
996 *dstp = n;
997 }
998}
999
1000/* Add all nodes from SRC which are not in *DSTP to *DSTP. */
1001
1002static void
1003attrs_list_union (attrs *dstp, attrs src)
1004{
1005 for (; src; src = src->next)
1006 {
b5b8b0ac
AO
1007 if (!attrs_list_member (*dstp, src->dv, src->offset))
1008 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1009 }
1010}
1011
1012/* Combine nodes that are not onepart nodes from SRC and SRC2 into
1013 *DSTP. */
1014
1015static void
1016attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
1017{
1018 gcc_assert (!*dstp);
1019 for (; src; src = src->next)
1020 {
1021 if (!dv_onepart_p (src->dv))
1022 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1023 }
1024 for (src = src2; src; src = src->next)
1025 {
1026 if (!dv_onepart_p (src->dv)
1027 && !attrs_list_member (*dstp, src->dv, src->offset))
1028 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
014a1138
JZ
1029 }
1030}
1031
d24686d7
JJ
1032/* Shared hashtable support. */
1033
1034/* Return true if VARS is shared. */
1035
1036static inline bool
1037shared_hash_shared (shared_hash vars)
1038{
1039 return vars->refcount > 1;
1040}
1041
1042/* Return the hash table for VARS. */
1043
1044static inline htab_t
1045shared_hash_htab (shared_hash vars)
1046{
1047 return vars->htab;
1048}
1049
1050/* Copy variables into a new hash table. */
1051
1052static shared_hash
1053shared_hash_unshare (shared_hash vars)
1054{
1055 shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
1056 gcc_assert (vars->refcount > 1);
1057 new_vars->refcount = 1;
1058 new_vars->htab
1059 = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
1060 variable_htab_eq, variable_htab_free);
1061 vars_copy (new_vars->htab, vars->htab);
1062 vars->refcount--;
1063 return new_vars;
1064}
1065
1066/* Increment reference counter on VARS and return it. */
1067
1068static inline shared_hash
1069shared_hash_copy (shared_hash vars)
1070{
1071 vars->refcount++;
1072 return vars;
1073}
1074
1075/* Decrement reference counter and destroy hash table if not shared
1076 anymore. */
014a1138
JZ
1077
1078static void
d24686d7 1079shared_hash_destroy (shared_hash vars)
014a1138 1080{
d24686d7
JJ
1081 gcc_assert (vars->refcount > 0);
1082 if (--vars->refcount == 0)
1083 {
1084 htab_delete (vars->htab);
1085 pool_free (shared_hash_pool, vars);
1086 }
1087}
1088
b5b8b0ac 1089/* Unshare *PVARS if shared and return slot for DV. If INS is
d24686d7
JJ
1090 INSERT, insert it if not already present. */
1091
1092static inline void **
b5b8b0ac
AO
1093shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
1094 hashval_t dvhash, enum insert_option ins)
d24686d7
JJ
1095{
1096 if (shared_hash_shared (*pvars))
1097 *pvars = shared_hash_unshare (*pvars);
b5b8b0ac
AO
1098 return htab_find_slot_with_hash (shared_hash_htab (*pvars), dv, dvhash, ins);
1099}
1100
1101static inline void **
1102shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
1103 enum insert_option ins)
1104{
1105 return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
d24686d7
JJ
1106}
1107
b5b8b0ac 1108/* Return slot for DV, if it is already present in the hash table.
d24686d7
JJ
1109 If it is not present, insert it only VARS is not shared, otherwise
1110 return NULL. */
1111
1112static inline void **
b5b8b0ac 1113shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
d24686d7 1114{
b5b8b0ac 1115 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
d24686d7
JJ
1116 shared_hash_shared (vars)
1117 ? NO_INSERT : INSERT);
1118}
1119
b5b8b0ac
AO
1120static inline void **
1121shared_hash_find_slot (shared_hash vars, decl_or_value dv)
1122{
1123 return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
1124}
1125
1126/* Return slot for DV only if it is already present in the hash table. */
1127
1128static inline void **
1129shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
1130 hashval_t dvhash)
1131{
1132 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
1133 NO_INSERT);
1134}
d24686d7
JJ
1135
1136static inline void **
b5b8b0ac 1137shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
d24686d7 1138{
b5b8b0ac 1139 return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
d24686d7
JJ
1140}
1141
b5b8b0ac 1142/* Return variable for DV or NULL if not already present in the hash
d24686d7
JJ
1143 table. */
1144
1145static inline variable
b5b8b0ac
AO
1146shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
1147{
1148 return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash);
1149}
1150
1151static inline variable
1152shared_hash_find (shared_hash vars, decl_or_value dv)
1153{
1154 return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
1155}
1156
1157/* Determine a total order between two distinct pointers. Compare the
1158 pointers as integral types if size_t is wide enough, otherwise
1159 resort to bitwise memory compare. The actual order does not
1160 matter, we just need to be consistent, so endianness is
1161 irrelevant. */
1162
1163static int
1164tie_break_pointers (const void *p1, const void *p2)
d24686d7 1165{
b5b8b0ac
AO
1166 gcc_assert (p1 != p2);
1167
1168 if (sizeof (size_t) >= sizeof (void*))
1169 return (size_t)p1 < (size_t)p2 ? -1 : 1;
1170 else
1171 return memcmp (&p1, &p2, sizeof (p1));
1172}
1173
1174/* Return true if TVAL is better than CVAL as a canonival value. We
1175 choose lowest-numbered VALUEs, using the RTX address as a
1176 tie-breaker. The idea is to arrange them into a star topology,
1177 such that all of them are at most one step away from the canonical
1178 value, and the canonical value has backlinks to all of them, in
1179 addition to all the actual locations. We don't enforce this
1180 topology throughout the entire dataflow analysis, though.
1181 */
1182
1183static inline bool
1184canon_value_cmp (rtx tval, rtx cval)
1185{
1186 return !cval
1187 || CSELIB_VAL_PTR (tval)->value < CSELIB_VAL_PTR (cval)->value
1188 || (CSELIB_VAL_PTR (tval)->value == CSELIB_VAL_PTR (cval)->value
1189 && tie_break_pointers (tval, cval) < 0);
014a1138
JZ
1190}
1191
b5b8b0ac
AO
1192static bool dst_can_be_shared;
1193
81f2eadb 1194/* Return a copy of a variable VAR and insert it to dataflow set SET. */
014a1138 1195
b5b8b0ac
AO
1196static void **
1197unshare_variable (dataflow_set *set, void **slot, variable var,
62760ffd 1198 enum var_init_status initialized)
014a1138 1199{
81f2eadb 1200 variable new_var;
014a1138
JZ
1201 int i;
1202
b5b8b0ac
AO
1203 new_var = (variable) pool_alloc (dv_pool (var->dv));
1204 new_var->dv = var->dv;
81f2eadb
JZ
1205 new_var->refcount = 1;
1206 var->refcount--;
1207 new_var->n_var_parts = var->n_var_parts;
014a1138 1208
7eb3f1f7
JJ
1209 if (! flag_var_tracking_uninit)
1210 initialized = VAR_INIT_STATUS_INITIALIZED;
1211
014a1138
JZ
1212 for (i = 0; i < var->n_var_parts; i++)
1213 {
11599d14
JZ
1214 location_chain node;
1215 location_chain *nextp;
014a1138 1216
81f2eadb
JZ
1217 new_var->var_part[i].offset = var->var_part[i].offset;
1218 nextp = &new_var->var_part[i].loc_chain;
1219 for (node = var->var_part[i].loc_chain; node; node = node->next)
014a1138
JZ
1220 {
1221 location_chain new_lc;
1222
3d9a9f94 1223 new_lc = (location_chain) pool_alloc (loc_chain_pool);
014a1138 1224 new_lc->next = NULL;
62760ffd
CT
1225 if (node->init > initialized)
1226 new_lc->init = node->init;
1227 else
1228 new_lc->init = initialized;
1229 if (node->set_src && !(MEM_P (node->set_src)))
1230 new_lc->set_src = node->set_src;
1231 else
1232 new_lc->set_src = NULL;
014a1138
JZ
1233 new_lc->loc = node->loc;
1234
11599d14
JZ
1235 *nextp = new_lc;
1236 nextp = &new_lc->next;
014a1138
JZ
1237 }
1238
1239 /* We are at the basic block boundary when copying variable description
1240 so set the CUR_LOC to be the first element of the chain. */
81f2eadb
JZ
1241 if (new_var->var_part[i].loc_chain)
1242 new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
014a1138 1243 else
81f2eadb 1244 new_var->var_part[i].cur_loc = NULL;
014a1138
JZ
1245 }
1246
b5b8b0ac
AO
1247 dst_can_be_shared = false;
1248 if (shared_hash_shared (set->vars))
1249 slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT);
1250 else if (set->traversed_vars && set->vars != set->traversed_vars)
1251 slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
81f2eadb 1252 *slot = new_var;
b5b8b0ac 1253 return slot;
81f2eadb
JZ
1254}
1255
1256/* Add a variable from *SLOT to hash table DATA and increase its reference
1257 count. */
1258
1259static int
1260vars_copy_1 (void **slot, void *data)
1261{
1262 htab_t dst = (htab_t) data;
b5b8b0ac
AO
1263 variable src;
1264 void **dstp;
81f2eadb 1265
b5b8b0ac 1266 src = (variable) *slot;
81f2eadb
JZ
1267 src->refcount++;
1268
b5b8b0ac
AO
1269 dstp = htab_find_slot_with_hash (dst, src->dv,
1270 dv_htab_hash (src->dv),
1271 INSERT);
81f2eadb
JZ
1272 *dstp = src;
1273
014a1138
JZ
1274 /* Continue traversing the hash table. */
1275 return 1;
1276}
1277
1278/* Copy all variables from hash table SRC to hash table DST. */
1279
1280static void
1281vars_copy (htab_t dst, htab_t src)
1282{
d24686d7 1283 htab_traverse_noresize (src, vars_copy_1, dst);
014a1138
JZ
1284}
1285
ca787200
AO
1286/* Map a decl to its main debug decl. */
1287
1288static inline tree
1289var_debug_decl (tree decl)
1290{
1291 if (decl && DECL_P (decl)
1292 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
1293 && DECL_P (DECL_DEBUG_EXPR (decl)))
1294 decl = DECL_DEBUG_EXPR (decl);
1295
1296 return decl;
1297}
1298
b5b8b0ac 1299/* Set the register LOC to contain DV, OFFSET. */
dedc1e6d
AO
1300
1301static void
b5b8b0ac
AO
1302var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1303 decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1304 enum insert_option iopt)
dedc1e6d 1305{
ca787200 1306 attrs node;
b5b8b0ac 1307 bool decl_p = dv_is_decl_p (dv);
ca787200 1308
b5b8b0ac
AO
1309 if (decl_p)
1310 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
dedc1e6d 1311
ca787200 1312 for (node = set->regs[REGNO (loc)]; node; node = node->next)
b5b8b0ac
AO
1313 if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
1314 && node->offset == offset)
ca787200
AO
1315 break;
1316 if (!node)
b5b8b0ac
AO
1317 attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc);
1318 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1319}
1320
1321/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
1322
1323static void
1324var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1325 rtx set_src)
1326{
1327 tree decl = REG_EXPR (loc);
1328 HOST_WIDE_INT offset = REG_OFFSET (loc);
1329
1330 var_reg_decl_set (set, loc, initialized,
1331 dv_from_decl (decl), offset, set_src, INSERT);
62760ffd
CT
1332}
1333
32e8bb8e 1334static enum var_init_status
b5b8b0ac 1335get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
62760ffd 1336{
62760ffd
CT
1337 variable var;
1338 int i;
32e8bb8e 1339 enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
62760ffd
CT
1340
1341 if (! flag_var_tracking_uninit)
1342 return VAR_INIT_STATUS_INITIALIZED;
1343
b5b8b0ac 1344 var = shared_hash_find (set->vars, dv);
d24686d7 1345 if (var)
62760ffd 1346 {
62760ffd
CT
1347 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
1348 {
1349 location_chain nextp;
1350 for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1351 if (rtx_equal_p (nextp->loc, loc))
1352 {
1353 ret_val = nextp->init;
1354 break;
1355 }
1356 }
1357 }
1358
1359 return ret_val;
dedc1e6d
AO
1360}
1361
ca787200
AO
1362/* Delete current content of register LOC in dataflow set SET and set
1363 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
1364 MODIFY is true, any other live copies of the same variable part are
1365 also deleted from the dataflow set, otherwise the variable part is
1366 assumed to be copied from another location holding the same
1367 part. */
014a1138
JZ
1368
1369static void
62760ffd
CT
1370var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1371 enum var_init_status initialized, rtx set_src)
014a1138 1372{
014a1138
JZ
1373 tree decl = REG_EXPR (loc);
1374 HOST_WIDE_INT offset = REG_OFFSET (loc);
11599d14
JZ
1375 attrs node, next;
1376 attrs *nextp;
014a1138 1377
ca787200
AO
1378 decl = var_debug_decl (decl);
1379
62760ffd 1380 if (initialized == VAR_INIT_STATUS_UNKNOWN)
b5b8b0ac 1381 initialized = get_init_value (set, loc, dv_from_decl (decl));
62760ffd 1382
11599d14
JZ
1383 nextp = &set->regs[REGNO (loc)];
1384 for (node = *nextp; node; node = next)
014a1138
JZ
1385 {
1386 next = node->next;
b5b8b0ac 1387 if (dv_as_opaque (node->dv) != decl || node->offset != offset)
014a1138 1388 {
b5b8b0ac 1389 delete_variable_part (set, node->loc, node->dv, node->offset);
014a1138 1390 pool_free (attrs_pool, node);
11599d14 1391 *nextp = next;
014a1138
JZ
1392 }
1393 else
1394 {
1395 node->loc = loc;
11599d14 1396 nextp = &node->next;
014a1138
JZ
1397 }
1398 }
ca787200 1399 if (modify)
b5b8b0ac 1400 clobber_variable_part (set, loc, dv_from_decl (decl), offset, set_src);
62760ffd 1401 var_reg_set (set, loc, initialized, set_src);
014a1138
JZ
1402}
1403
ca787200
AO
1404/* Delete current content of register LOC in dataflow set SET. If
1405 CLOBBER is true, also delete any other live copies of the same
1406 variable part. */
014a1138
JZ
1407
1408static void
ca787200 1409var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
014a1138
JZ
1410{
1411 attrs *reg = &set->regs[REGNO (loc)];
1412 attrs node, next;
1413
ca787200
AO
1414 if (clobber)
1415 {
1416 tree decl = REG_EXPR (loc);
1417 HOST_WIDE_INT offset = REG_OFFSET (loc);
1418
1419 decl = var_debug_decl (decl);
1420
b5b8b0ac 1421 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
ca787200
AO
1422 }
1423
014a1138
JZ
1424 for (node = *reg; node; node = next)
1425 {
1426 next = node->next;
b5b8b0ac 1427 delete_variable_part (set, node->loc, node->dv, node->offset);
014a1138
JZ
1428 pool_free (attrs_pool, node);
1429 }
1430 *reg = NULL;
1431}
1432
1433/* Delete content of register with number REGNO in dataflow set SET. */
1434
1435static void
1436var_regno_delete (dataflow_set *set, int regno)
1437{
1438 attrs *reg = &set->regs[regno];
1439 attrs node, next;
1440
1441 for (node = *reg; node; node = next)
1442 {
1443 next = node->next;
b5b8b0ac 1444 delete_variable_part (set, node->loc, node->dv, node->offset);
014a1138
JZ
1445 pool_free (attrs_pool, node);
1446 }
1447 *reg = NULL;
1448}
1449
b5b8b0ac
AO
1450/* Set the location of DV, OFFSET as the MEM LOC. */
1451
1452static void
1453var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1454 decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1455 enum insert_option iopt)
1456{
1457 if (dv_is_decl_p (dv))
1458 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1459
1460 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1461}
1462
dedc1e6d
AO
1463/* Set the location part of variable MEM_EXPR (LOC) in dataflow set
1464 SET to LOC.
014a1138
JZ
1465 Adjust the address first if it is stack pointer based. */
1466
1467static void
62760ffd
CT
1468var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1469 rtx set_src)
014a1138
JZ
1470{
1471 tree decl = MEM_EXPR (loc);
8c6c36a3 1472 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
014a1138 1473
b5b8b0ac
AO
1474 var_mem_decl_set (set, loc, initialized,
1475 dv_from_decl (decl), offset, set_src, INSERT);
014a1138
JZ
1476}
1477
ca787200
AO
1478/* Delete and set the location part of variable MEM_EXPR (LOC) in
1479 dataflow set SET to LOC. If MODIFY is true, any other live copies
1480 of the same variable part are also deleted from the dataflow set,
1481 otherwise the variable part is assumed to be copied from another
1482 location holding the same part.
dedc1e6d
AO
1483 Adjust the address first if it is stack pointer based. */
1484
1485static void
62760ffd
CT
1486var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1487 enum var_init_status initialized, rtx set_src)
dedc1e6d 1488{
ca787200 1489 tree decl = MEM_EXPR (loc);
8c6c36a3 1490 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
ca787200
AO
1491
1492 decl = var_debug_decl (decl);
1493
62760ffd 1494 if (initialized == VAR_INIT_STATUS_UNKNOWN)
b5b8b0ac 1495 initialized = get_init_value (set, loc, dv_from_decl (decl));
62760ffd 1496
ca787200 1497 if (modify)
b5b8b0ac 1498 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, set_src);
62760ffd 1499 var_mem_set (set, loc, initialized, set_src);
dedc1e6d
AO
1500}
1501
ca787200
AO
1502/* Delete the location part LOC from dataflow set SET. If CLOBBER is
1503 true, also delete any other live copies of the same variable part.
014a1138
JZ
1504 Adjust the address first if it is stack pointer based. */
1505
1506static void
ca787200 1507var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
014a1138
JZ
1508{
1509 tree decl = MEM_EXPR (loc);
8c6c36a3 1510 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
014a1138 1511
ca787200
AO
1512 decl = var_debug_decl (decl);
1513 if (clobber)
b5b8b0ac
AO
1514 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
1515 delete_variable_part (set, loc, dv_from_decl (decl), offset);
1516}
1517
1518/* Map a value to a location it was just stored in. */
1519
1520static void
1521val_store (dataflow_set *set, rtx val, rtx loc, rtx insn)
1522{
1523 cselib_val *v = CSELIB_VAL_PTR (val);
1524
1525 gcc_assert (cselib_preserved_value_p (v));
1526
1527 if (dump_file)
1528 {
1529 fprintf (dump_file, "%i: ", INSN_UID (insn));
1530 print_inline_rtx (dump_file, val, 0);
1531 fprintf (dump_file, " stored in ");
1532 print_inline_rtx (dump_file, loc, 0);
1533 if (v->locs)
1534 {
1535 struct elt_loc_list *l;
1536 for (l = v->locs; l; l = l->next)
1537 {
1538 fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn));
1539 print_inline_rtx (dump_file, l->loc, 0);
1540 }
1541 }
1542 fprintf (dump_file, "\n");
1543 }
1544
1545 if (REG_P (loc))
1546 {
1547 var_regno_delete (set, REGNO (loc));
1548 var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1549 dv_from_value (val), 0, NULL_RTX, INSERT);
1550 }
1551 else if (MEM_P (loc))
1552 var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1553 dv_from_value (val), 0, NULL_RTX, INSERT);
1554 else
1555 set_variable_part (set, loc, dv_from_value (val), 0,
1556 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1557}
1558
1559/* Reset this node, detaching all its equivalences. Return the slot
1560 in the variable hash table that holds dv, if there is one. */
1561
1562static void
1563val_reset (dataflow_set *set, decl_or_value dv)
1564{
1565 variable var = shared_hash_find (set->vars, dv) ;
1566 location_chain node;
1567 rtx cval;
1568
1569 if (!var || !var->n_var_parts)
1570 return;
1571
1572 gcc_assert (var->n_var_parts == 1);
1573
1574 cval = NULL;
1575 for (node = var->var_part[0].loc_chain; node; node = node->next)
1576 if (GET_CODE (node->loc) == VALUE
1577 && canon_value_cmp (node->loc, cval))
1578 cval = node->loc;
1579
1580 for (node = var->var_part[0].loc_chain; node; node = node->next)
1581 if (GET_CODE (node->loc) == VALUE && cval != node->loc)
1582 {
1583 /* Redirect the equivalence link to the new canonical
1584 value, or simply remove it if it would point at
1585 itself. */
1586 if (cval)
1587 set_variable_part (set, cval, dv_from_value (node->loc),
1588 0, node->init, node->set_src, NO_INSERT);
1589 delete_variable_part (set, dv_as_value (dv),
1590 dv_from_value (node->loc), 0);
1591 }
1592
1593 if (cval)
1594 {
1595 decl_or_value cdv = dv_from_value (cval);
1596
1597 /* Keep the remaining values connected, accummulating links
1598 in the canonical value. */
1599 for (node = var->var_part[0].loc_chain; node; node = node->next)
1600 {
1601 if (node->loc == cval)
1602 continue;
1603 else if (GET_CODE (node->loc) == REG)
1604 var_reg_decl_set (set, node->loc, node->init, cdv, 0,
1605 node->set_src, NO_INSERT);
1606 else if (GET_CODE (node->loc) == MEM)
1607 var_mem_decl_set (set, node->loc, node->init, cdv, 0,
1608 node->set_src, NO_INSERT);
1609 else
1610 set_variable_part (set, node->loc, cdv, 0,
1611 node->init, node->set_src, NO_INSERT);
1612 }
1613 }
1614
1615 /* We remove this last, to make sure that the canonical value is not
1616 removed to the point of requiring reinsertion. */
1617 if (cval)
1618 delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
1619
1620 clobber_variable_part (set, NULL, dv, 0, NULL);
1621
1622 /* ??? Should we make sure there aren't other available values or
1623 variables whose values involve this one other than by
1624 equivalence? E.g., at the very least we should reset MEMs, those
1625 shouldn't be too hard to find cselib-looking up the value as an
1626 address, then locating the resulting value in our own hash
1627 table. */
1628}
1629
1630/* Find the values in a given location and map the val to another
1631 value, if it is unique, or add the location as one holding the
1632 value. */
1633
1634static void
1635val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
1636{
1637 decl_or_value dv = dv_from_value (val);
1638
1639 if (dump_file && (dump_flags & TDF_DETAILS))
1640 {
1641 if (insn)
1642 fprintf (dump_file, "%i: ", INSN_UID (insn));
1643 else
1644 fprintf (dump_file, "head: ");
1645 print_inline_rtx (dump_file, val, 0);
1646 fputs (" is at ", dump_file);
1647 print_inline_rtx (dump_file, loc, 0);
1648 fputc ('\n', dump_file);
1649 }
1650
1651 val_reset (set, dv);
1652
1653 if (REG_P (loc))
1654 {
1655 attrs node, found = NULL;
1656
1657 for (node = set->regs[REGNO (loc)]; node; node = node->next)
1658 if (dv_is_value_p (node->dv)
1659 && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc))
1660 {
1661 found = node;
1662
1663 /* Map incoming equivalences. ??? Wouldn't it be nice if
1664 we just started sharing the location lists? Maybe a
1665 circular list ending at the value itself or some
1666 such. */
1667 set_variable_part (set, dv_as_value (node->dv),
1668 dv_from_value (val), node->offset,
1669 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1670 set_variable_part (set, val, node->dv, node->offset,
1671 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1672 }
1673
1674 /* If we didn't find any equivalence, we need to remember that
1675 this value is held in the named register. */
1676 if (!found)
1677 var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1678 dv_from_value (val), 0, NULL_RTX, INSERT);
1679 }
1680 else if (MEM_P (loc))
1681 /* ??? Merge equivalent MEMs. */
1682 var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1683 dv_from_value (val), 0, NULL_RTX, INSERT);
1684 else
1685 /* ??? Merge equivalent expressions. */
1686 set_variable_part (set, loc, dv_from_value (val), 0,
1687 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
014a1138
JZ
1688}
1689
1690/* Initialize dataflow set SET to be empty.
1691 VARS_SIZE is the initial size of hash table VARS. */
1692
1693static void
d24686d7 1694dataflow_set_init (dataflow_set *set)
014a1138
JZ
1695{
1696 init_attrs_list_set (set->regs);
d24686d7 1697 set->vars = shared_hash_copy (empty_shared_hash);
014a1138 1698 set->stack_adjust = 0;
b5b8b0ac 1699 set->traversed_vars = NULL;
014a1138
JZ
1700}
1701
1702/* Delete the contents of dataflow set SET. */
1703
1704static void
1705dataflow_set_clear (dataflow_set *set)
1706{
1707 int i;
1708
1709 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1710 attrs_list_clear (&set->regs[i]);
1711
d24686d7
JJ
1712 shared_hash_destroy (set->vars);
1713 set->vars = shared_hash_copy (empty_shared_hash);
014a1138
JZ
1714}
1715
1716/* Copy the contents of dataflow set SRC to DST. */
1717
1718static void
1719dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1720{
1721 int i;
1722
1723 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1724 attrs_list_copy (&dst->regs[i], src->regs[i]);
1725
d24686d7
JJ
1726 shared_hash_destroy (dst->vars);
1727 dst->vars = shared_hash_copy (src->vars);
014a1138
JZ
1728 dst->stack_adjust = src->stack_adjust;
1729}
1730
1731/* Information for merging lists of locations for a given offset of variable.
1732 */
1733struct variable_union_info
1734{
1735 /* Node of the location chain. */
1736 location_chain lc;
1737
1738 /* The sum of positions in the input chains. */
1739 int pos;
1740
7eb3f1f7 1741 /* The position in the chain of DST dataflow set. */
014a1138
JZ
1742 int pos_dst;
1743};
1744
7eb3f1f7
JJ
1745/* Buffer for location list sorting and its allocated size. */
1746static struct variable_union_info *vui_vec;
1747static int vui_allocated;
1748
014a1138
JZ
1749/* Compare function for qsort, order the structures by POS element. */
1750
1751static int
1752variable_union_info_cmp_pos (const void *n1, const void *n2)
1753{
3d9a9f94
KG
1754 const struct variable_union_info *const i1 =
1755 (const struct variable_union_info *) n1;
1756 const struct variable_union_info *const i2 =
1757 ( const struct variable_union_info *) n2;
014a1138
JZ
1758
1759 if (i1->pos != i2->pos)
1760 return i1->pos - i2->pos;
1761
1762 return (i1->pos_dst - i2->pos_dst);
1763}
1764
1765/* Compute union of location parts of variable *SLOT and the same variable
1766 from hash table DATA. Compute "sorted" union of the location chains
1767 for common offsets, i.e. the locations of a variable part are sorted by
1768 a priority where the priority is the sum of the positions in the 2 chains
1769 (if a location is only in one list the position in the second list is
1770 defined to be larger than the length of the chains).
1771 When we are updating the location parts the newest location is in the
1772 beginning of the chain, so when we do the described "sorted" union
1773 we keep the newest locations in the beginning. */
1774
1775static int
1776variable_union (void **slot, void *data)
1777{
d24686d7
JJ
1778 variable src, dst;
1779 void **dstp;
014a1138
JZ
1780 dataflow_set *set = (dataflow_set *) data;
1781 int i, j, k;
1782
b5b8b0ac
AO
1783 src = (variable) *slot;
1784 dstp = shared_hash_find_slot (set->vars, src->dv);
d24686d7 1785 if (!dstp || !*dstp)
014a1138 1786 {
81f2eadb
JZ
1787 src->refcount++;
1788
b5b8b0ac
AO
1789 dst_can_be_shared = false;
1790 if (!dstp)
1791 dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT);
1792
1793 *dstp = src;
1794
81f2eadb
JZ
1795 /* If CUR_LOC of some variable part is not the first element of
1796 the location chain we are going to change it so we have to make
1797 a copy of the variable. */
1798 for (k = 0; k < src->n_var_parts; k++)
1799 {
fbc848cc
NS
1800 gcc_assert (!src->var_part[k].loc_chain
1801 == !src->var_part[k].cur_loc);
81f2eadb
JZ
1802 if (src->var_part[k].loc_chain)
1803 {
fbc848cc 1804 gcc_assert (src->var_part[k].cur_loc);
81f2eadb
JZ
1805 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
1806 break;
1807 }
81f2eadb
JZ
1808 }
1809 if (k < src->n_var_parts)
b5b8b0ac 1810 dstp = unshare_variable (set, dstp, src, VAR_INIT_STATUS_UNKNOWN);
81f2eadb
JZ
1811
1812 /* Continue traversing the hash table. */
1813 return 1;
014a1138
JZ
1814 }
1815 else
d24686d7 1816 dst = (variable) *dstp;
014a1138 1817
fbc848cc 1818 gcc_assert (src->n_var_parts);
014a1138 1819
b5b8b0ac
AO
1820 /* We can combine one-part variables very efficiently, because their
1821 entries are in canonical order. */
1822 if (dv_onepart_p (src->dv))
1823 {
1824 location_chain *nodep, dnode, snode;
1825
1826 gcc_assert (src->n_var_parts == 1);
1827 gcc_assert (dst->n_var_parts == 1);
1828
1829 snode = src->var_part[0].loc_chain;
1830 gcc_assert (snode);
1831
1832 restart_onepart_unshared:
1833 nodep = &dst->var_part[0].loc_chain;
1834 dnode = *nodep;
1835 gcc_assert (dnode);
1836
1837 while (snode)
1838 {
1839 int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1;
1840
1841 if (r > 0)
1842 {
1843 location_chain nnode;
1844
1845 if (dst->refcount != 1 || shared_hash_shared (set->vars))
1846 {
1847 dstp = unshare_variable (set, dstp, dst,
1848 VAR_INIT_STATUS_INITIALIZED);
1849 dst = (variable)*dstp;
1850 goto restart_onepart_unshared;
1851 }
1852
1853 *nodep = nnode = (location_chain) pool_alloc (loc_chain_pool);
1854 nnode->loc = snode->loc;
1855 nnode->init = snode->init;
1856 if (!snode->set_src || MEM_P (snode->set_src))
1857 nnode->set_src = NULL;
1858 else
1859 nnode->set_src = snode->set_src;
1860 nnode->next = dnode;
1861 dnode = nnode;
1862 }
1863#ifdef ENABLE_CHECKING
1864 else if (r == 0)
1865 gcc_assert (rtx_equal_p (dnode->loc, snode->loc));
1866#endif
1867
1868 if (r >= 0)
1869 snode = snode->next;
1870
1871 nodep = &dnode->next;
1872 dnode = *nodep;
1873 }
1874
1875 dst->var_part[0].cur_loc = dst->var_part[0].loc_chain->loc;
1876
1877 return 1;
1878 }
1879
014a1138
JZ
1880 /* Count the number of location parts, result is K. */
1881 for (i = 0, j = 0, k = 0;
1882 i < src->n_var_parts && j < dst->n_var_parts; k++)
1883 {
1884 if (src->var_part[i].offset == dst->var_part[j].offset)
1885 {
1886 i++;
1887 j++;
1888 }
1889 else if (src->var_part[i].offset < dst->var_part[j].offset)
1890 i++;
1891 else
1892 j++;
1893 }
81f2eadb
JZ
1894 k += src->n_var_parts - i;
1895 k += dst->n_var_parts - j;
fbc848cc 1896
014a1138
JZ
1897 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1898 thus there are at most MAX_VAR_PARTS different offsets. */
b5b8b0ac 1899 gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS);
014a1138 1900
d24686d7
JJ
1901 if ((dst->refcount > 1 || shared_hash_shared (set->vars))
1902 && dst->n_var_parts != k)
b5b8b0ac
AO
1903 {
1904 dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
1905 dst = (variable)*dstp;
1906 }
1907
014a1138
JZ
1908 i = src->n_var_parts - 1;
1909 j = dst->n_var_parts - 1;
1910 dst->n_var_parts = k;
1911
1912 for (k--; k >= 0; k--)
1913 {
81f2eadb 1914 location_chain node, node2;
014a1138
JZ
1915
1916 if (i >= 0 && j >= 0
1917 && src->var_part[i].offset == dst->var_part[j].offset)
1918 {
1919 /* Compute the "sorted" union of the chains, i.e. the locations which
1920 are in both chains go first, they are sorted by the sum of
1921 positions in the chains. */
1922 int dst_l, src_l;
1923 int ii, jj, n;
1924 struct variable_union_info *vui;
81f2eadb
JZ
1925
1926 /* If DST is shared compare the location chains.
1927 If they are different we will modify the chain in DST with
1928 high probability so make a copy of DST. */
d24686d7 1929 if (dst->refcount > 1 || shared_hash_shared (set->vars))
81f2eadb
JZ
1930 {
1931 for (node = src->var_part[i].loc_chain,
1932 node2 = dst->var_part[j].loc_chain; node && node2;
1933 node = node->next, node2 = node2->next)
1934 {
f8cfc6aa
JQ
1935 if (!((REG_P (node2->loc)
1936 && REG_P (node->loc)
81f2eadb
JZ
1937 && REGNO (node2->loc) == REGNO (node->loc))
1938 || rtx_equal_p (node2->loc, node->loc)))
e56f9152
MM
1939 {
1940 if (node2->init < node->init)
1941 node2->init = node->init;
1942 break;
1943 }
81f2eadb
JZ
1944 }
1945 if (node || node2)
b5b8b0ac
AO
1946 {
1947 dstp = unshare_variable (set, dstp, dst,
1948 VAR_INIT_STATUS_UNKNOWN);
1949 dst = (variable)*dstp;
1950 }
81f2eadb
JZ
1951 }
1952
014a1138
JZ
1953 src_l = 0;
1954 for (node = src->var_part[i].loc_chain; node; node = node->next)
1955 src_l++;
1956 dst_l = 0;
1957 for (node = dst->var_part[j].loc_chain; node; node = node->next)
1958 dst_l++;
014a1138 1959
7eb3f1f7 1960 if (dst_l == 1)
014a1138 1961 {
7eb3f1f7
JJ
1962 /* The most common case, much simpler, no qsort is needed. */
1963 location_chain dstnode = dst->var_part[j].loc_chain;
1964 dst->var_part[k].loc_chain = dstnode;
1965 dst->var_part[k].offset = dst->var_part[j].offset;
1966 node2 = dstnode;
1967 for (node = src->var_part[i].loc_chain; node; node = node->next)
1968 if (!((REG_P (dstnode->loc)
1969 && REG_P (node->loc)
1970 && REGNO (dstnode->loc) == REGNO (node->loc))
1971 || rtx_equal_p (dstnode->loc, node->loc)))
1972 {
1973 location_chain new_node;
1974
1975 /* Copy the location from SRC. */
1976 new_node = (location_chain) pool_alloc (loc_chain_pool);
1977 new_node->loc = node->loc;
1978 new_node->init = node->init;
1979 if (!node->set_src || MEM_P (node->set_src))
1980 new_node->set_src = NULL;
1981 else
1982 new_node->set_src = node->set_src;
1983 node2->next = new_node;
1984 node2 = new_node;
1985 }
1986 node2->next = NULL;
014a1138 1987 }
7eb3f1f7 1988 else
014a1138 1989 {
7eb3f1f7 1990 if (src_l + dst_l > vui_allocated)
014a1138 1991 {
7eb3f1f7
JJ
1992 vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
1993 vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
1994 vui_allocated);
1995 }
1996 vui = vui_vec;
1997
1998 /* Fill in the locations from DST. */
1999 for (node = dst->var_part[j].loc_chain, jj = 0; node;
2000 node = node->next, jj++)
2001 {
2002 vui[jj].lc = node;
2003 vui[jj].pos_dst = jj;
2004
2005 /* Pos plus value larger than a sum of 2 valid positions. */
2006 vui[jj].pos = jj + src_l + dst_l;
2007 }
2008
2009 /* Fill in the locations from SRC. */
2010 n = dst_l;
2011 for (node = src->var_part[i].loc_chain, ii = 0; node;
2012 node = node->next, ii++)
2013 {
2014 /* Find location from NODE. */
2015 for (jj = 0; jj < dst_l; jj++)
014a1138 2016 {
7eb3f1f7
JJ
2017 if ((REG_P (vui[jj].lc->loc)
2018 && REG_P (node->loc)
2019 && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
2020 || rtx_equal_p (vui[jj].lc->loc, node->loc))
2021 {
2022 vui[jj].pos = jj + ii;
2023 break;
2024 }
2025 }
2026 if (jj >= dst_l) /* The location has not been found. */
2027 {
2028 location_chain new_node;
2029
2030 /* Copy the location from SRC. */
2031 new_node = (location_chain) pool_alloc (loc_chain_pool);
2032 new_node->loc = node->loc;
2033 new_node->init = node->init;
2034 if (!node->set_src || MEM_P (node->set_src))
2035 new_node->set_src = NULL;
2036 else
2037 new_node->set_src = node->set_src;
2038 vui[n].lc = new_node;
2039 vui[n].pos_dst = src_l + dst_l;
2040 vui[n].pos = ii + src_l + dst_l;
2041 n++;
014a1138
JZ
2042 }
2043 }
7eb3f1f7
JJ
2044
2045 if (dst_l == 2)
014a1138 2046 {
7eb3f1f7
JJ
2047 /* Special case still very common case. For dst_l == 2
2048 all entries dst_l ... n-1 are sorted, with for i >= dst_l
2049 vui[i].pos == i + src_l + dst_l. */
2050 if (vui[0].pos > vui[1].pos)
2051 {
2052 /* Order should be 1, 0, 2... */
2053 dst->var_part[k].loc_chain = vui[1].lc;
2054 vui[1].lc->next = vui[0].lc;
2055 if (n >= 3)
2056 {
2057 vui[0].lc->next = vui[2].lc;
2058 vui[n - 1].lc->next = NULL;
2059 }
2060 else
2061 vui[0].lc->next = NULL;
2062 ii = 3;
2063 }
62760ffd 2064 else
7eb3f1f7
JJ
2065 {
2066 dst->var_part[k].loc_chain = vui[0].lc;
2067 if (n >= 3 && vui[2].pos < vui[1].pos)
2068 {
2069 /* Order should be 0, 2, 1, 3... */
2070 vui[0].lc->next = vui[2].lc;
2071 vui[2].lc->next = vui[1].lc;
2072 if (n >= 4)
2073 {
2074 vui[1].lc->next = vui[3].lc;
2075 vui[n - 1].lc->next = NULL;
2076 }
2077 else
2078 vui[1].lc->next = NULL;
2079 ii = 4;
2080 }
2081 else
2082 {
2083 /* Order should be 0, 1, 2... */
2084 ii = 1;
2085 vui[n - 1].lc->next = NULL;
2086 }
2087 }
2088 for (; ii < n; ii++)
2089 vui[ii - 1].lc->next = vui[ii].lc;
2090 }
2091 else
2092 {
2093 qsort (vui, n, sizeof (struct variable_union_info),
2094 variable_union_info_cmp_pos);
2095
2096 /* Reconnect the nodes in sorted order. */
2097 for (ii = 1; ii < n; ii++)
2098 vui[ii - 1].lc->next = vui[ii].lc;
2099 vui[n - 1].lc->next = NULL;
2100 dst->var_part[k].loc_chain = vui[0].lc;
014a1138 2101 }
014a1138 2102
7eb3f1f7
JJ
2103 dst->var_part[k].offset = dst->var_part[j].offset;
2104 }
014a1138
JZ
2105 i--;
2106 j--;
2107 }
2108 else if ((i >= 0 && j >= 0
2109 && src->var_part[i].offset < dst->var_part[j].offset)
2110 || i < 0)
2111 {
2112 dst->var_part[k] = dst->var_part[j];
2113 j--;
2114 }
2115 else if ((i >= 0 && j >= 0
2116 && src->var_part[i].offset > dst->var_part[j].offset)
2117 || j < 0)
2118 {
11599d14 2119 location_chain *nextp;
014a1138
JZ
2120
2121 /* Copy the chain from SRC. */
11599d14 2122 nextp = &dst->var_part[k].loc_chain;
014a1138
JZ
2123 for (node = src->var_part[i].loc_chain; node; node = node->next)
2124 {
2125 location_chain new_lc;
2126
3d9a9f94 2127 new_lc = (location_chain) pool_alloc (loc_chain_pool);
014a1138 2128 new_lc->next = NULL;
62760ffd
CT
2129 new_lc->init = node->init;
2130 if (!node->set_src || MEM_P (node->set_src))
2131 new_lc->set_src = NULL;
2132 else
2133 new_lc->set_src = node->set_src;
014a1138
JZ
2134 new_lc->loc = node->loc;
2135
11599d14
JZ
2136 *nextp = new_lc;
2137 nextp = &new_lc->next;
014a1138
JZ
2138 }
2139
2140 dst->var_part[k].offset = src->var_part[i].offset;
2141 i--;
2142 }
2143
2144 /* We are at the basic block boundary when computing union
2145 so set the CUR_LOC to be the first element of the chain. */
2146 if (dst->var_part[k].loc_chain)
2147 dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc;
2148 else
2149 dst->var_part[k].cur_loc = NULL;
2150 }
2151
7eb3f1f7
JJ
2152 if (flag_var_tracking_uninit)
2153 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
2154 {
2155 location_chain node, node2;
2156 for (node = src->var_part[i].loc_chain; node; node = node->next)
2157 for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
2158 if (rtx_equal_p (node->loc, node2->loc))
2159 {
2160 if (node->init > node2->init)
2161 node2->init = node->init;
2162 }
2163 }
62760ffd 2164
014a1138
JZ
2165 /* Continue traversing the hash table. */
2166 return 1;
2167}
2168
d24686d7
JJ
2169/* Like variable_union, but only used when doing dataflow_set_union
2170 into an empty hashtab. To allow sharing, dst is initially shared
2171 with src (so all variables are "copied" from src to dst hashtab),
2172 so only unshare_variable for variables that need canonicalization
2173 are needed. */
2174
2175static int
2176variable_canonicalize (void **slot, void *data)
2177{
2178 variable src;
2179 dataflow_set *set = (dataflow_set *) data;
2180 int k;
2181
2182 src = *(variable *) slot;
2183
2184 /* If CUR_LOC of some variable part is not the first element of
2185 the location chain we are going to change it so we have to make
2186 a copy of the variable. */
2187 for (k = 0; k < src->n_var_parts; k++)
2188 {
2189 gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc);
2190 if (src->var_part[k].loc_chain)
2191 {
2192 gcc_assert (src->var_part[k].cur_loc);
2193 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
2194 break;
2195 }
2196 }
2197 if (k < src->n_var_parts)
b5b8b0ac 2198 slot = unshare_variable (set, slot, src, VAR_INIT_STATUS_UNKNOWN);
d24686d7
JJ
2199 return 1;
2200}
2201
014a1138
JZ
2202/* Compute union of dataflow sets SRC and DST and store it to DST. */
2203
2204static void
2205dataflow_set_union (dataflow_set *dst, dataflow_set *src)
2206{
2207 int i;
2208
2209 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2210 attrs_list_union (&dst->regs[i], src->regs[i]);
2211
d24686d7
JJ
2212 if (dst->vars == empty_shared_hash)
2213 {
2214 shared_hash_destroy (dst->vars);
2215 dst->vars = shared_hash_copy (src->vars);
b5b8b0ac
AO
2216 dst->traversed_vars = dst->vars;
2217 htab_traverse (shared_hash_htab (dst->vars), variable_canonicalize, dst);
2218 dst->traversed_vars = NULL;
d24686d7
JJ
2219 }
2220 else
2221 htab_traverse (shared_hash_htab (src->vars), variable_union, dst);
014a1138
JZ
2222}
2223
b5b8b0ac
AO
2224/* Whether the value is currently being expanded. */
2225#define VALUE_RECURSED_INTO(x) \
0ca5af51 2226 (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
b5b8b0ac
AO
2227/* Whether the value is in changed_variables hash table. */
2228#define VALUE_CHANGED(x) \
2229 (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
2230/* Whether the decl is in changed_variables hash table. */
2231#define DECL_CHANGED(x) TREE_VISITED (x)
014a1138 2232
b5b8b0ac
AO
2233/* Record that DV has been added into resp. removed from changed_variables
2234 hashtable. */
014a1138 2235
b5b8b0ac
AO
2236static inline void
2237set_dv_changed (decl_or_value dv, bool newv)
2238{
2239 if (dv_is_value_p (dv))
2240 VALUE_CHANGED (dv_as_value (dv)) = newv;
2241 else
2242 DECL_CHANGED (dv_as_decl (dv)) = newv;
014a1138
JZ
2243}
2244
b5b8b0ac 2245/* Return true if DV is present in changed_variables hash table. */
014a1138 2246
b5b8b0ac
AO
2247static inline bool
2248dv_changed_p (decl_or_value dv)
014a1138 2249{
b5b8b0ac
AO
2250 return (dv_is_value_p (dv)
2251 ? VALUE_CHANGED (dv_as_value (dv))
2252 : DECL_CHANGED (dv_as_decl (dv)));
014a1138
JZ
2253}
2254
b5b8b0ac
AO
2255/* Return a location list node whose loc is rtx_equal to LOC, in the
2256 location list of a one-part variable or value VAR, or in that of
2257 any values recursively mentioned in the location lists. */
014a1138 2258
b5b8b0ac
AO
2259static location_chain
2260find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
014a1138 2261{
b5b8b0ac 2262 location_chain node;
014a1138 2263
b5b8b0ac
AO
2264 if (!var)
2265 return NULL;
014a1138 2266
b5b8b0ac 2267 gcc_assert (dv_onepart_p (var->dv));
014a1138 2268
b5b8b0ac
AO
2269 if (!var->n_var_parts)
2270 return NULL;
014a1138 2271
b5b8b0ac 2272 gcc_assert (var->var_part[0].offset == 0);
014a1138 2273
b5b8b0ac
AO
2274 for (node = var->var_part[0].loc_chain; node; node = node->next)
2275 if (rtx_equal_p (loc, node->loc))
2276 return node;
2277 else if (GET_CODE (node->loc) == VALUE
2278 && !VALUE_RECURSED_INTO (node->loc))
2279 {
2280 decl_or_value dv = dv_from_value (node->loc);
2281 variable var = (variable)
2282 htab_find_with_hash (vars, dv, dv_htab_hash (dv));
2283
2284 if (var)
2285 {
2286 location_chain where;
2287 VALUE_RECURSED_INTO (node->loc) = true;
2288 if ((where = find_loc_in_1pdv (loc, var, vars)))
2289 {
2290 VALUE_RECURSED_INTO (node->loc) = false;
2291 return where;
2292 }
2293 VALUE_RECURSED_INTO (node->loc) = false;
2294 }
2295 }
014a1138 2296
b5b8b0ac
AO
2297 return NULL;
2298}
014a1138 2299
b5b8b0ac
AO
2300/* Hash table iteration argument passed to variable_merge. */
2301struct dfset_merge
014a1138 2302{
b5b8b0ac
AO
2303 /* The set in which the merge is to be inserted. */
2304 dataflow_set *dst;
2305 /* The set that we're iterating in. */
2306 dataflow_set *cur;
2307 /* The set that may contain the other dv we are to merge with. */
2308 dataflow_set *src;
2309 /* Number of onepart dvs in src. */
2310 int src_onepart_cnt;
2311};
014a1138 2312
b5b8b0ac
AO
2313/* Insert LOC in *DNODE, if it's not there yet. The list must be in
2314 loc_cmp order, and it is maintained as such. */
014a1138
JZ
2315
2316static void
b5b8b0ac
AO
2317insert_into_intersection (location_chain *nodep, rtx loc,
2318 enum var_init_status status)
014a1138 2319{
b5b8b0ac
AO
2320 location_chain node;
2321 int r;
014a1138 2322
b5b8b0ac
AO
2323 for (node = *nodep; node; nodep = &node->next, node = *nodep)
2324 if ((r = loc_cmp (node->loc, loc)) == 0)
2325 {
2326 node->init = MIN (node->init, status);
2327 return;
2328 }
2329 else if (r > 0)
2330 break;
014a1138 2331
b5b8b0ac
AO
2332 node = (location_chain) pool_alloc (loc_chain_pool);
2333
2334 node->loc = loc;
2335 node->set_src = NULL;
2336 node->init = status;
2337 node->next = *nodep;
2338 *nodep = node;
014a1138
JZ
2339}
2340
b5b8b0ac
AO
2341/* Insert in DEST the intersection the locations present in both
2342 S1NODE and S2VAR, directly or indirectly. S1NODE is from a
2343 variable in DSM->cur, whereas S2VAR is from DSM->src. dvar is in
2344 DSM->dst. */
014a1138 2345
b5b8b0ac
AO
2346static void
2347intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
2348 location_chain s1node, variable s2var)
014a1138 2349{
b5b8b0ac
AO
2350 dataflow_set *s1set = dsm->cur;
2351 dataflow_set *s2set = dsm->src;
2352 location_chain found;
014a1138 2353
b5b8b0ac 2354 for (; s1node; s1node = s1node->next)
014a1138 2355 {
b5b8b0ac
AO
2356 if (s1node->loc == val)
2357 continue;
2358
2359 if ((found = find_loc_in_1pdv (s1node->loc, s2var,
2360 shared_hash_htab (s2set->vars))))
014a1138 2361 {
b5b8b0ac
AO
2362 insert_into_intersection (dest, s1node->loc,
2363 MIN (s1node->init, found->init));
2364 continue;
014a1138 2365 }
b5b8b0ac
AO
2366
2367 if (GET_CODE (s1node->loc) == VALUE
2368 && !VALUE_RECURSED_INTO (s1node->loc))
014a1138 2369 {
b5b8b0ac
AO
2370 decl_or_value dv = dv_from_value (s1node->loc);
2371 variable svar = shared_hash_find (s1set->vars, dv);
2372 if (svar)
2373 {
2374 if (svar->n_var_parts == 1)
2375 {
2376 VALUE_RECURSED_INTO (s1node->loc) = true;
2377 intersect_loc_chains (val, dest, dsm,
2378 svar->var_part[0].loc_chain,
2379 s2var);
2380 VALUE_RECURSED_INTO (s1node->loc) = false;
2381 }
2382 }
014a1138 2383 }
014a1138 2384
b5b8b0ac
AO
2385 /* ??? if the location is equivalent to any location in src,
2386 searched recursively
014a1138 2387
b5b8b0ac 2388 add to dst the values needed to represent the equivalence
014a1138 2389
b5b8b0ac
AO
2390 telling whether locations S is equivalent to another dv's
2391 location list:
014a1138 2392
b5b8b0ac 2393 for each location D in the list
014a1138 2394
b5b8b0ac 2395 if S and D satisfy rtx_equal_p, then it is present
014a1138 2396
b5b8b0ac 2397 else if D is a value, recurse without cycles
ac3bfd86 2398
b5b8b0ac 2399 else if S and D have the same CODE and MODE
af931390 2400
b5b8b0ac 2401 for each operand oS and the corresponding oD
014a1138 2402
b5b8b0ac 2403 if oS and oD are not equivalent, then S an D are not equivalent
014a1138 2404
b5b8b0ac 2405 else if they are RTX vectors
014a1138 2406
b5b8b0ac
AO
2407 if any vector oS element is not equivalent to its respective oD,
2408 then S and D are not equivalent
014a1138 2409
b5b8b0ac
AO
2410 */
2411
2412
2413 }
014a1138
JZ
2414}
2415
b5b8b0ac
AO
2416/* Return -1 if X should be before Y in a location list for a 1-part
2417 variable, 1 if Y should be before X, and 0 if they're equivalent
2418 and should not appear in the list. */
ca787200 2419
b5b8b0ac
AO
2420static int
2421loc_cmp (rtx x, rtx y)
ca787200 2422{
b5b8b0ac
AO
2423 int i, j, r;
2424 RTX_CODE code = GET_CODE (x);
2425 const char *fmt;
ca787200 2426
b5b8b0ac
AO
2427 if (x == y)
2428 return 0;
ca787200 2429
b5b8b0ac 2430 if (REG_P (x))
ca787200 2431 {
b5b8b0ac
AO
2432 if (!REG_P (y))
2433 return -1;
2434 gcc_assert (GET_MODE (x) == GET_MODE (y));
2435 if (REGNO (x) == REGNO (y))
2436 return 0;
2437 else if (REGNO (x) < REGNO (y))
2438 return -1;
2439 else
2440 return 1;
ca787200 2441 }
b5b8b0ac
AO
2442
2443 if (REG_P (y))
2444 return 1;
2445
2446 if (MEM_P (x))
ca787200 2447 {
b5b8b0ac
AO
2448 if (!MEM_P (y))
2449 return -1;
2450 gcc_assert (GET_MODE (x) == GET_MODE (y));
2451 return loc_cmp (XEXP (x, 0), XEXP (y, 0));
ca787200 2452 }
ca787200 2453
b5b8b0ac
AO
2454 if (MEM_P (y))
2455 return 1;
ca787200 2456
b5b8b0ac
AO
2457 if (GET_CODE (x) == VALUE)
2458 {
2459 if (GET_CODE (y) != VALUE)
2460 return -1;
2461 gcc_assert (GET_MODE (x) == GET_MODE (y));
2462 if (canon_value_cmp (x, y))
2463 return -1;
2464 else
2465 return 1;
2466 }
ca787200 2467
b5b8b0ac
AO
2468 if (GET_CODE (y) == VALUE)
2469 return 1;
ca787200 2470
b5b8b0ac
AO
2471 if (GET_CODE (x) == GET_CODE (y))
2472 /* Compare operands below. */;
2473 else if (GET_CODE (x) < GET_CODE (y))
2474 return -1;
2475 else
2476 return 1;
2477
2478 gcc_assert (GET_MODE (x) == GET_MODE (y));
2479
2480 fmt = GET_RTX_FORMAT (code);
2481 for (i = 0; i < GET_RTX_LENGTH (code); i++)
2482 switch (fmt[i])
2483 {
2484 case 'w':
2485 if (XWINT (x, i) == XWINT (y, i))
2486 break;
2487 else if (XWINT (x, i) < XWINT (y, i))
2488 return -1;
2489 else
2490 return 1;
2491
2492 case 'n':
2493 case 'i':
2494 if (XINT (x, i) == XINT (y, i))
2495 break;
2496 else if (XINT (x, i) < XINT (y, i))
2497 return -1;
2498 else
2499 return 1;
2500
2501 case 'V':
2502 case 'E':
2503 /* Compare the vector length first. */
2504 if (XVECLEN (x, i) == XVECLEN (y, i))
2505 /* Compare the vectors elements. */;
2506 else if (XVECLEN (x, i) < XVECLEN (y, i))
2507 return -1;
2508 else
2509 return 1;
2510
2511 for (j = 0; j < XVECLEN (x, i); j++)
2512 if ((r = loc_cmp (XVECEXP (x, i, j),
2513 XVECEXP (y, i, j))))
2514 return r;
2515 break;
2516
2517 case 'e':
2518 if ((r = loc_cmp (XEXP (x, i), XEXP (y, i))))
2519 return r;
2520 break;
2521
2522 case 'S':
2523 case 's':
2524 if (XSTR (x, i) == XSTR (y, i))
2525 break;
2526 if (!XSTR (x, i))
2527 return -1;
2528 if (!XSTR (y, i))
2529 return 1;
2530 if ((r = strcmp (XSTR (x, i), XSTR (y, i))) == 0)
2531 break;
2532 else if (r < 0)
2533 return -1;
2534 else
2535 return 1;
2536
2537 case 'u':
2538 /* These are just backpointers, so they don't matter. */
2539 break;
2540
2541 case '0':
2542 case 't':
2543 break;
2544
2545 /* It is believed that rtx's at this level will never
2546 contain anything but integers and other rtx's,
2547 except for within LABEL_REFs and SYMBOL_REFs. */
2548 default:
2549 gcc_unreachable ();
2550 }
2551
2552 return 0;
2553}
2554
2555/* If decl or value DVP refers to VALUE from *LOC, add backlinks
2556 from VALUE to DVP. */
2557
2558static int
2559add_value_chain (rtx *loc, void *dvp)
2560{
2561 if (GET_CODE (*loc) == VALUE && (void *) *loc != dvp)
2562 {
2563 decl_or_value dv = (decl_or_value) dvp;
2564 decl_or_value ldv = dv_from_value (*loc);
2565 value_chain vc, nvc;
2566 void **slot = htab_find_slot_with_hash (value_chains, ldv,
2567 dv_htab_hash (ldv), INSERT);
2568 if (!*slot)
2569 {
2570 vc = (value_chain) pool_alloc (value_chain_pool);
2571 vc->dv = ldv;
2572 vc->next = NULL;
2573 vc->refcount = 0;
2574 *slot = (void *) vc;
2575 }
2576 else
2577 {
2578 for (vc = ((value_chain) *slot)->next; vc; vc = vc->next)
2579 if (dv_as_opaque (vc->dv) == dv_as_opaque (dv))
2580 break;
2581 if (vc)
2582 {
2583 vc->refcount++;
2584 return 0;
2585 }
2586 }
2587 vc = (value_chain) *slot;
2588 nvc = (value_chain) pool_alloc (value_chain_pool);
2589 nvc->dv = dv;
2590 nvc->next = vc->next;
2591 nvc->refcount = 1;
2592 vc->next = nvc;
2593 }
2594 return 0;
2595}
2596
2597/* If decl or value DVP refers to VALUEs from within LOC, add backlinks
2598 from those VALUEs to DVP. */
2599
2600static void
2601add_value_chains (decl_or_value dv, rtx loc)
2602{
2603 if (GET_CODE (loc) == VALUE)
2604 {
2605 add_value_chain (&loc, dv_as_opaque (dv));
2606 return;
2607 }
2608 if (REG_P (loc))
2609 return;
2610 if (MEM_P (loc))
2611 loc = XEXP (loc, 0);
2612 for_each_rtx (&loc, add_value_chain, dv_as_opaque (dv));
2613}
2614
2615/* If CSELIB_VAL_PTR of value DV refer to VALUEs, add backlinks from those
2616 VALUEs to DV. */
2617
2618static void
2619add_cselib_value_chains (decl_or_value dv)
2620{
2621 struct elt_loc_list *l;
2622
2623 for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
2624 for_each_rtx (&l->loc, add_value_chain, dv_as_opaque (dv));
2625}
2626
2627/* If decl or value DVP refers to VALUE from *LOC, remove backlinks
2628 from VALUE to DVP. */
2629
2630static int
2631remove_value_chain (rtx *loc, void *dvp)
2632{
2633 if (GET_CODE (*loc) == VALUE && (void *) *loc != dvp)
2634 {
2635 decl_or_value dv = (decl_or_value) dvp;
2636 decl_or_value ldv = dv_from_value (*loc);
2637 value_chain vc, dvc = NULL;
2638 void **slot = htab_find_slot_with_hash (value_chains, ldv,
2639 dv_htab_hash (ldv), NO_INSERT);
2640 for (vc = (value_chain) *slot; vc->next; vc = vc->next)
2641 if (dv_as_opaque (vc->next->dv) == dv_as_opaque (dv))
2642 {
2643 dvc = vc->next;
2644 gcc_assert (dvc->refcount > 0);
2645 if (--dvc->refcount == 0)
2646 {
2647 vc->next = dvc->next;
2648 pool_free (value_chain_pool, dvc);
2649 if (vc->next == NULL && vc == (value_chain) *slot)
2650 {
2651 pool_free (value_chain_pool, vc);
2652 htab_clear_slot (value_chains, slot);
2653 }
2654 }
2655 return 0;
2656 }
2657 gcc_unreachable ();
2658 }
2659 return 0;
2660}
2661
2662/* If decl or value DVP refers to VALUEs from within LOC, remove backlinks
2663 from those VALUEs to DVP. */
2664
2665static void
2666remove_value_chains (decl_or_value dv, rtx loc)
2667{
2668 if (GET_CODE (loc) == VALUE)
2669 {
2670 remove_value_chain (&loc, dv_as_opaque (dv));
2671 return;
2672 }
2673 if (REG_P (loc))
2674 return;
2675 if (MEM_P (loc))
2676 loc = XEXP (loc, 0);
2677 for_each_rtx (&loc, remove_value_chain, dv_as_opaque (dv));
2678}
2679
2680/* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those
2681 VALUEs to DV. */
2682
2683static void
2684remove_cselib_value_chains (decl_or_value dv)
2685{
2686 struct elt_loc_list *l;
2687
2688 for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
2689 for_each_rtx (&l->loc, remove_value_chain, dv_as_opaque (dv));
2690}
2691
2692#if ENABLE_CHECKING
2693/* Check the order of entries in one-part variables. */
2694
2695static int
2696canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
2697{
2698 variable var = (variable) *slot;
2699 decl_or_value dv = var->dv;
2700 location_chain node, next;
2701
2702 if (!dv_onepart_p (dv))
2703 return 1;
2704
2705 gcc_assert (var->n_var_parts == 1);
2706 node = var->var_part[0].loc_chain;
2707 gcc_assert (node);
2708
2709 while ((next = node->next))
2710 {
2711 gcc_assert (loc_cmp (node->loc, next->loc) < 0);
2712 node = next;
2713 }
2714
2715 return 1;
2716}
2717#endif
2718
2719/* Mark with VALUE_RECURSED_INTO values that have neighbors that are
2720 more likely to be chosen as canonical for an equivalence set.
2721 Ensure less likely values can reach more likely neighbors, making
2722 the connections bidirectional. */
2723
2724static int
2725canonicalize_values_mark (void **slot, void *data)
2726{
2727 dataflow_set *set = (dataflow_set *)data;
2728 variable var = (variable) *slot;
2729 decl_or_value dv = var->dv;
2730 rtx val;
2731 location_chain node;
2732
2733 if (!dv_is_value_p (dv))
2734 return 1;
2735
2736 gcc_assert (var->n_var_parts == 1);
2737
2738 val = dv_as_value (dv);
2739
2740 for (node = var->var_part[0].loc_chain; node; node = node->next)
2741 if (GET_CODE (node->loc) == VALUE)
2742 {
2743 if (canon_value_cmp (node->loc, val))
2744 VALUE_RECURSED_INTO (val) = true;
2745 else
2746 {
2747 decl_or_value odv = dv_from_value (node->loc);
2748 void **oslot = shared_hash_find_slot_noinsert (set->vars, odv);
2749
2750 oslot = set_slot_part (set, val, oslot, odv, 0,
2751 node->init, NULL_RTX);
2752
2753 VALUE_RECURSED_INTO (node->loc) = true;
2754 }
2755 }
2756
2757 return 1;
2758}
2759
2760/* Remove redundant entries from equivalence lists in onepart
2761 variables, canonicalizing equivalence sets into star shapes. */
2762
2763static int
2764canonicalize_values_star (void **slot, void *data)
2765{
2766 dataflow_set *set = (dataflow_set *)data;
2767 variable var = (variable) *slot;
2768 decl_or_value dv = var->dv;
2769 location_chain node;
2770 decl_or_value cdv;
2771 rtx val, cval;
2772 void **cslot;
2773 bool has_value;
2774 bool has_marks;
2775
2776 if (!dv_onepart_p (dv))
2777 return 1;
2778
2779 gcc_assert (var->n_var_parts == 1);
2780
2781 if (dv_is_value_p (dv))
2782 {
2783 cval = dv_as_value (dv);
2784 if (!VALUE_RECURSED_INTO (cval))
2785 return 1;
2786 VALUE_RECURSED_INTO (cval) = false;
2787 }
2788 else
2789 cval = NULL_RTX;
2790
2791 restart:
2792 val = cval;
2793 has_value = false;
2794 has_marks = false;
2795
2796 gcc_assert (var->n_var_parts == 1);
2797
2798 for (node = var->var_part[0].loc_chain; node; node = node->next)
2799 if (GET_CODE (node->loc) == VALUE)
2800 {
2801 has_value = true;
2802 if (VALUE_RECURSED_INTO (node->loc))
2803 has_marks = true;
2804 if (canon_value_cmp (node->loc, cval))
2805 cval = node->loc;
2806 }
2807
2808 if (!has_value)
2809 return 1;
2810
2811 if (cval == val)
2812 {
2813 if (!has_marks || dv_is_decl_p (dv))
2814 return 1;
2815
2816 /* Keep it marked so that we revisit it, either after visiting a
2817 child node, or after visiting a new parent that might be
2818 found out. */
2819 VALUE_RECURSED_INTO (val) = true;
2820
2821 for (node = var->var_part[0].loc_chain; node; node = node->next)
2822 if (GET_CODE (node->loc) == VALUE
2823 && VALUE_RECURSED_INTO (node->loc))
2824 {
2825 cval = node->loc;
2826 restart_with_cval:
2827 VALUE_RECURSED_INTO (cval) = false;
2828 dv = dv_from_value (cval);
2829 slot = shared_hash_find_slot_noinsert (set->vars, dv);
2830 if (!slot)
2831 {
2832 gcc_assert (dv_is_decl_p (var->dv));
2833 /* The canonical value was reset and dropped.
2834 Remove it. */
2835 clobber_variable_part (set, NULL, var->dv, 0, NULL);
2836 return 1;
2837 }
2838 var = (variable)*slot;
2839 gcc_assert (dv_is_value_p (var->dv));
2840 if (var->n_var_parts == 0)
2841 return 1;
2842 gcc_assert (var->n_var_parts == 1);
2843 goto restart;
2844 }
2845
2846 VALUE_RECURSED_INTO (val) = false;
2847
2848 return 1;
2849 }
2850
2851 /* Push values to the canonical one. */
2852 cdv = dv_from_value (cval);
2853 cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
2854
2855 for (node = var->var_part[0].loc_chain; node; node = node->next)
2856 if (node->loc != cval)
2857 {
2858 cslot = set_slot_part (set, node->loc, cslot, cdv, 0,
2859 node->init, NULL_RTX);
2860 if (GET_CODE (node->loc) == VALUE)
2861 {
2862 decl_or_value ndv = dv_from_value (node->loc);
2863
2864 set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX,
2865 NO_INSERT);
2866
2867 if (canon_value_cmp (node->loc, val))
2868 {
2869 /* If it could have been a local minimum, it's not any more,
2870 since it's now neighbor to cval, so it may have to push
2871 to it. Conversely, if it wouldn't have prevailed over
2872 val, then whatever mark it has is fine: if it was to
2873 push, it will now push to a more canonical node, but if
2874 it wasn't, then it has already pushed any values it might
2875 have to. */
2876 VALUE_RECURSED_INTO (node->loc) = true;
2877 /* Make sure we visit node->loc by ensuring we cval is
2878 visited too. */
2879 VALUE_RECURSED_INTO (cval) = true;
2880 }
2881 else if (!VALUE_RECURSED_INTO (node->loc))
2882 /* If we have no need to "recurse" into this node, it's
2883 already "canonicalized", so drop the link to the old
2884 parent. */
2885 clobber_variable_part (set, cval, ndv, 0, NULL);
2886 }
2887 else if (GET_CODE (node->loc) == REG)
2888 {
2889 attrs list = set->regs[REGNO (node->loc)], *listp;
2890
2891 /* Change an existing attribute referring to dv so that it
2892 refers to cdv, removing any duplicate this might
2893 introduce, and checking that no previous duplicates
2894 existed, all in a single pass. */
2895
2896 while (list)
2897 {
2898 if (list->offset == 0
2899 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
2900 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
2901 break;
2902
2903 list = list->next;
2904 }
2905
2906 gcc_assert (list);
2907 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
2908 {
2909 list->dv = cdv;
2910 for (listp = &list->next; (list = *listp); listp = &list->next)
2911 {
2912 if (list->offset)
2913 continue;
2914
2915 if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
2916 {
2917 *listp = list->next;
2918 pool_free (attrs_pool, list);
2919 list = *listp;
2920 break;
2921 }
2922
2923 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv));
2924 }
2925 }
2926 else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
2927 {
2928 for (listp = &list->next; (list = *listp); listp = &list->next)
2929 {
2930 if (list->offset)
2931 continue;
2932
2933 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
2934 {
2935 *listp = list->next;
2936 pool_free (attrs_pool, list);
2937 list = *listp;
2938 break;
2939 }
2940
2941 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv));
2942 }
2943 }
2944 else
2945 gcc_unreachable ();
2946
2947#if ENABLE_CHECKING
2948 while (list)
2949 {
2950 if (list->offset == 0
2951 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
2952 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
2953 gcc_unreachable ();
2954
2955 list = list->next;
2956 }
2957#endif
2958 }
2959 }
2960
2961 if (val)
2962 cslot = set_slot_part (set, val, cslot, cdv, 0,
2963 VAR_INIT_STATUS_INITIALIZED, NULL_RTX);
2964
2965 slot = clobber_slot_part (set, cval, slot, 0, NULL);
2966
2967 /* Variable may have been unshared. */
2968 var = (variable)*slot;
2969 gcc_assert (var->n_var_parts && var->var_part[0].loc_chain->loc == cval
2970 && var->var_part[0].loc_chain->next == NULL);
2971
2972 if (VALUE_RECURSED_INTO (cval))
2973 goto restart_with_cval;
2974
2975 return 1;
2976}
2977
2978/* Combine variable or value in *S1SLOT (in DSM->cur) with the
2979 corresponding entry in DSM->src. Multi-part variables are combined
2980 with variable_union, whereas onepart dvs are combined with
2981 intersection. */
2982
2983static int
2984variable_merge_over_cur (void **s1slot, void *data)
2985{
2986 struct dfset_merge *dsm = (struct dfset_merge *)data;
2987 dataflow_set *dst = dsm->dst;
2988 void **dstslot;
2989 variable s1var = (variable) *s1slot;
2990 variable s2var, dvar = NULL;
2991 decl_or_value dv = s1var->dv;
2992 bool onepart = dv_onepart_p (dv);
2993 rtx val;
2994 hashval_t dvhash;
2995 location_chain node, *nodep;
2996
2997 /* If the incoming onepart variable has an empty location list, then
2998 the intersection will be just as empty. For other variables,
2999 it's always union. */
3000 gcc_assert (s1var->n_var_parts);
3001 gcc_assert (s1var->var_part[0].loc_chain);
3002
3003 if (!onepart)
3004 return variable_union (s1slot, dst);
3005
3006 gcc_assert (s1var->n_var_parts == 1);
3007 gcc_assert (s1var->var_part[0].offset == 0);
3008
3009 dvhash = dv_htab_hash (dv);
3010 if (dv_is_value_p (dv))
3011 val = dv_as_value (dv);
3012 else
3013 val = NULL;
3014
3015 s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash);
3016 if (!s2var)
3017 {
3018 dst_can_be_shared = false;
3019 return 1;
3020 }
3021
3022 dsm->src_onepart_cnt--;
3023 gcc_assert (s2var->var_part[0].loc_chain);
3024 gcc_assert (s2var->n_var_parts == 1);
3025 gcc_assert (s2var->var_part[0].offset == 0);
3026
3027 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3028 if (dstslot)
3029 {
3030 dvar = (variable)*dstslot;
3031 gcc_assert (dvar->refcount == 1);
3032 gcc_assert (dvar->n_var_parts == 1);
3033 gcc_assert (dvar->var_part[0].offset == 0);
3034 nodep = &dvar->var_part[0].loc_chain;
3035 }
3036 else
3037 {
3038 nodep = &node;
3039 node = NULL;
3040 }
3041
3042 if (!dstslot && !onepart_variable_different_p (s1var, s2var))
3043 {
3044 dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv,
3045 dvhash, INSERT);
3046 *dstslot = dvar = s2var;
3047 dvar->refcount++;
3048 }
3049 else
3050 {
3051 dst_can_be_shared = false;
3052
3053 intersect_loc_chains (val, nodep, dsm,
3054 s1var->var_part[0].loc_chain, s2var);
3055
3056 if (!dstslot)
3057 {
3058 if (node)
3059 {
3060 dvar = (variable) pool_alloc (dv_pool (dv));
3061 dvar->dv = dv;
3062 dvar->refcount = 1;
3063 dvar->n_var_parts = 1;
3064 dvar->var_part[0].offset = 0;
3065 dvar->var_part[0].loc_chain = node;
3066 dvar->var_part[0].cur_loc = node->loc;
3067
3068 dstslot
3069 = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
3070 INSERT);
3071 gcc_assert (!*dstslot);
3072 *dstslot = dvar;
3073 }
3074 else
3075 return 1;
3076 }
3077 }
3078
3079 nodep = &dvar->var_part[0].loc_chain;
3080 while ((node = *nodep))
3081 {
3082 location_chain *nextp = &node->next;
3083
3084 if (GET_CODE (node->loc) == REG)
3085 {
3086 attrs list;
3087
3088 for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
3089 if (GET_MODE (node->loc) == GET_MODE (list->loc)
3090 && dv_is_value_p (list->dv))
3091 break;
3092
3093 if (!list)
3094 attrs_list_insert (&dst->regs[REGNO (node->loc)],
3095 dv, 0, node->loc);
3096 /* If this value became canonical for another value that had
3097 this register, we want to leave it alone. */
3098 else if (dv_as_value (list->dv) != val)
3099 {
3100 dstslot = set_slot_part (dst, dv_as_value (list->dv),
3101 dstslot, dv, 0,
3102 node->init, NULL_RTX);
3103 dstslot = delete_slot_part (dst, node->loc, dstslot, 0);
3104
3105 /* Since nextp points into the removed node, we can't
3106 use it. The pointer to the next node moved to nodep.
3107 However, if the variable we're walking is unshared
3108 during our walk, we'll keep walking the location list
3109 of the previously-shared variable, in which case the
3110 node won't have been removed, and we'll want to skip
3111 it. That's why we test *nodep here. */
3112 if (*nodep != node)
3113 nextp = nodep;
3114 }
3115 }
3116 else
3117 /* Canonicalization puts registers first, so we don't have to
3118 walk it all. */
3119 break;
3120 nodep = nextp;
3121 }
3122
3123 if (dvar != (variable)*dstslot)
3124 dvar = (variable)*dstslot;
3125 nodep = &dvar->var_part[0].loc_chain;
3126
3127 if (val)
3128 {
3129 /* Mark all referenced nodes for canonicalization, and make sure
3130 we have mutual equivalence links. */
3131 VALUE_RECURSED_INTO (val) = true;
3132 for (node = *nodep; node; node = node->next)
3133 if (GET_CODE (node->loc) == VALUE)
3134 {
3135 VALUE_RECURSED_INTO (node->loc) = true;
3136 set_variable_part (dst, val, dv_from_value (node->loc), 0,
3137 node->init, NULL, INSERT);
3138 }
3139
3140 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3141 gcc_assert (*dstslot == dvar);
3142 canonicalize_values_star (dstslot, dst);
3143#ifdef ENABLE_CHECKING
3144 gcc_assert (dstslot
3145 == shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash));
3146#endif
3147 dvar = (variable)*dstslot;
3148 }
3149 else
3150 {
3151 bool has_value = false, has_other = false;
3152
3153 /* If we have one value and anything else, we're going to
3154 canonicalize this, so make sure all values have an entry in
3155 the table and are marked for canonicalization. */
3156 for (node = *nodep; node; node = node->next)
3157 {
3158 if (GET_CODE (node->loc) == VALUE)
3159 {
3160 /* If this was marked during register canonicalization,
3161 we know we have to canonicalize values. */
3162 if (has_value)
3163 has_other = true;
3164 has_value = true;
3165 if (has_other)
3166 break;
3167 }
3168 else
3169 {
3170 has_other = true;
3171 if (has_value)
3172 break;
3173 }
3174 }
3175
3176 if (has_value && has_other)
3177 {
3178 for (node = *nodep; node; node = node->next)
3179 {
3180 if (GET_CODE (node->loc) == VALUE)
3181 {
3182 decl_or_value dv = dv_from_value (node->loc);
3183 void **slot = NULL;
3184
3185 if (shared_hash_shared (dst->vars))
3186 slot = shared_hash_find_slot_noinsert (dst->vars, dv);
3187 if (!slot)
3188 slot = shared_hash_find_slot_unshare (&dst->vars, dv,
3189 INSERT);
3190 if (!*slot)
3191 {
3192 variable var = (variable) pool_alloc (dv_pool (dv));
3193 var->dv = dv;
3194 var->refcount = 1;
3195 var->n_var_parts = 1;
3196 var->var_part[0].offset = 0;
3197 var->var_part[0].loc_chain = NULL;
3198 var->var_part[0].cur_loc = NULL;
3199 *slot = var;
3200 }
3201
3202 VALUE_RECURSED_INTO (node->loc) = true;
3203 }
3204 }
3205
3206 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3207 gcc_assert (*dstslot == dvar);
3208 canonicalize_values_star (dstslot, dst);
3209#ifdef ENABLE_CHECKING
3210 gcc_assert (dstslot
3211 == shared_hash_find_slot_noinsert_1 (dst->vars,
3212 dv, dvhash));
3213#endif
3214 dvar = (variable)*dstslot;
3215 }
3216 }
3217
3218 if (!onepart_variable_different_p (dvar, s2var))
3219 {
3220 variable_htab_free (dvar);
3221 *dstslot = dvar = s2var;
3222 dvar->refcount++;
3223 }
3224 else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var))
3225 {
3226 variable_htab_free (dvar);
3227 *dstslot = dvar = s1var;
3228 dvar->refcount++;
3229 dst_can_be_shared = false;
3230 }
3231 else
3232 {
3233 if (dvar->refcount == 1)
3234 dvar->var_part[0].cur_loc = dvar->var_part[0].loc_chain->loc;
3235 dst_can_be_shared = false;
3236 }
3237
3238 return 1;
3239}
3240
3241/* Combine variable in *S1SLOT (in DSM->src) with the corresponding
3242 entry in DSM->src. Only multi-part variables are combined, using
3243 variable_union. onepart dvs were already combined with
3244 intersection in variable_merge_over_cur(). */
3245
3246static int
3247variable_merge_over_src (void **s2slot, void *data)
3248{
3249 struct dfset_merge *dsm = (struct dfset_merge *)data;
3250 dataflow_set *dst = dsm->dst;
3251 variable s2var = (variable) *s2slot;
3252 decl_or_value dv = s2var->dv;
3253 bool onepart = dv_onepart_p (dv);
3254
3255 if (!onepart)
3256 {
3257 void **dstp = shared_hash_find_slot (dst->vars, dv);
3258 *dstp = s2var;
3259 s2var->refcount++;
3260 return variable_canonicalize (dstp, dst);
3261 }
3262
3263 dsm->src_onepart_cnt++;
3264 return 1;
3265}
3266
3267/* Combine dataflow set information from SRC into DST, using PDST
3268 to carry over information across passes. */
3269
3270static void
3271dataflow_set_merge (dataflow_set *dst, dataflow_set *src)
3272{
3273 dataflow_set src2 = *dst;
3274 struct dfset_merge dsm;
3275 int i;
3276 size_t src_elems, dst_elems;
3277
3278 src_elems = htab_elements (shared_hash_htab (src->vars));
3279 dst_elems = htab_elements (shared_hash_htab (src2.vars));
3280 dataflow_set_init (dst);
3281 dst->stack_adjust = src2.stack_adjust;
3282 shared_hash_destroy (dst->vars);
3283 dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
3284 dst->vars->refcount = 1;
3285 dst->vars->htab
3286 = htab_create (MAX (src_elems, dst_elems), variable_htab_hash,
3287 variable_htab_eq, variable_htab_free);
3288
3289 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3290 attrs_list_mpdv_union (&dst->regs[i], src->regs[i], src2.regs[i]);
3291
3292 dsm.dst = dst;
3293 dsm.src = &src2;
3294 dsm.cur = src;
3295 dsm.src_onepart_cnt = 0;
3296
3297 htab_traverse (shared_hash_htab (dsm.src->vars), variable_merge_over_src,
3298 &dsm);
3299 htab_traverse (shared_hash_htab (dsm.cur->vars), variable_merge_over_cur,
3300 &dsm);
3301
3302 if (dsm.src_onepart_cnt)
3303 dst_can_be_shared = false;
3304
3305 dataflow_set_destroy (&src2);
3306}
3307
3308/* Mark register equivalences. */
3309
3310static void
3311dataflow_set_equiv_regs (dataflow_set *set)
3312{
3313 int i;
3314 attrs list, *listp;
3315
3316 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3317 {
3318 rtx canon[NUM_MACHINE_MODES];
3319
3320 memset (canon, 0, sizeof (canon));
3321
3322 for (list = set->regs[i]; list; list = list->next)
3323 if (list->offset == 0 && dv_is_value_p (list->dv))
3324 {
3325 rtx val = dv_as_value (list->dv);
3326 rtx *cvalp = &canon[(int)GET_MODE (val)];
3327 rtx cval = *cvalp;
3328
3329 if (canon_value_cmp (val, cval))
3330 *cvalp = val;
3331 }
3332
3333 for (list = set->regs[i]; list; list = list->next)
3334 if (list->offset == 0 && dv_onepart_p (list->dv))
3335 {
3336 rtx cval = canon[(int)GET_MODE (list->loc)];
3337
3338 if (!cval)
3339 continue;
3340
3341 if (dv_is_value_p (list->dv))
3342 {
3343 rtx val = dv_as_value (list->dv);
3344
3345 if (val == cval)
3346 continue;
3347
3348 VALUE_RECURSED_INTO (val) = true;
3349 set_variable_part (set, val, dv_from_value (cval), 0,
3350 VAR_INIT_STATUS_INITIALIZED,
3351 NULL, NO_INSERT);
3352 }
3353
3354 VALUE_RECURSED_INTO (cval) = true;
3355 set_variable_part (set, cval, list->dv, 0,
3356 VAR_INIT_STATUS_INITIALIZED, NULL, NO_INSERT);
3357 }
3358
3359 for (listp = &set->regs[i]; (list = *listp);
3360 listp = list ? &list->next : listp)
3361 if (list->offset == 0 && dv_onepart_p (list->dv))
3362 {
3363 rtx cval = canon[(int)GET_MODE (list->loc)];
3364 void **slot;
3365
3366 if (!cval)
3367 continue;
3368
3369 if (dv_is_value_p (list->dv))
3370 {
3371 rtx val = dv_as_value (list->dv);
3372 if (!VALUE_RECURSED_INTO (val))
3373 continue;
3374 }
3375
3376 slot = shared_hash_find_slot_noinsert (set->vars, list->dv);
3377 canonicalize_values_star (slot, set);
3378 if (*listp != list)
3379 list = NULL;
3380 }
3381 }
3382}
3383
3384/* Remove any redundant values in the location list of VAR, which must
3385 be unshared and 1-part. */
3386
3387static void
3388remove_duplicate_values (variable var)
3389{
3390 location_chain node, *nodep;
3391
3392 gcc_assert (dv_onepart_p (var->dv));
3393 gcc_assert (var->n_var_parts == 1);
3394 gcc_assert (var->refcount == 1);
3395
3396 for (nodep = &var->var_part[0].loc_chain; (node = *nodep); )
3397 {
3398 if (GET_CODE (node->loc) == VALUE)
3399 {
3400 if (VALUE_RECURSED_INTO (node->loc))
3401 {
3402 /* Remove duplicate value node. */
3403 *nodep = node->next;
3404 pool_free (loc_chain_pool, node);
3405 continue;
3406 }
3407 else
3408 VALUE_RECURSED_INTO (node->loc) = true;
3409 }
3410 nodep = &node->next;
3411 }
3412
3413 for (node = var->var_part[0].loc_chain; node; node = node->next)
3414 if (GET_CODE (node->loc) == VALUE)
3415 {
3416 gcc_assert (VALUE_RECURSED_INTO (node->loc));
3417 VALUE_RECURSED_INTO (node->loc) = false;
3418 }
3419}
3420
3421
3422/* Hash table iteration argument passed to variable_post_merge. */
3423struct dfset_post_merge
3424{
3425 /* The new input set for the current block. */
3426 dataflow_set *set;
3427 /* Pointer to the permanent input set for the current block, or
3428 NULL. */
3429 dataflow_set **permp;
3430};
3431
3432/* Create values for incoming expressions associated with one-part
3433 variables that don't have value numbers for them. */
3434
3435static int
3436variable_post_merge_new_vals (void **slot, void *info)
3437{
3438 struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
3439 dataflow_set *set = dfpm->set;
3440 variable var = (variable)*slot;
3441 location_chain node;
3442
3443 if (!dv_onepart_p (var->dv) || !var->n_var_parts)
3444 return 1;
3445
3446 gcc_assert (var->n_var_parts == 1);
3447
3448 if (dv_is_decl_p (var->dv))
3449 {
3450 bool check_dupes = false;
3451
3452 restart:
3453 for (node = var->var_part[0].loc_chain; node; node = node->next)
3454 {
3455 if (GET_CODE (node->loc) == VALUE)
3456 gcc_assert (!VALUE_RECURSED_INTO (node->loc));
3457 else if (GET_CODE (node->loc) == REG)
3458 {
3459 attrs att, *attp, *curp = NULL;
3460
3461 if (var->refcount != 1)
3462 {
3463 slot = unshare_variable (set, slot, var,
3464 VAR_INIT_STATUS_INITIALIZED);
3465 var = (variable)*slot;
3466 goto restart;
3467 }
3468
3469 for (attp = &set->regs[REGNO (node->loc)]; (att = *attp);
3470 attp = &att->next)
3471 if (att->offset == 0
3472 && GET_MODE (att->loc) == GET_MODE (node->loc))
3473 {
3474 if (dv_is_value_p (att->dv))
3475 {
3476 rtx cval = dv_as_value (att->dv);
3477 node->loc = cval;
3478 check_dupes = true;
3479 break;
3480 }
3481 else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv))
3482 curp = attp;
3483 }
3484
3485 if (!curp)
3486 {
3487 curp = attp;
3488 while (*curp)
3489 if ((*curp)->offset == 0
3490 && GET_MODE ((*curp)->loc) == GET_MODE (node->loc)
3491 && dv_as_opaque ((*curp)->dv) == dv_as_opaque (var->dv))
3492 break;
3493 else
3494 curp = &(*curp)->next;
3495 gcc_assert (*curp);
3496 }
3497
3498 if (!att)
3499 {
3500 decl_or_value cdv;
3501 rtx cval;
3502
3503 if (!*dfpm->permp)
3504 {
3505 *dfpm->permp = XNEW (dataflow_set);
3506 dataflow_set_init (*dfpm->permp);
3507 }
3508
3509 for (att = (*dfpm->permp)->regs[REGNO (node->loc)];
3510 att; att = att->next)
3511 if (GET_MODE (att->loc) == GET_MODE (node->loc))
3512 {
3513 gcc_assert (att->offset == 0);
3514 gcc_assert (dv_is_value_p (att->dv));
3515 val_reset (set, att->dv);
3516 break;
3517 }
3518
3519 if (att)
3520 {
3521 cdv = att->dv;
3522 cval = dv_as_value (cdv);
3523 }
3524 else
3525 {
3526 /* Create a unique value to hold this register,
3527 that ought to be found and reused in
3528 subsequent rounds. */
3529 cselib_val *v;
3530 gcc_assert (!cselib_lookup (node->loc,
3531 GET_MODE (node->loc), 0));
3532 v = cselib_lookup (node->loc, GET_MODE (node->loc), 1);
3533 cselib_preserve_value (v);
3534 cselib_invalidate_rtx (node->loc);
3535 cval = v->val_rtx;
3536 cdv = dv_from_value (cval);
3537 if (dump_file)
3538 fprintf (dump_file,
3539 "Created new value %i for reg %i\n",
3540 v->value, REGNO (node->loc));
3541 }
3542
3543 var_reg_decl_set (*dfpm->permp, node->loc,
3544 VAR_INIT_STATUS_INITIALIZED,
3545 cdv, 0, NULL, INSERT);
3546
3547 node->loc = cval;
3548 check_dupes = true;
3549 }
3550
3551 /* Remove attribute referring to the decl, which now
3552 uses the value for the register, already existing or
3553 to be added when we bring perm in. */
3554 att = *curp;
3555 *curp = att->next;
3556 pool_free (attrs_pool, att);
3557 }
3558 }
3559
3560 if (check_dupes)
3561 remove_duplicate_values (var);
3562 }
3563
3564 return 1;
3565}
3566
3567/* Reset values in the permanent set that are not associated with the
3568 chosen expression. */
3569
3570static int
3571variable_post_merge_perm_vals (void **pslot, void *info)
3572{
3573 struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
3574 dataflow_set *set = dfpm->set;
3575 variable pvar = (variable)*pslot, var;
3576 location_chain pnode;
3577 decl_or_value dv;
3578 attrs att;
3579
3580 gcc_assert (dv_is_value_p (pvar->dv));
3581 gcc_assert (pvar->n_var_parts == 1);
3582 pnode = pvar->var_part[0].loc_chain;
3583 gcc_assert (pnode);
3584 gcc_assert (!pnode->next);
3585 gcc_assert (REG_P (pnode->loc));
3586
3587 dv = pvar->dv;
3588
3589 var = shared_hash_find (set->vars, dv);
3590 if (var)
3591 {
3592 if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
3593 return 1;
3594 val_reset (set, dv);
3595 }
3596
3597 for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next)
3598 if (att->offset == 0
3599 && GET_MODE (att->loc) == GET_MODE (pnode->loc)
3600 && dv_is_value_p (att->dv))
3601 break;
3602
3603 /* If there is a value associated with this register already, create
3604 an equivalence. */
3605 if (att && dv_as_value (att->dv) != dv_as_value (dv))
3606 {
3607 rtx cval = dv_as_value (att->dv);
3608 set_variable_part (set, cval, dv, 0, pnode->init, NULL, INSERT);
3609 set_variable_part (set, dv_as_value (dv), att->dv, 0, pnode->init,
3610 NULL, INSERT);
3611 }
3612 else if (!att)
3613 {
3614 attrs_list_insert (&set->regs[REGNO (pnode->loc)],
3615 dv, 0, pnode->loc);
3616 variable_union (pslot, set);
3617 }
3618
3619 return 1;
3620}
3621
3622/* Just checking stuff and registering register attributes for
3623 now. */
3624
3625static void
3626dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
3627{
3628 struct dfset_post_merge dfpm;
3629
3630 dfpm.set = set;
3631 dfpm.permp = permp;
3632
3633 htab_traverse (shared_hash_htab (set->vars), variable_post_merge_new_vals,
3634 &dfpm);
3635 if (*permp)
3636 htab_traverse (shared_hash_htab ((*permp)->vars),
3637 variable_post_merge_perm_vals, &dfpm);
3638 htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set);
3639}
3640
3641/* Return a node whose loc is a MEM that refers to EXPR in the
3642 location list of a one-part variable or value VAR, or in that of
3643 any values recursively mentioned in the location lists. */
3644
3645static location_chain
3646find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
3647{
3648 location_chain node;
3649 decl_or_value dv;
3650 variable var;
3651 location_chain where = NULL;
3652
3653 if (!val)
3654 return NULL;
3655
3656 gcc_assert (GET_CODE (val) == VALUE);
3657
3658 gcc_assert (!VALUE_RECURSED_INTO (val));
3659
3660 dv = dv_from_value (val);
3661 var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
3662
3663 if (!var)
3664 return NULL;
3665
3666 gcc_assert (dv_onepart_p (var->dv));
3667
3668 if (!var->n_var_parts)
3669 return NULL;
3670
3671 gcc_assert (var->var_part[0].offset == 0);
3672
3673 VALUE_RECURSED_INTO (val) = true;
3674
3675 for (node = var->var_part[0].loc_chain; node; node = node->next)
3676 if (MEM_P (node->loc) && MEM_EXPR (node->loc) == expr
3677 && MEM_OFFSET (node->loc) == 0)
3678 {
3679 where = node;
3680 break;
3681 }
3682 else if (GET_CODE (node->loc) == VALUE
3683 && !VALUE_RECURSED_INTO (node->loc)
3684 && (where = find_mem_expr_in_1pdv (expr, node->loc, vars)))
3685 break;
3686
3687 VALUE_RECURSED_INTO (val) = false;
3688
3689 return where;
3690}
3691
3692/* Remove all MEMs from the location list of a hash table entry for a
3693 one-part variable, except those whose MEM attributes map back to
3694 the variable itself, directly or within a VALUE.
3695
3696 ??? We could also preserve MEMs that reference stack slots that are
3697 annotated as not addressable. This is arguably even more reliable
3698 than the current heuristic. */
3699
3700static int
3701dataflow_set_preserve_mem_locs (void **slot, void *data)
3702{
3703 dataflow_set *set = (dataflow_set *) data;
3704 variable var = (variable) *slot;
3705
3706 if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv))
3707 {
3708 tree decl = dv_as_decl (var->dv);
3709 location_chain loc, *locp;
3710
3711 if (!var->n_var_parts)
3712 return 1;
3713
3714 gcc_assert (var->n_var_parts == 1);
3715
3716 if (var->refcount > 1 || shared_hash_shared (set->vars))
3717 {
3718 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
3719 {
3720 /* We want to remove a MEM that doesn't refer to DECL. */
3721 if (GET_CODE (loc->loc) == MEM
3722 && (MEM_EXPR (loc->loc) != decl
3723 || MEM_OFFSET (loc->loc)))
3724 break;
3725 /* We want to move here a MEM that does refer to DECL. */
3726 else if (GET_CODE (loc->loc) == VALUE
3727 && find_mem_expr_in_1pdv (decl, loc->loc,
3728 shared_hash_htab (set->vars)))
3729 break;
3730 }
3731
3732 if (!loc)
3733 return 1;
3734
3735 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
3736 var = (variable)*slot;
3737 gcc_assert (var->n_var_parts == 1);
3738 }
3739
3740 for (locp = &var->var_part[0].loc_chain, loc = *locp;
3741 loc; loc = *locp)
3742 {
3743 rtx old_loc = loc->loc;
3744 if (GET_CODE (old_loc) == VALUE)
3745 {
3746 location_chain mem_node
3747 = find_mem_expr_in_1pdv (decl, loc->loc,
3748 shared_hash_htab (set->vars));
3749
3750 /* ??? This picks up only one out of multiple MEMs that
3751 refer to the same variable. Do we ever need to be
3752 concerned about dealing with more than one, or, given
3753 that they should all map to the same variable
3754 location, their addresses will have been merged and
3755 they will be regarded as equivalent? */
3756 if (mem_node)
3757 {
3758 loc->loc = mem_node->loc;
3759 loc->set_src = mem_node->set_src;
3760 loc->init = MIN (loc->init, mem_node->init);
3761 }
3762 }
3763
3764 if (GET_CODE (loc->loc) != MEM
3765 || (MEM_EXPR (loc->loc) == decl
3766 && MEM_OFFSET (loc->loc) == 0))
3767 {
3768 if (old_loc != loc->loc && emit_notes)
3769 {
3770 add_value_chains (var->dv, loc->loc);
3771 remove_value_chains (var->dv, old_loc);
3772 }
3773 locp = &loc->next;
3774 continue;
3775 }
3776
3777 if (emit_notes)
3778 remove_value_chains (var->dv, old_loc);
3779 *locp = loc->next;
3780 pool_free (loc_chain_pool, loc);
3781 }
3782
3783 if (!var->var_part[0].loc_chain)
3784 {
3785 var->n_var_parts--;
3786 if (emit_notes && dv_is_value_p (var->dv))
3787 remove_cselib_value_chains (var->dv);
3788 variable_was_changed (var, set);
3789 }
3790 }
3791
3792 return 1;
3793}
3794
3795/* Remove all MEMs from the location list of a hash table entry for a
3796 value. */
3797
3798static int
3799dataflow_set_remove_mem_locs (void **slot, void *data)
3800{
3801 dataflow_set *set = (dataflow_set *) data;
3802 variable var = (variable) *slot;
3803
3804 if (dv_is_value_p (var->dv))
3805 {
3806 location_chain loc, *locp;
3807 bool changed = false;
3808
3809 gcc_assert (var->n_var_parts == 1);
3810
3811 if (var->refcount > 1 || shared_hash_shared (set->vars))
3812 {
3813 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
3814 if (GET_CODE (loc->loc) == MEM)
3815 break;
3816
3817 if (!loc)
3818 return 1;
3819
3820 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
3821 var = (variable)*slot;
3822 gcc_assert (var->n_var_parts == 1);
3823 }
3824
3825 for (locp = &var->var_part[0].loc_chain, loc = *locp;
3826 loc; loc = *locp)
3827 {
3828 if (GET_CODE (loc->loc) != MEM)
3829 {
3830 locp = &loc->next;
3831 continue;
3832 }
3833
3834 if (emit_notes)
3835 remove_value_chains (var->dv, loc->loc);
3836 *locp = loc->next;
3837 /* If we have deleted the location which was last emitted
3838 we have to emit new location so add the variable to set
3839 of changed variables. */
3840 if (var->var_part[0].cur_loc
3841 && rtx_equal_p (loc->loc, var->var_part[0].cur_loc))
3842 changed = true;
3843 pool_free (loc_chain_pool, loc);
3844 }
3845
3846 if (!var->var_part[0].loc_chain)
3847 {
3848 var->n_var_parts--;
3849 if (emit_notes && dv_is_value_p (var->dv))
3850 remove_cselib_value_chains (var->dv);
3851 gcc_assert (changed);
3852 }
3853 if (changed)
3854 {
3855 if (var->n_var_parts && var->var_part[0].loc_chain)
3856 var->var_part[0].cur_loc = var->var_part[0].loc_chain->loc;
3857 variable_was_changed (var, set);
3858 }
3859 }
3860
3861 return 1;
3862}
3863
3864/* Remove all variable-location information about call-clobbered
3865 registers, as well as associations between MEMs and VALUEs. */
3866
3867static void
3868dataflow_set_clear_at_call (dataflow_set *set)
3869{
3870 int r;
3871
3872 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
3873 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
3874 var_regno_delete (set, r);
3875
3876 if (MAY_HAVE_DEBUG_INSNS)
3877 {
3878 set->traversed_vars = set->vars;
3879 htab_traverse (shared_hash_htab (set->vars),
3880 dataflow_set_preserve_mem_locs, set);
3881 set->traversed_vars = set->vars;
3882 htab_traverse (shared_hash_htab (set->vars), dataflow_set_remove_mem_locs,
3883 set);
3884 set->traversed_vars = NULL;
3885 }
3886}
3887
3888/* Flag whether two dataflow sets being compared contain different data. */
3889static bool
3890dataflow_set_different_value;
3891
3892static bool
3893variable_part_different_p (variable_part *vp1, variable_part *vp2)
3894{
3895 location_chain lc1, lc2;
3896
3897 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
3898 {
3899 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
3900 {
3901 if (REG_P (lc1->loc) && REG_P (lc2->loc))
3902 {
3903 if (REGNO (lc1->loc) == REGNO (lc2->loc))
3904 break;
3905 }
3906 if (rtx_equal_p (lc1->loc, lc2->loc))
3907 break;
3908 }
3909 if (!lc2)
3910 return true;
3911 }
3912 return false;
3913}
3914
3915/* Return true if one-part variables VAR1 and VAR2 are different.
3916 They must be in canonical order. */
3917
3918static bool
3919onepart_variable_different_p (variable var1, variable var2)
3920{
3921 location_chain lc1, lc2;
3922
3923 if (var1 == var2)
3924 return false;
3925
3926 gcc_assert (var1->n_var_parts == 1);
3927 gcc_assert (var2->n_var_parts == 1);
3928
3929 lc1 = var1->var_part[0].loc_chain;
3930 lc2 = var2->var_part[0].loc_chain;
3931
3932 gcc_assert (lc1);
3933 gcc_assert (lc2);
3934
3935 while (lc1 && lc2)
3936 {
3937 if (loc_cmp (lc1->loc, lc2->loc))
3938 return true;
3939 lc1 = lc1->next;
3940 lc2 = lc2->next;
3941 }
3942
3943 return lc1 != lc2;
3944}
3945
3946/* Return true if variables VAR1 and VAR2 are different.
3947 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
3948 variable part. */
3949
3950static bool
3951variable_different_p (variable var1, variable var2,
3952 bool compare_current_location)
3953{
3954 int i;
3955
3956 if (var1 == var2)
3957 return false;
3958
3959 if (var1->n_var_parts != var2->n_var_parts)
3960 return true;
3961
3962 for (i = 0; i < var1->n_var_parts; i++)
3963 {
3964 if (var1->var_part[i].offset != var2->var_part[i].offset)
3965 return true;
3966 if (compare_current_location)
3967 {
3968 if (!((REG_P (var1->var_part[i].cur_loc)
3969 && REG_P (var2->var_part[i].cur_loc)
3970 && (REGNO (var1->var_part[i].cur_loc)
3971 == REGNO (var2->var_part[i].cur_loc)))
3972 || rtx_equal_p (var1->var_part[i].cur_loc,
3973 var2->var_part[i].cur_loc)))
3974 return true;
3975 }
3976 /* One-part values have locations in a canonical order. */
3977 if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv))
3978 {
3979 gcc_assert (var1->n_var_parts == 1);
3980 gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
3981 return onepart_variable_different_p (var1, var2);
3982 }
3983 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
3984 return true;
3985 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
3986 return true;
3987 }
3988 return false;
3989}
3990
3991/* Compare variable *SLOT with the same variable in hash table DATA
3992 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
3993
3994static int
3995dataflow_set_different_1 (void **slot, void *data)
3996{
3997 htab_t htab = (htab_t) data;
3998 variable var1, var2;
3999
4000 var1 = (variable) *slot;
4001 var2 = (variable) htab_find_with_hash (htab, var1->dv,
4002 dv_htab_hash (var1->dv));
4003 if (!var2)
4004 {
4005 dataflow_set_different_value = true;
4006
4007 if (dump_file && (dump_flags & TDF_DETAILS))
4008 {
4009 fprintf (dump_file, "dataflow difference found: removal of:\n");
4010 dump_variable (var1);
4011 }
4012
4013 /* Stop traversing the hash table. */
4014 return 0;
4015 }
4016
4017 if (variable_different_p (var1, var2, false))
4018 {
4019 dataflow_set_different_value = true;
4020
4021 if (dump_file && (dump_flags & TDF_DETAILS))
4022 {
4023 fprintf (dump_file, "dataflow difference found: old and new follow:\n");
4024 dump_variable (var1);
4025 dump_variable (var2);
4026 }
4027
4028 /* Stop traversing the hash table. */
4029 return 0;
4030 }
4031
4032 /* Continue traversing the hash table. */
4033 return 1;
4034}
4035
4036/* Return true if dataflow sets OLD_SET and NEW_SET differ. */
4037
4038static bool
4039dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
4040{
4041 if (old_set->vars == new_set->vars)
4042 return false;
4043
4044 if (htab_elements (shared_hash_htab (old_set->vars))
4045 != htab_elements (shared_hash_htab (new_set->vars)))
4046 return true;
4047
4048 dataflow_set_different_value = false;
4049
4050 htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1,
4051 shared_hash_htab (new_set->vars));
4052 /* No need to traverse the second hashtab, if both have the same number
4053 of elements and the second one had all entries found in the first one,
4054 then it can't have any extra entries. */
4055 return dataflow_set_different_value;
4056}
4057
4058/* Free the contents of dataflow set SET. */
4059
4060static void
4061dataflow_set_destroy (dataflow_set *set)
4062{
4063 int i;
4064
4065 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4066 attrs_list_clear (&set->regs[i]);
4067
4068 shared_hash_destroy (set->vars);
4069 set->vars = NULL;
4070}
4071
4072/* Return true if RTL X contains a SYMBOL_REF. */
4073
4074static bool
4075contains_symbol_ref (rtx x)
4076{
4077 const char *fmt;
4078 RTX_CODE code;
4079 int i;
4080
4081 if (!x)
4082 return false;
4083
4084 code = GET_CODE (x);
4085 if (code == SYMBOL_REF)
4086 return true;
4087
4088 fmt = GET_RTX_FORMAT (code);
4089 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4090 {
4091 if (fmt[i] == 'e')
4092 {
4093 if (contains_symbol_ref (XEXP (x, i)))
4094 return true;
4095 }
4096 else if (fmt[i] == 'E')
4097 {
4098 int j;
4099 for (j = 0; j < XVECLEN (x, i); j++)
4100 if (contains_symbol_ref (XVECEXP (x, i, j)))
4101 return true;
4102 }
4103 }
4104
4105 return false;
4106}
4107
4108/* Shall EXPR be tracked? */
4109
4110static bool
4111track_expr_p (tree expr, bool need_rtl)
4112{
4113 rtx decl_rtl;
4114 tree realdecl;
4115
0ca5af51
AO
4116 if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
4117 return DECL_RTL_SET_P (expr);
4118
b5b8b0ac
AO
4119 /* If EXPR is not a parameter or a variable do not track it. */
4120 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
4121 return 0;
4122
4123 /* It also must have a name... */
4124 if (!DECL_NAME (expr))
4125 return 0;
4126
4127 /* ... and a RTL assigned to it. */
4128 decl_rtl = DECL_RTL_IF_SET (expr);
4129 if (!decl_rtl && need_rtl)
4130 return 0;
4131
4132 /* If this expression is really a debug alias of some other declaration, we
4133 don't need to track this expression if the ultimate declaration is
4134 ignored. */
4135 realdecl = expr;
4136 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
4137 {
4138 realdecl = DECL_DEBUG_EXPR (realdecl);
4139 /* ??? We don't yet know how to emit DW_OP_piece for variable
4140 that has been SRA'ed. */
4141 if (!DECL_P (realdecl))
4142 return 0;
4143 }
4144
4145 /* Do not track EXPR if REALDECL it should be ignored for debugging
4146 purposes. */
4147 if (DECL_IGNORED_P (realdecl))
4148 return 0;
4149
4150 /* Do not track global variables until we are able to emit correct location
4151 list for them. */
4152 if (TREE_STATIC (realdecl))
4153 return 0;
4154
4155 /* When the EXPR is a DECL for alias of some variable (see example)
4156 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
4157 DECL_RTL contains SYMBOL_REF.
4158
4159 Example:
4160 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
4161 char **_dl_argv;
4162 */
4163 if (decl_rtl && MEM_P (decl_rtl)
4164 && contains_symbol_ref (XEXP (decl_rtl, 0)))
4165 return 0;
4166
4167 /* If RTX is a memory it should not be very large (because it would be
4168 an array or struct). */
4169 if (decl_rtl && MEM_P (decl_rtl))
4170 {
4171 /* Do not track structures and arrays. */
4172 if (GET_MODE (decl_rtl) == BLKmode
4173 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
4174 return 0;
4175 if (MEM_SIZE (decl_rtl)
4176 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
4177 return 0;
4178 }
4179
4180 DECL_CHANGED (expr) = 0;
4181 DECL_CHANGED (realdecl) = 0;
4182 return 1;
4183}
4184
4185/* Determine whether a given LOC refers to the same variable part as
4186 EXPR+OFFSET. */
4187
4188static bool
4189same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
4190{
4191 tree expr2;
4192 HOST_WIDE_INT offset2;
4193
4194 if (! DECL_P (expr))
4195 return false;
4196
4197 if (REG_P (loc))
4198 {
4199 expr2 = REG_EXPR (loc);
4200 offset2 = REG_OFFSET (loc);
4201 }
4202 else if (MEM_P (loc))
4203 {
4204 expr2 = MEM_EXPR (loc);
4205 offset2 = INT_MEM_OFFSET (loc);
4206 }
4207 else
4208 return false;
4209
4210 if (! expr2 || ! DECL_P (expr2))
4211 return false;
4212
4213 expr = var_debug_decl (expr);
4214 expr2 = var_debug_decl (expr2);
4215
4216 return (expr == expr2 && offset == offset2);
4217}
4218
4219/* LOC is a REG or MEM that we would like to track if possible.
38ae7651
RS
4220 If EXPR is null, we don't know what expression LOC refers to,
4221 otherwise it refers to EXPR + OFFSET. STORE_REG_P is true if
4222 LOC is an lvalue register.
94a7682d 4223
38ae7651
RS
4224 Return true if EXPR is nonnull and if LOC, or some lowpart of it,
4225 is something we can track. When returning true, store the mode of
4226 the lowpart we can track in *MODE_OUT (if nonnull) and its offset
4227 from EXPR in *OFFSET_OUT (if nonnull). */
94a7682d 4228
38ae7651
RS
4229static bool
4230track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
4231 enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
94a7682d
RS
4232{
4233 enum machine_mode mode;
4234
b5b8b0ac 4235 if (expr == NULL || !track_expr_p (expr, true))
38ae7651
RS
4236 return false;
4237
4238 /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
4239 whole subreg, but only the old inner part is really relevant. */
4240 mode = GET_MODE (loc);
4241 if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
94a7682d
RS
4242 {
4243 enum machine_mode pseudo_mode;
4244
38ae7651 4245 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
94a7682d 4246 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
38ae7651
RS
4247 {
4248 offset += byte_lowpart_offset (pseudo_mode, mode);
4249 mode = pseudo_mode;
4250 }
4251 }
4252
4253 /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
4254 Do the same if we are storing to a register and EXPR occupies
4255 the whole of register LOC; in that case, the whole of EXPR is
4256 being changed. We exclude complex modes from the second case
4257 because the real and imaginary parts are represented as separate
4258 pseudo registers, even if the whole complex value fits into one
4259 hard register. */
4260 if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
4261 || (store_reg_p
4262 && !COMPLEX_MODE_P (DECL_MODE (expr))
4263 && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
4264 && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
4265 {
4266 mode = DECL_MODE (expr);
4267 offset = 0;
94a7682d 4268 }
38ae7651
RS
4269
4270 if (offset < 0 || offset >= MAX_VAR_PARTS)
4271 return false;
4272
4273 if (mode_out)
4274 *mode_out = mode;
4275 if (offset_out)
4276 *offset_out = offset;
4277 return true;
94a7682d
RS
4278}
4279
4280/* Return the MODE lowpart of LOC, or null if LOC is not something we
4281 want to track. When returning nonnull, make sure that the attributes
4282 on the returned value are updated. */
4283
4284static rtx
4285var_lowpart (enum machine_mode mode, rtx loc)
4286{
38ae7651 4287 unsigned int offset, reg_offset, regno;
94a7682d
RS
4288
4289 if (!REG_P (loc) && !MEM_P (loc))
4290 return NULL;
4291
4292 if (GET_MODE (loc) == mode)
4293 return loc;
4294
b5b8b0ac
AO
4295 offset = byte_lowpart_offset (mode, GET_MODE (loc));
4296
4297 if (MEM_P (loc))
4298 return adjust_address_nv (loc, mode, offset);
4299
4300 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
4301 regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
4302 reg_offset, mode);
4303 return gen_rtx_REG_offset (loc, mode, regno, offset);
4304}
4305
4306/* Carry information about uses and stores while walking rtx. */
4307
4308struct count_use_info
4309{
4310 /* The insn where the RTX is. */
4311 rtx insn;
4312
4313 /* The basic block where insn is. */
4314 basic_block bb;
4315
4316 /* The array of n_sets sets in the insn, as determined by cselib. */
4317 struct cselib_set *sets;
4318 int n_sets;
4319
4320 /* True if we're counting stores, false otherwise. */
4321 bool store_p;
4322};
4323
4324/* Find a VALUE corresponding to X. */
4325
4326static inline cselib_val *
4327find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
4328{
4329 int i;
4330
4331 if (cui->sets)
4332 {
4333 /* This is called after uses are set up and before stores are
4334 processed bycselib, so it's safe to look up srcs, but not
4335 dsts. So we look up expressions that appear in srcs or in
4336 dest expressions, but we search the sets array for dests of
4337 stores. */
4338 if (cui->store_p)
4339 {
4340 for (i = 0; i < cui->n_sets; i++)
4341 if (cui->sets[i].dest == x)
4342 return cui->sets[i].src_elt;
4343 }
4344 else
4345 return cselib_lookup (x, mode, 0);
4346 }
4347
4348 return NULL;
4349}
4350
4351/* Replace all registers and addresses in an expression with VALUE
4352 expressions that map back to them, unless the expression is a
4353 register. If no mapping is or can be performed, returns NULL. */
4354
4355static rtx
4356replace_expr_with_values (rtx loc)
4357{
4358 if (REG_P (loc))
4359 return NULL;
4360 else if (MEM_P (loc))
4361 {
d4ebfa65
BE
4362 enum machine_mode address_mode
4363 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (loc));
4364 cselib_val *addr = cselib_lookup (XEXP (loc, 0), address_mode, 0);
b5b8b0ac
AO
4365 if (addr)
4366 return replace_equiv_address_nv (loc, addr->val_rtx);
4367 else
4368 return NULL;
4369 }
4370 else
4371 return cselib_subst_to_values (loc);
4372}
4373
4374/* Determine what kind of micro operation to choose for a USE. Return
4375 MO_CLOBBER if no micro operation is to be generated. */
4376
4377static enum micro_operation_type
4378use_type (rtx *loc, struct count_use_info *cui, enum machine_mode *modep)
4379{
4380 tree expr;
4381 cselib_val *val;
4382
4383 if (cui && cui->sets)
4384 {
4385 if (GET_CODE (*loc) == VAR_LOCATION)
4386 {
4387 if (track_expr_p (PAT_VAR_LOCATION_DECL (*loc), false))
4388 {
4389 rtx ploc = PAT_VAR_LOCATION_LOC (*loc);
4390 cselib_val *val = cselib_lookup (ploc, GET_MODE (*loc), 1);
4391
4392 /* ??? flag_float_store and volatile mems are never
4393 given values, but we could in theory use them for
4394 locations. */
4395 gcc_assert (val || 1);
4396 return MO_VAL_LOC;
4397 }
4398 else
4399 return MO_CLOBBER;
4400 }
4401
4402 if ((REG_P (*loc) || MEM_P (*loc))
4403 && (val = find_use_val (*loc, GET_MODE (*loc), cui)))
4404 {
4405 if (modep)
4406 *modep = GET_MODE (*loc);
4407 if (cui->store_p)
4408 {
4409 if (REG_P (*loc)
4410 || cselib_lookup (XEXP (*loc, 0), GET_MODE (*loc), 0))
4411 return MO_VAL_SET;
4412 }
4413 else if (!cselib_preserved_value_p (val))
4414 return MO_VAL_USE;
4415 }
4416 }
4417
4418 if (REG_P (*loc))
4419 {
4420 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
4421
4422 expr = REG_EXPR (*loc);
4423
4424 if (!expr)
4425 return MO_USE_NO_VAR;
4426 else if (target_for_debug_bind (var_debug_decl (expr)))
4427 return MO_CLOBBER;
4428 else if (track_loc_p (*loc, expr, REG_OFFSET (*loc),
4429 false, modep, NULL))
4430 return MO_USE;
4431 else
4432 return MO_USE_NO_VAR;
4433 }
4434 else if (MEM_P (*loc))
4435 {
4436 expr = MEM_EXPR (*loc);
4437
4438 if (!expr)
4439 return MO_CLOBBER;
4440 else if (target_for_debug_bind (var_debug_decl (expr)))
4441 return MO_CLOBBER;
4442 else if (track_loc_p (*loc, expr, INT_MEM_OFFSET (*loc),
4443 false, modep, NULL))
4444 return MO_USE;
4445 else
4446 return MO_CLOBBER;
4447 }
4448
4449 return MO_CLOBBER;
4450}
94a7682d 4451
b5b8b0ac
AO
4452/* Log to OUT information about micro-operation MOPT involving X in
4453 INSN of BB. */
94a7682d 4454
b5b8b0ac
AO
4455static inline void
4456log_op_type (rtx x, basic_block bb, rtx insn,
4457 enum micro_operation_type mopt, FILE *out)
4458{
4459 fprintf (out, "bb %i op %i insn %i %s ",
4460 bb->index, VTI (bb)->n_mos - 1,
4461 INSN_UID (insn), micro_operation_type_name[mopt]);
4462 print_inline_rtx (out, x, 2);
4463 fputc ('\n', out);
94a7682d 4464}
ca787200 4465
014a1138
JZ
4466/* Count uses (register and memory references) LOC which will be tracked.
4467 INSN is instruction which the LOC is part of. */
4468
4469static int
b5b8b0ac 4470count_uses (rtx *loc, void *cuip)
014a1138 4471{
b5b8b0ac
AO
4472 struct count_use_info *cui = (struct count_use_info *) cuip;
4473 enum micro_operation_type mopt = use_type (loc, cui, NULL);
014a1138 4474
b5b8b0ac 4475 if (mopt != MO_CLOBBER)
014a1138 4476 {
b5b8b0ac
AO
4477 cselib_val *val;
4478 enum machine_mode mode = GET_MODE (*loc);
4479
4480 VTI (cui->bb)->n_mos++;
4481
4482 if (dump_file && (dump_flags & TDF_DETAILS))
4483 log_op_type (*loc, cui->bb, cui->insn, mopt, dump_file);
4484
4485 switch (mopt)
4486 {
4487 case MO_VAL_LOC:
4488 loc = &PAT_VAR_LOCATION_LOC (*loc);
4489 if (VAR_LOC_UNKNOWN_P (*loc))
4490 break;
4491 /* Fall through. */
4492
4493 case MO_VAL_USE:
4494 case MO_VAL_SET:
4495 if (MEM_P (*loc)
4496 && !REG_P (XEXP (*loc, 0)) && !MEM_P (XEXP (*loc, 0)))
4497 {
d4ebfa65
BE
4498 enum machine_mode address_mode
4499 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (*loc));
4500 val = cselib_lookup (XEXP (*loc, 0), address_mode, false);
b5b8b0ac
AO
4501
4502 if (val && !cselib_preserved_value_p (val))
4503 {
4504 VTI (cui->bb)->n_mos++;
4505 cselib_preserve_value (val);
4506 }
4507 }
4508
4509 val = find_use_val (*loc, mode, cui);
4510 if (val)
4511 cselib_preserve_value (val);
4512 else
4513 gcc_assert (mopt == MO_VAL_LOC);
4514
4515 break;
4516
4517 default:
4518 break;
4519 }
014a1138
JZ
4520 }
4521
4522 return 0;
4523}
4524
b5b8b0ac
AO
4525/* Helper function for finding all uses of REG/MEM in X in CUI's
4526 insn. */
014a1138
JZ
4527
4528static void
b5b8b0ac 4529count_uses_1 (rtx *x, void *cui)
014a1138 4530{
b5b8b0ac 4531 for_each_rtx (x, count_uses, cui);
014a1138
JZ
4532}
4533
b5b8b0ac
AO
4534/* Count stores (register and memory references) LOC which will be
4535 tracked. CUI is a count_use_info object containing the instruction
4536 which the LOC is part of. */
4537
4538static void
4539count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *cui)
4540{
4541 count_uses (&loc, cui);
4542}
4543
4544/* Callback for cselib_record_sets_hook, that counts how many micro
4545 operations it takes for uses and stores in an insn after
4546 cselib_record_sets has analyzed the sets in an insn, but before it
4547 modifies the stored values in the internal tables, unless
4548 cselib_record_sets doesn't call it directly (perhaps because we're
4549 not doing cselib in the first place, in which case sets and n_sets
4550 will be 0). */
014a1138
JZ
4551
4552static void
b5b8b0ac 4553count_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
014a1138 4554{
b5b8b0ac
AO
4555 basic_block bb = BLOCK_FOR_INSN (insn);
4556 struct count_use_info cui;
4557
4558 cselib_hook_called = true;
4559
4560 cui.insn = insn;
4561 cui.bb = bb;
4562 cui.sets = sets;
4563 cui.n_sets = n_sets;
4564
4565 cui.store_p = false;
4566 note_uses (&PATTERN (insn), count_uses_1, &cui);
4567 cui.store_p = true;
4568 note_stores (PATTERN (insn), count_stores, &cui);
014a1138
JZ
4569}
4570
b5b8b0ac
AO
4571/* Tell whether the CONCAT used to holds a VALUE and its location
4572 needs value resolution, i.e., an attempt of mapping the location
4573 back to other incoming values. */
4574#define VAL_NEEDS_RESOLUTION(x) \
4575 (RTL_FLAG_CHECK1 ("VAL_NEEDS_RESOLUTION", (x), CONCAT)->volatil)
4576/* Whether the location in the CONCAT is a tracked expression, that
4577 should also be handled like a MO_USE. */
4578#define VAL_HOLDS_TRACK_EXPR(x) \
4579 (RTL_FLAG_CHECK1 ("VAL_HOLDS_TRACK_EXPR", (x), CONCAT)->used)
4580/* Whether the location in the CONCAT should be handled like a MO_COPY
4581 as well. */
4582#define VAL_EXPR_IS_COPIED(x) \
4583 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_COPIED", (x), CONCAT)->jump)
4584/* Whether the location in the CONCAT should be handled like a
4585 MO_CLOBBER as well. */
4586#define VAL_EXPR_IS_CLOBBERED(x) \
4587 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_CLOBBERED", (x), CONCAT)->unchanging)
4588
014a1138
JZ
4589/* Add uses (register and memory references) LOC which will be tracked
4590 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
4591
4592static int
b5b8b0ac 4593add_uses (rtx *loc, void *data)
014a1138 4594{
b5b8b0ac
AO
4595 enum machine_mode mode = VOIDmode;
4596 struct count_use_info *cui = (struct count_use_info *)data;
4597 enum micro_operation_type type = use_type (loc, cui, &mode);
38ae7651 4598
b5b8b0ac 4599 if (type != MO_CLOBBER)
014a1138 4600 {
b5b8b0ac 4601 basic_block bb = cui->bb;
014a1138
JZ
4602 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
4603
b5b8b0ac
AO
4604 mo->type = type;
4605 mo->u.loc = type == MO_USE ? var_lowpart (mode, *loc) : *loc;
4606 mo->insn = cui->insn;
4607
4608 if (type == MO_VAL_LOC)
94a7682d 4609 {
b5b8b0ac
AO
4610 rtx oloc = *loc;
4611 rtx vloc = PAT_VAR_LOCATION_LOC (oloc);
4612 cselib_val *val;
4613
4614 gcc_assert (cui->sets);
4615
4616 if (MEM_P (vloc)
4617 && !REG_P (XEXP (vloc, 0)) && !MEM_P (XEXP (vloc, 0)))
4618 {
4619 rtx mloc = vloc;
d4ebfa65
BE
4620 enum machine_mode address_mode
4621 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
4622 cselib_val *val
4623 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
b5b8b0ac
AO
4624
4625 if (val && !cselib_preserved_value_p (val))
4626 {
4627 micro_operation *mon = VTI (bb)->mos + VTI (bb)->n_mos++;
4628 mon->type = mo->type;
4629 mon->u.loc = mo->u.loc;
4630 mon->insn = mo->insn;
4631 cselib_preserve_value (val);
4632 mo->type = MO_VAL_USE;
4633 mloc = cselib_subst_to_values (XEXP (mloc, 0));
d4ebfa65
BE
4634 mo->u.loc = gen_rtx_CONCAT (address_mode,
4635 val->val_rtx, mloc);
b5b8b0ac
AO
4636 if (dump_file && (dump_flags & TDF_DETAILS))
4637 log_op_type (mo->u.loc, cui->bb, cui->insn,
4638 mo->type, dump_file);
4639 mo = mon;
4640 }
4641 }
4642
4643 if (!VAR_LOC_UNKNOWN_P (vloc)
4644 && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
4645 {
4646 enum machine_mode mode2;
4647 enum micro_operation_type type2;
4648 rtx nloc = replace_expr_with_values (vloc);
4649
4650 if (nloc)
4651 {
4652 oloc = shallow_copy_rtx (oloc);
4653 PAT_VAR_LOCATION_LOC (oloc) = nloc;
4654 }
4655
4656 oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc);
4657
4658 type2 = use_type (&vloc, 0, &mode2);
4659
4660 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
4661 || type2 == MO_CLOBBER);
4662
4663 if (type2 == MO_CLOBBER
4664 && !cselib_preserved_value_p (val))
4665 {
4666 VAL_NEEDS_RESOLUTION (oloc) = 1;
4667 cselib_preserve_value (val);
4668 }
4669 }
4670 else if (!VAR_LOC_UNKNOWN_P (vloc))
4671 {
4672 oloc = shallow_copy_rtx (oloc);
4673 PAT_VAR_LOCATION_LOC (oloc) = gen_rtx_UNKNOWN_VAR_LOC ();
4674 }
4675
4676 mo->u.loc = oloc;
94a7682d 4677 }
b5b8b0ac 4678 else if (type == MO_VAL_USE)
94a7682d 4679 {
b5b8b0ac
AO
4680 enum machine_mode mode2 = VOIDmode;
4681 enum micro_operation_type type2;
4682 cselib_val *val = find_use_val (*loc, GET_MODE (*loc), cui);
4683 rtx vloc, oloc = *loc, nloc;
4684
4685 gcc_assert (cui->sets);
4686
4687 if (MEM_P (oloc)
4688 && !REG_P (XEXP (oloc, 0)) && !MEM_P (XEXP (oloc, 0)))
4689 {
4690 rtx mloc = oloc;
d4ebfa65
BE
4691 enum machine_mode address_mode
4692 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
4693 cselib_val *val
4694 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
b5b8b0ac
AO
4695
4696 if (val && !cselib_preserved_value_p (val))
4697 {
4698 micro_operation *mon = VTI (bb)->mos + VTI (bb)->n_mos++;
4699 mon->type = mo->type;
4700 mon->u.loc = mo->u.loc;
4701 mon->insn = mo->insn;
4702 cselib_preserve_value (val);
4703 mo->type = MO_VAL_USE;
4704 mloc = cselib_subst_to_values (XEXP (mloc, 0));
d4ebfa65
BE
4705 mo->u.loc = gen_rtx_CONCAT (address_mode,
4706 val->val_rtx, mloc);
b5b8b0ac
AO
4707 mo->insn = cui->insn;
4708 if (dump_file && (dump_flags & TDF_DETAILS))
4709 log_op_type (mo->u.loc, cui->bb, cui->insn,
4710 mo->type, dump_file);
4711 mo = mon;
4712 }
4713 }
4714
4715 type2 = use_type (loc, 0, &mode2);
4716
4717 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
4718 || type2 == MO_CLOBBER);
4719
4720 if (type2 == MO_USE)
4721 vloc = var_lowpart (mode2, *loc);
4722 else
4723 vloc = oloc;
4724
4725 /* The loc of a MO_VAL_USE may have two forms:
4726
4727 (concat val src): val is at src, a value-based
4728 representation.
4729
4730 (concat (concat val use) src): same as above, with use as
4731 the MO_USE tracked value, if it differs from src.
4732
4733 */
4734
4735 nloc = replace_expr_with_values (*loc);
4736 if (!nloc)
4737 nloc = oloc;
4738
4739 if (vloc != nloc)
4740 oloc = gen_rtx_CONCAT (mode2, val->val_rtx, vloc);
4741 else
4742 oloc = val->val_rtx;
4743
4744 mo->u.loc = gen_rtx_CONCAT (mode, oloc, nloc);
4745
4746 if (type2 == MO_USE)
4747 VAL_HOLDS_TRACK_EXPR (mo->u.loc) = 1;
4748 if (!cselib_preserved_value_p (val))
4749 {
4750 VAL_NEEDS_RESOLUTION (mo->u.loc) = 1;
4751 cselib_preserve_value (val);
4752 }
94a7682d 4753 }
b5b8b0ac
AO
4754 else
4755 gcc_assert (type == MO_USE || type == MO_USE_NO_VAR);
014a1138 4756
b5b8b0ac
AO
4757 if (dump_file && (dump_flags & TDF_DETAILS))
4758 log_op_type (mo->u.loc, cui->bb, cui->insn, mo->type, dump_file);
014a1138
JZ
4759 }
4760
4761 return 0;
4762}
4763
4764/* Helper function for finding all uses of REG/MEM in X in insn INSN. */
4765
4766static void
b5b8b0ac 4767add_uses_1 (rtx *x, void *cui)
014a1138 4768{
b5b8b0ac 4769 for_each_rtx (x, add_uses, cui);
014a1138
JZ
4770}
4771
4772/* Add stores (register and memory references) LOC which will be tracked
b5b8b0ac
AO
4773 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
4774 CUIP->insn is instruction which the LOC is part of. */
014a1138
JZ
4775
4776static void
b5b8b0ac 4777add_stores (rtx loc, const_rtx expr, void *cuip)
014a1138 4778{
b5b8b0ac
AO
4779 enum machine_mode mode = VOIDmode, mode2;
4780 struct count_use_info *cui = (struct count_use_info *)cuip;
4781 basic_block bb = cui->bb;
4782 micro_operation *mo;
4783 rtx oloc = loc, nloc, src = NULL;
4784 enum micro_operation_type type = use_type (&loc, cui, &mode);
4785 bool track_p = false;
4786 cselib_val *v;
4787 bool resolve, preserve;
4788
4789 if (type == MO_CLOBBER)
4790 return;
4791
4792 mode2 = mode;
38ae7651 4793
f8cfc6aa 4794 if (REG_P (loc))
014a1138 4795 {
b5b8b0ac 4796 mo = VTI (bb)->mos + VTI (bb)->n_mos++;
014a1138 4797
b5b8b0ac
AO
4798 if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET)
4799 || !(track_p = use_type (&loc, NULL, &mode2) == MO_USE)
4800 || GET_CODE (expr) == CLOBBER)
94a7682d
RS
4801 {
4802 mo->type = MO_CLOBBER;
4803 mo->u.loc = loc;
4804 }
ca787200 4805 else
94a7682d 4806 {
94a7682d 4807 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
b5b8b0ac
AO
4808 src = var_lowpart (mode2, SET_SRC (expr));
4809 loc = var_lowpart (mode2, loc);
94a7682d
RS
4810
4811 if (src == NULL)
4812 {
4813 mo->type = MO_SET;
4814 mo->u.loc = loc;
4815 }
4816 else
4817 {
4818 if (SET_SRC (expr) != src)
4819 expr = gen_rtx_SET (VOIDmode, loc, src);
4820 if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
4821 mo->type = MO_COPY;
4822 else
4823 mo->type = MO_SET;
4824 mo->u.loc = CONST_CAST_RTX (expr);
4825 }
4826 }
b5b8b0ac 4827 mo->insn = cui->insn;
014a1138 4828 }
3c0cb5de 4829 else if (MEM_P (loc)
b5b8b0ac
AO
4830 && ((track_p = use_type (&loc, NULL, &mode2) == MO_USE)
4831 || cui->sets))
014a1138 4832 {
b5b8b0ac
AO
4833 mo = VTI (bb)->mos + VTI (bb)->n_mos++;
4834
4835 if (MEM_P (loc) && type == MO_VAL_SET
4836 && !REG_P (XEXP (loc, 0)) && !MEM_P (XEXP (loc, 0)))
4837 {
4838 rtx mloc = loc;
d4ebfa65
BE
4839 enum machine_mode address_mode
4840 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
4841 cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
b5b8b0ac
AO
4842
4843 if (val && !cselib_preserved_value_p (val))
4844 {
4845 cselib_preserve_value (val);
4846 mo->type = MO_VAL_USE;
4847 mloc = cselib_subst_to_values (XEXP (mloc, 0));
d4ebfa65 4848 mo->u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
b5b8b0ac
AO
4849 mo->insn = cui->insn;
4850 if (dump_file && (dump_flags & TDF_DETAILS))
4851 log_op_type (mo->u.loc, cui->bb, cui->insn,
4852 mo->type, dump_file);
4853 mo = VTI (bb)->mos + VTI (bb)->n_mos++;
4854 }
4855 }
014a1138 4856
b5b8b0ac 4857 if (GET_CODE (expr) == CLOBBER || !track_p)
94a7682d
RS
4858 {
4859 mo->type = MO_CLOBBER;
b5b8b0ac 4860 mo->u.loc = track_p ? var_lowpart (mode2, loc) : loc;
94a7682d
RS
4861 }
4862 else
4863 {
94a7682d 4864 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
b5b8b0ac
AO
4865 src = var_lowpart (mode2, SET_SRC (expr));
4866 loc = var_lowpart (mode2, loc);
94a7682d
RS
4867
4868 if (src == NULL)
4869 {
4870 mo->type = MO_SET;
4871 mo->u.loc = loc;
4872 }
4873 else
4874 {
38ae7651
RS
4875 if (SET_SRC (expr) != src)
4876 expr = gen_rtx_SET (VOIDmode, loc, src);
94a7682d 4877 if (same_variable_part_p (SET_SRC (expr),
ca787200 4878 MEM_EXPR (loc),
8c6c36a3 4879 INT_MEM_OFFSET (loc)))
94a7682d
RS
4880 mo->type = MO_COPY;
4881 else
4882 mo->type = MO_SET;
4883 mo->u.loc = CONST_CAST_RTX (expr);
4884 }
4885 }
b5b8b0ac
AO
4886 mo->insn = cui->insn;
4887 }
4888 else
4889 return;
4890
4891 if (type != MO_VAL_SET)
4892 goto log_and_return;
4893
4894 v = find_use_val (oloc, mode, cui);
4895
4896 resolve = preserve = !cselib_preserved_value_p (v);
4897
4898 nloc = replace_expr_with_values (oloc);
4899 if (nloc)
4900 oloc = nloc;
4901
4902 if (resolve && GET_CODE (mo->u.loc) == SET)
4903 {
4904 nloc = replace_expr_with_values (SET_SRC (mo->u.loc));
4905
4906 if (nloc)
4907 oloc = gen_rtx_SET (GET_MODE (mo->u.loc), oloc, nloc);
4908 else
4909 {
4910 if (oloc == SET_DEST (mo->u.loc))
4911 /* No point in duplicating. */
4912 oloc = mo->u.loc;
4913 if (!REG_P (SET_SRC (mo->u.loc)))
4914 resolve = false;
4915 }
4916 }
4917 else if (!resolve)
4918 {
4919 if (GET_CODE (mo->u.loc) == SET
4920 && oloc == SET_DEST (mo->u.loc))
4921 /* No point in duplicating. */
4922 oloc = mo->u.loc;
4923 }
4924 else
4925 resolve = false;
4926
4927 loc = gen_rtx_CONCAT (mode, v->val_rtx, oloc);
4928
4929 if (mo->u.loc != oloc)
4930 loc = gen_rtx_CONCAT (GET_MODE (mo->u.loc), loc, mo->u.loc);
4931
4932 /* The loc of a MO_VAL_SET may have various forms:
4933
4934 (concat val dst): dst now holds val
4935
4936 (concat val (set dst src)): dst now holds val, copied from src
4937
4938 (concat (concat val dstv) dst): dst now holds val; dstv is dst
4939 after replacing mems and non-top-level regs with values.
4940
4941 (concat (concat val dstv) (set dst src)): dst now holds val,
4942 copied from src. dstv is a value-based representation of dst, if
4943 it differs from dst. If resolution is needed, src is a REG.
4944
4945 (concat (concat val (set dstv srcv)) (set dst src)): src
4946 copied to dst, holding val. dstv and srcv are value-based
4947 representations of dst and src, respectively.
4948
4949 */
4950
4951 mo->u.loc = loc;
4952
4953 if (track_p)
4954 VAL_HOLDS_TRACK_EXPR (loc) = 1;
4955 if (preserve)
4956 {
4957 VAL_NEEDS_RESOLUTION (loc) = resolve;
4958 cselib_preserve_value (v);
4959 }
4960 if (mo->type == MO_CLOBBER)
4961 VAL_EXPR_IS_CLOBBERED (loc) = 1;
4962 if (mo->type == MO_COPY)
4963 VAL_EXPR_IS_COPIED (loc) = 1;
4964
4965 mo->type = MO_VAL_SET;
4966
4967 log_and_return:
4968 if (dump_file && (dump_flags & TDF_DETAILS))
4969 log_op_type (mo->u.loc, cui->bb, cui->insn, mo->type, dump_file);
4970}
4971
4972/* Callback for cselib_record_sets_hook, that records as micro
4973 operations uses and stores in an insn after cselib_record_sets has
4974 analyzed the sets in an insn, but before it modifies the stored
4975 values in the internal tables, unless cselib_record_sets doesn't
4976 call it directly (perhaps because we're not doing cselib in the
4977 first place, in which case sets and n_sets will be 0). */
4978
4979static void
4980add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
4981{
4982 basic_block bb = BLOCK_FOR_INSN (insn);
4983 int n1, n2;
4984 struct count_use_info cui;
4985
4986 cselib_hook_called = true;
4987
4988 cui.insn = insn;
4989 cui.bb = bb;
4990 cui.sets = sets;
4991 cui.n_sets = n_sets;
4992
4993 n1 = VTI (bb)->n_mos;
4994 cui.store_p = false;
4995 note_uses (&PATTERN (insn), add_uses_1, &cui);
4996 n2 = VTI (bb)->n_mos - 1;
4997
7168dc47
AO
4998 /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
4999 MO_VAL_LOC last. */
b5b8b0ac
AO
5000 while (n1 < n2)
5001 {
5002 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
5003 n1++;
5004 while (n1 < n2 && VTI (bb)->mos[n2].type != MO_USE)
5005 n2--;
5006 if (n1 < n2)
5007 {
5008 micro_operation sw;
5009
7168dc47
AO
5010 sw = VTI (bb)->mos[n1];
5011 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
5012 VTI (bb)->mos[n2] = sw;
5013 }
5014 }
5015
5016 n2 = VTI (bb)->n_mos - 1;
5017
5018 while (n1 < n2)
5019 {
5020 while (n1 < n2 && VTI (bb)->mos[n1].type != MO_VAL_LOC)
5021 n1++;
5022 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_VAL_LOC)
5023 n2--;
5024 if (n1 < n2)
5025 {
5026 micro_operation sw;
5027
b5b8b0ac
AO
5028 sw = VTI (bb)->mos[n1];
5029 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
5030 VTI (bb)->mos[n2] = sw;
5031 }
5032 }
5033
5034 if (CALL_P (insn))
5035 {
5036 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
5037
5038 mo->type = MO_CALL;
5039 mo->insn = insn;
5040
5041 if (dump_file && (dump_flags & TDF_DETAILS))
5042 log_op_type (PATTERN (insn), bb, insn, mo->type, dump_file);
5043 }
5044
5045 n1 = VTI (bb)->n_mos;
5046 /* This will record NEXT_INSN (insn), such that we can
5047 insert notes before it without worrying about any
5048 notes that MO_USEs might emit after the insn. */
5049 cui.store_p = true;
5050 note_stores (PATTERN (insn), add_stores, &cui);
5051 n2 = VTI (bb)->n_mos - 1;
5052
5053 /* Order the MO_CLOBBERs to be before MO_SETs. */
5054 while (n1 < n2)
5055 {
5056 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
5057 n1++;
5058 while (n1 < n2 && VTI (bb)->mos[n2].type != MO_CLOBBER)
5059 n2--;
5060 if (n1 < n2)
5061 {
5062 micro_operation sw;
5063
5064 sw = VTI (bb)->mos[n1];
5065 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
5066 VTI (bb)->mos[n2] = sw;
5067 }
014a1138
JZ
5068 }
5069}
5070
62760ffd 5071static enum var_init_status
94a7682d 5072find_src_status (dataflow_set *in, rtx src)
62760ffd 5073{
62760ffd
CT
5074 tree decl = NULL_TREE;
5075 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
5076
5077 if (! flag_var_tracking_uninit)
5078 status = VAR_INIT_STATUS_INITIALIZED;
5079
0ef0421e 5080 if (src && REG_P (src))
62760ffd 5081 decl = var_debug_decl (REG_EXPR (src));
0ef0421e 5082 else if (src && MEM_P (src))
62760ffd
CT
5083 decl = var_debug_decl (MEM_EXPR (src));
5084
5085 if (src && decl)
b5b8b0ac 5086 status = get_init_value (in, src, dv_from_decl (decl));
62760ffd
CT
5087
5088 return status;
5089}
5090
94a7682d
RS
5091/* SRC is the source of an assignment. Use SET to try to find what
5092 was ultimately assigned to SRC. Return that value if known,
5093 otherwise return SRC itself. */
62760ffd
CT
5094
5095static rtx
94a7682d 5096find_src_set_src (dataflow_set *set, rtx src)
62760ffd
CT
5097{
5098 tree decl = NULL_TREE; /* The variable being copied around. */
62760ffd 5099 rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
62760ffd
CT
5100 variable var;
5101 location_chain nextp;
5102 int i;
5103 bool found;
5104
0ef0421e 5105 if (src && REG_P (src))
62760ffd 5106 decl = var_debug_decl (REG_EXPR (src));
0ef0421e 5107 else if (src && MEM_P (src))
62760ffd
CT
5108 decl = var_debug_decl (MEM_EXPR (src));
5109
5110 if (src && decl)
5111 {
b5b8b0ac
AO
5112 decl_or_value dv = dv_from_decl (decl);
5113
5114 var = shared_hash_find (set->vars, dv);
d24686d7 5115 if (var)
62760ffd 5116 {
62760ffd
CT
5117 found = false;
5118 for (i = 0; i < var->n_var_parts && !found; i++)
5119 for (nextp = var->var_part[i].loc_chain; nextp && !found;
5120 nextp = nextp->next)
5121 if (rtx_equal_p (nextp->loc, src))
5122 {
5123 set_src = nextp->set_src;
5124 found = true;
5125 }
5126
5127 }
5128 }
5129
5130 return set_src;
5131}
5132
b5b8b0ac
AO
5133/* Compute the changes of variable locations in the basic block BB. */
5134
5135static bool
5136compute_bb_dataflow (basic_block bb)
5137{
5138 int i, n;
5139 bool changed;
5140 dataflow_set old_out;
5141 dataflow_set *in = &VTI (bb)->in;
5142 dataflow_set *out = &VTI (bb)->out;
5143
5144 dataflow_set_init (&old_out);
5145 dataflow_set_copy (&old_out, out);
5146 dataflow_set_copy (out, in);
5147
5148 n = VTI (bb)->n_mos;
5149 for (i = 0; i < n; i++)
5150 {
5151 rtx insn = VTI (bb)->mos[i].insn;
5152
5153 switch (VTI (bb)->mos[i].type)
5154 {
5155 case MO_CALL:
5156 dataflow_set_clear_at_call (out);
5157 break;
5158
5159 case MO_USE:
5160 {
5161 rtx loc = VTI (bb)->mos[i].u.loc;
5162
5163 if (REG_P (loc))
5164 var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5165 else if (MEM_P (loc))
5166 var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5167 }
5168 break;
5169
5170 case MO_VAL_LOC:
5171 {
5172 rtx loc = VTI (bb)->mos[i].u.loc;
5173 rtx val, vloc;
5174 tree var;
5175
5176 if (GET_CODE (loc) == CONCAT)
5177 {
5178 val = XEXP (loc, 0);
5179 vloc = XEXP (loc, 1);
5180 }
5181 else
5182 {
5183 val = NULL_RTX;
5184 vloc = loc;
5185 }
5186
5187 var = PAT_VAR_LOCATION_DECL (vloc);
5188
5189 clobber_variable_part (out, NULL_RTX,
5190 dv_from_decl (var), 0, NULL_RTX);
5191 if (val)
5192 {
5193 if (VAL_NEEDS_RESOLUTION (loc))
5194 val_resolve (out, val, PAT_VAR_LOCATION_LOC (vloc), insn);
5195 set_variable_part (out, val, dv_from_decl (var), 0,
5196 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
5197 INSERT);
5198 }
5199 }
5200 break;
5201
5202 case MO_VAL_USE:
5203 {
5204 rtx loc = VTI (bb)->mos[i].u.loc;
5205 rtx val, vloc, uloc;
5206
5207 vloc = uloc = XEXP (loc, 1);
5208 val = XEXP (loc, 0);
5209
5210 if (GET_CODE (val) == CONCAT)
5211 {
5212 uloc = XEXP (val, 1);
5213 val = XEXP (val, 0);
5214 }
5215
5216 if (VAL_NEEDS_RESOLUTION (loc))
5217 val_resolve (out, val, vloc, insn);
5218
5219 if (VAL_HOLDS_TRACK_EXPR (loc))
5220 {
5221 if (GET_CODE (uloc) == REG)
5222 var_reg_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5223 NULL);
5224 else if (GET_CODE (uloc) == MEM)
5225 var_mem_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5226 NULL);
5227 }
5228 }
5229 break;
5230
5231 case MO_VAL_SET:
5232 {
5233 rtx loc = VTI (bb)->mos[i].u.loc;
5234 rtx val, vloc, uloc;
5235
5236 vloc = uloc = XEXP (loc, 1);
5237 val = XEXP (loc, 0);
5238
5239 if (GET_CODE (val) == CONCAT)
5240 {
5241 vloc = XEXP (val, 1);
5242 val = XEXP (val, 0);
5243 }
5244
5245 if (GET_CODE (vloc) == SET)
5246 {
5247 rtx vsrc = SET_SRC (vloc);
5248
5249 gcc_assert (val != vsrc);
5250 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
5251
5252 vloc = SET_DEST (vloc);
5253
5254 if (VAL_NEEDS_RESOLUTION (loc))
5255 val_resolve (out, val, vsrc, insn);
5256 }
5257 else if (VAL_NEEDS_RESOLUTION (loc))
5258 {
5259 gcc_assert (GET_CODE (uloc) == SET
5260 && GET_CODE (SET_SRC (uloc)) == REG);
5261 val_resolve (out, val, SET_SRC (uloc), insn);
5262 }
5263
5264 if (VAL_HOLDS_TRACK_EXPR (loc))
5265 {
5266 if (VAL_EXPR_IS_CLOBBERED (loc))
5267 {
5268 if (REG_P (uloc))
5269 var_reg_delete (out, uloc, true);
5270 else if (MEM_P (uloc))
5271 var_mem_delete (out, uloc, true);
5272 }
5273 else
5274 {
5275 bool copied_p = VAL_EXPR_IS_COPIED (loc);
5276 rtx set_src = NULL;
5277 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
5278
5279 if (GET_CODE (uloc) == SET)
5280 {
5281 set_src = SET_SRC (uloc);
5282 uloc = SET_DEST (uloc);
5283 }
014a1138 5284
b5b8b0ac
AO
5285 if (copied_p)
5286 {
5287 if (flag_var_tracking_uninit)
5288 {
5289 status = find_src_status (in, set_src);
014a1138 5290
b5b8b0ac
AO
5291 if (status == VAR_INIT_STATUS_UNKNOWN)
5292 status = find_src_status (out, set_src);
5293 }
014a1138 5294
b5b8b0ac
AO
5295 set_src = find_src_set_src (in, set_src);
5296 }
014a1138 5297
b5b8b0ac
AO
5298 if (REG_P (uloc))
5299 var_reg_delete_and_set (out, uloc, !copied_p,
5300 status, set_src);
5301 else if (MEM_P (uloc))
5302 var_mem_delete_and_set (out, uloc, !copied_p,
5303 status, set_src);
5304 }
5305 }
5306 else if (REG_P (uloc))
5307 var_regno_delete (out, REGNO (uloc));
dedc1e6d 5308
b5b8b0ac 5309 val_store (out, val, vloc, insn);
dedc1e6d
AO
5310 }
5311 break;
5312
014a1138
JZ
5313 case MO_SET:
5314 {
5315 rtx loc = VTI (bb)->mos[i].u.loc;
94a7682d 5316 rtx set_src = NULL;
62760ffd 5317
94a7682d 5318 if (GET_CODE (loc) == SET)
62760ffd 5319 {
94a7682d
RS
5320 set_src = SET_SRC (loc);
5321 loc = SET_DEST (loc);
62760ffd 5322 }
014a1138 5323
f8cfc6aa 5324 if (REG_P (loc))
62760ffd
CT
5325 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5326 set_src);
ca787200 5327 else if (MEM_P (loc))
62760ffd
CT
5328 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5329 set_src);
ca787200
AO
5330 }
5331 break;
5332
5333 case MO_COPY:
5334 {
5335 rtx loc = VTI (bb)->mos[i].u.loc;
62760ffd 5336 enum var_init_status src_status;
94a7682d
RS
5337 rtx set_src = NULL;
5338
5339 if (GET_CODE (loc) == SET)
5340 {
5341 set_src = SET_SRC (loc);
5342 loc = SET_DEST (loc);
5343 }
62760ffd
CT
5344
5345 if (! flag_var_tracking_uninit)
5346 src_status = VAR_INIT_STATUS_INITIALIZED;
5347 else
7eb3f1f7
JJ
5348 {
5349 src_status = find_src_status (in, set_src);
62760ffd 5350
7eb3f1f7
JJ
5351 if (src_status == VAR_INIT_STATUS_UNKNOWN)
5352 src_status = find_src_status (out, set_src);
5353 }
62760ffd 5354
94a7682d 5355 set_src = find_src_set_src (in, set_src);
ca787200
AO
5356
5357 if (REG_P (loc))
62760ffd 5358 var_reg_delete_and_set (out, loc, false, src_status, set_src);
3c0cb5de 5359 else if (MEM_P (loc))
62760ffd 5360 var_mem_delete_and_set (out, loc, false, src_status, set_src);
014a1138
JZ
5361 }
5362 break;
5363
5364 case MO_USE_NO_VAR:
ca787200
AO
5365 {
5366 rtx loc = VTI (bb)->mos[i].u.loc;
5367
5368 if (REG_P (loc))
5369 var_reg_delete (out, loc, false);
5370 else if (MEM_P (loc))
5371 var_mem_delete (out, loc, false);
5372 }
5373 break;
5374
014a1138
JZ
5375 case MO_CLOBBER:
5376 {
5377 rtx loc = VTI (bb)->mos[i].u.loc;
5378
f8cfc6aa 5379 if (REG_P (loc))
ca787200 5380 var_reg_delete (out, loc, true);
3c0cb5de 5381 else if (MEM_P (loc))
ca787200 5382 var_mem_delete (out, loc, true);
014a1138
JZ
5383 }
5384 break;
5385
5386 case MO_ADJUST:
30e6f306 5387 out->stack_adjust += VTI (bb)->mos[i].u.adjust;
014a1138
JZ
5388 break;
5389 }
5390 }
5391
b5b8b0ac
AO
5392 if (MAY_HAVE_DEBUG_INSNS)
5393 {
5394 dataflow_set_equiv_regs (out);
5395 htab_traverse (shared_hash_htab (out->vars), canonicalize_values_mark,
5396 out);
5397 htab_traverse (shared_hash_htab (out->vars), canonicalize_values_star,
5398 out);
5399#if ENABLE_CHECKING
5400 htab_traverse (shared_hash_htab (out->vars),
5401 canonicalize_loc_order_check, out);
5402#endif
5403 }
014a1138
JZ
5404 changed = dataflow_set_different (&old_out, out);
5405 dataflow_set_destroy (&old_out);
5406 return changed;
5407}
5408
5409/* Find the locations of variables in the whole function. */
5410
5411static void
5412vt_find_locations (void)
5413{
5414 fibheap_t worklist, pending, fibheap_swap;
5415 sbitmap visited, in_worklist, in_pending, sbitmap_swap;
5416 basic_block bb;
5417 edge e;
5418 int *bb_order;
5419 int *rc_order;
5420 int i;
b5b8b0ac 5421 int htabsz = 0;
014a1138
JZ
5422
5423 /* Compute reverse completion order of depth first search of the CFG
5424 so that the data-flow runs faster. */
5ed6ace5
MD
5425 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
5426 bb_order = XNEWVEC (int, last_basic_block);
f91a0beb 5427 pre_and_rev_post_order_compute (NULL, rc_order, false);
24bd1a0b 5428 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
014a1138
JZ
5429 bb_order[rc_order[i]] = i;
5430 free (rc_order);
5431
5432 worklist = fibheap_new ();
5433 pending = fibheap_new ();
5434 visited = sbitmap_alloc (last_basic_block);
5435 in_worklist = sbitmap_alloc (last_basic_block);
5436 in_pending = sbitmap_alloc (last_basic_block);
5437 sbitmap_zero (in_worklist);
014a1138
JZ
5438
5439 FOR_EACH_BB (bb)
0e6ed899
JZ
5440 fibheap_insert (pending, bb_order[bb->index], bb);
5441 sbitmap_ones (in_pending);
014a1138
JZ
5442
5443 while (!fibheap_empty (pending))
5444 {
5445 fibheap_swap = pending;
5446 pending = worklist;
5447 worklist = fibheap_swap;
5448 sbitmap_swap = in_pending;
5449 in_pending = in_worklist;
5450 in_worklist = sbitmap_swap;
5451
5452 sbitmap_zero (visited);
5453
5454 while (!fibheap_empty (worklist))
5455 {
3d9a9f94 5456 bb = (basic_block) fibheap_extract_min (worklist);
014a1138
JZ
5457 RESET_BIT (in_worklist, bb->index);
5458 if (!TEST_BIT (visited, bb->index))
5459 {
5460 bool changed;
628f6a4e 5461 edge_iterator ei;
b5b8b0ac 5462 int oldinsz, oldoutsz;
014a1138
JZ
5463
5464 SET_BIT (visited, bb->index);
5465
b5b8b0ac
AO
5466 if (dump_file && VTI (bb)->in.vars)
5467 {
5468 htabsz
5469 -= htab_size (shared_hash_htab (VTI (bb)->in.vars))
5470 + htab_size (shared_hash_htab (VTI (bb)->out.vars));
5471 oldinsz
5472 = htab_elements (shared_hash_htab (VTI (bb)->in.vars));
5473 oldoutsz
5474 = htab_elements (shared_hash_htab (VTI (bb)->out.vars));
5475 }
5476 else
5477 oldinsz = oldoutsz = 0;
5478
5479 if (MAY_HAVE_DEBUG_INSNS)
5480 {
5481 dataflow_set *in = &VTI (bb)->in, *first_out = NULL;
5482 bool first = true, adjust = false;
5483
5484 /* Calculate the IN set as the intersection of
5485 predecessor OUT sets. */
5486
5487 dataflow_set_clear (in);
5488 dst_can_be_shared = true;
5489
5490 FOR_EACH_EDGE (e, ei, bb->preds)
5491 if (!VTI (e->src)->flooded)
5492 gcc_assert (bb_order[bb->index]
5493 <= bb_order[e->src->index]);
5494 else if (first)
5495 {
5496 dataflow_set_copy (in, &VTI (e->src)->out);
5497 first_out = &VTI (e->src)->out;
5498 first = false;
5499 }
5500 else
5501 {
5502 dataflow_set_merge (in, &VTI (e->src)->out);
5503 adjust = true;
5504 }
5505
5506 if (adjust)
5507 {
5508 dataflow_post_merge_adjust (in, &VTI (bb)->permp);
5509#if ENABLE_CHECKING
5510 /* Merge and merge_adjust should keep entries in
5511 canonical order. */
5512 htab_traverse (shared_hash_htab (in->vars),
5513 canonicalize_loc_order_check,
5514 in);
5515#endif
5516 if (dst_can_be_shared)
5517 {
5518 shared_hash_destroy (in->vars);
5519 in->vars = shared_hash_copy (first_out->vars);
5520 }
5521 }
5522
5523 VTI (bb)->flooded = true;
5524 }
5525 else
014a1138 5526 {
b5b8b0ac
AO
5527 /* Calculate the IN set as union of predecessor OUT sets. */
5528 dataflow_set_clear (&VTI (bb)->in);
5529 FOR_EACH_EDGE (e, ei, bb->preds)
5530 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
014a1138
JZ
5531 }
5532
5533 changed = compute_bb_dataflow (bb);
b5b8b0ac
AO
5534 if (dump_file)
5535 htabsz += htab_size (shared_hash_htab (VTI (bb)->in.vars))
5536 + htab_size (shared_hash_htab (VTI (bb)->out.vars));
5537
014a1138
JZ
5538 if (changed)
5539 {
628f6a4e 5540 FOR_EACH_EDGE (e, ei, bb->succs)
014a1138
JZ
5541 {
5542 if (e->dest == EXIT_BLOCK_PTR)
5543 continue;
5544
014a1138
JZ
5545 if (TEST_BIT (visited, e->dest->index))
5546 {
5547 if (!TEST_BIT (in_pending, e->dest->index))
5548 {
5549 /* Send E->DEST to next round. */
5550 SET_BIT (in_pending, e->dest->index);
5551 fibheap_insert (pending,
5552 bb_order[e->dest->index],
5553 e->dest);
5554 }
5555 }
5556 else if (!TEST_BIT (in_worklist, e->dest->index))
5557 {
5558 /* Add E->DEST to current round. */
5559 SET_BIT (in_worklist, e->dest->index);
5560 fibheap_insert (worklist, bb_order[e->dest->index],
5561 e->dest);
5562 }
5563 }
5564 }
b5b8b0ac
AO
5565
5566 if (dump_file)
5567 fprintf (dump_file,
5568 "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n",
5569 bb->index,
5570 (int)htab_elements (shared_hash_htab (VTI (bb)->in.vars)),
5571 oldinsz,
5572 (int)htab_elements (shared_hash_htab (VTI (bb)->out.vars)),
5573 oldoutsz,
5574 (int)worklist->nodes, (int)pending->nodes, htabsz);
5575
5576 if (dump_file && (dump_flags & TDF_DETAILS))
5577 {
5578 fprintf (dump_file, "BB %i IN:\n", bb->index);
5579 dump_dataflow_set (&VTI (bb)->in);
5580 fprintf (dump_file, "BB %i OUT:\n", bb->index);
5581 dump_dataflow_set (&VTI (bb)->out);
5582 }
014a1138
JZ
5583 }
5584 }
5585 }
5586
b5b8b0ac
AO
5587 if (MAY_HAVE_DEBUG_INSNS)
5588 FOR_EACH_BB (bb)
5589 gcc_assert (VTI (bb)->flooded);
5590
014a1138
JZ
5591 free (bb_order);
5592 fibheap_delete (worklist);
5593 fibheap_delete (pending);
5594 sbitmap_free (visited);
5595 sbitmap_free (in_worklist);
5596 sbitmap_free (in_pending);
5597}
5598
5599/* Print the content of the LIST to dump file. */
5600
5601static void
5602dump_attrs_list (attrs list)
5603{
5604 for (; list; list = list->next)
5605 {
b5b8b0ac
AO
5606 if (dv_is_decl_p (list->dv))
5607 print_mem_expr (dump_file, dv_as_decl (list->dv));
5608 else
5609 print_rtl_single (dump_file, dv_as_value (list->dv));
30e6f306 5610 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
014a1138 5611 }
c263766c 5612 fprintf (dump_file, "\n");
014a1138
JZ
5613}
5614
5615/* Print the information about variable *SLOT to dump file. */
5616
5617static int
b5b8b0ac
AO
5618dump_variable_slot (void **slot, void *data ATTRIBUTE_UNUSED)
5619{
5620 variable var = (variable) *slot;
5621
5622 dump_variable (var);
5623
5624 /* Continue traversing the hash table. */
5625 return 1;
5626}
5627
5628/* Print the information about variable VAR to dump file. */
5629
5630static void
5631dump_variable (variable var)
014a1138 5632{
014a1138
JZ
5633 int i;
5634 location_chain node;
5635
b5b8b0ac
AO
5636 if (dv_is_decl_p (var->dv))
5637 {
5638 const_tree decl = dv_as_decl (var->dv);
5639
5640 if (DECL_NAME (decl))
5641 fprintf (dump_file, " name: %s",
5642 IDENTIFIER_POINTER (DECL_NAME (decl)));
5643 else
5644 fprintf (dump_file, " name: D.%u", DECL_UID (decl));
5645 if (dump_flags & TDF_UID)
5646 fprintf (dump_file, " D.%u\n", DECL_UID (decl));
5647 else
5648 fprintf (dump_file, "\n");
5649 }
e56f9152 5650 else
b5b8b0ac
AO
5651 {
5652 fputc (' ', dump_file);
5653 print_rtl_single (dump_file, dv_as_value (var->dv));
5654 }
e56f9152 5655
014a1138
JZ
5656 for (i = 0; i < var->n_var_parts; i++)
5657 {
c263766c 5658 fprintf (dump_file, " offset %ld\n",
014a1138
JZ
5659 (long) var->var_part[i].offset);
5660 for (node = var->var_part[i].loc_chain; node; node = node->next)
5661 {
c263766c 5662 fprintf (dump_file, " ");
62760ffd
CT
5663 if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
5664 fprintf (dump_file, "[uninit]");
c263766c 5665 print_rtl_single (dump_file, node->loc);
014a1138
JZ
5666 }
5667 }
014a1138
JZ
5668}
5669
5670/* Print the information about variables from hash table VARS to dump file. */
5671
5672static void
5673dump_vars (htab_t vars)
5674{
5675 if (htab_elements (vars) > 0)
5676 {
c263766c 5677 fprintf (dump_file, "Variables:\n");
b5b8b0ac 5678 htab_traverse (vars, dump_variable_slot, NULL);
014a1138
JZ
5679 }
5680}
5681
5682/* Print the dataflow set SET to dump file. */
5683
5684static void
5685dump_dataflow_set (dataflow_set *set)
5686{
5687 int i;
5688
30e6f306
RH
5689 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
5690 set->stack_adjust);
d3067303 5691 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
014a1138
JZ
5692 {
5693 if (set->regs[i])
5694 {
c263766c 5695 fprintf (dump_file, "Reg %d:", i);
014a1138
JZ
5696 dump_attrs_list (set->regs[i]);
5697 }
5698 }
d24686d7 5699 dump_vars (shared_hash_htab (set->vars));
c263766c 5700 fprintf (dump_file, "\n");
014a1138
JZ
5701}
5702
5703/* Print the IN and OUT sets for each basic block to dump file. */
5704
5705static void
5706dump_dataflow_sets (void)
5707{
5708 basic_block bb;
5709
5710 FOR_EACH_BB (bb)
5711 {
c263766c
RH
5712 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
5713 fprintf (dump_file, "IN:\n");
014a1138 5714 dump_dataflow_set (&VTI (bb)->in);
c263766c 5715 fprintf (dump_file, "OUT:\n");
014a1138
JZ
5716 dump_dataflow_set (&VTI (bb)->out);
5717 }
5718}
5719
5720/* Add variable VAR to the hash table of changed variables and
d24686d7 5721 if it has no locations delete it from SET's hash table. */
014a1138
JZ
5722
5723static void
d24686d7 5724variable_was_changed (variable var, dataflow_set *set)
014a1138 5725{
b5b8b0ac 5726 hashval_t hash = dv_htab_hash (var->dv);
014a1138
JZ
5727
5728 if (emit_notes)
5729 {
b5b8b0ac
AO
5730 void **slot;
5731
5732 /* Remember this decl or VALUE has been added to changed_variables. */
5733 set_dv_changed (var->dv, true);
014a1138 5734
b5b8b0ac
AO
5735 slot = htab_find_slot_with_hash (changed_variables,
5736 var->dv,
5737 hash, INSERT);
014a1138 5738
d24686d7 5739 if (set && var->n_var_parts == 0)
014a1138
JZ
5740 {
5741 variable empty_var;
014a1138 5742
b5b8b0ac
AO
5743 empty_var = (variable) pool_alloc (dv_pool (var->dv));
5744 empty_var->dv = var->dv;
81f2eadb 5745 empty_var->refcount = 1;
014a1138
JZ
5746 empty_var->n_var_parts = 0;
5747 *slot = empty_var;
d24686d7 5748 goto drop_var;
014a1138
JZ
5749 }
5750 else
5751 {
d24686d7 5752 var->refcount++;
014a1138
JZ
5753 *slot = var;
5754 }
5755 }
5756 else
5757 {
d24686d7 5758 gcc_assert (set);
014a1138
JZ
5759 if (var->n_var_parts == 0)
5760 {
d24686d7
JJ
5761 void **slot;
5762
5763 drop_var:
b5b8b0ac 5764 slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
014a1138 5765 if (slot)
d24686d7
JJ
5766 {
5767 if (shared_hash_shared (set->vars))
b5b8b0ac 5768 slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
d24686d7
JJ
5769 NO_INSERT);
5770 htab_clear_slot (shared_hash_htab (set->vars), slot);
5771 }
014a1138
JZ
5772 }
5773 }
5774}
5775
ca787200
AO
5776/* Look for the index in VAR->var_part corresponding to OFFSET.
5777 Return -1 if not found. If INSERTION_POINT is non-NULL, the
5778 referenced int will be set to the index that the part has or should
5779 have, if it should be inserted. */
5780
5781static inline int
5782find_variable_location_part (variable var, HOST_WIDE_INT offset,
5783 int *insertion_point)
5784{
5785 int pos, low, high;
5786
5787 /* Find the location part. */
5788 low = 0;
5789 high = var->n_var_parts;
5790 while (low != high)
5791 {
5792 pos = (low + high) / 2;
5793 if (var->var_part[pos].offset < offset)
5794 low = pos + 1;
5795 else
5796 high = pos;
5797 }
5798 pos = low;
5799
5800 if (insertion_point)
5801 *insertion_point = pos;
5802
5803 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
5804 return pos;
5805
5806 return -1;
5807}
5808
b5b8b0ac
AO
5809static void **
5810set_slot_part (dataflow_set *set, rtx loc, void **slot,
5811 decl_or_value dv, HOST_WIDE_INT offset,
5812 enum var_init_status initialized, rtx set_src)
014a1138 5813{
ca787200 5814 int pos;
11599d14
JZ
5815 location_chain node, next;
5816 location_chain *nextp;
014a1138 5817 variable var;
b5b8b0ac
AO
5818 bool onepart = dv_onepart_p (dv);
5819
5820 gcc_assert (offset == 0 || !onepart);
5821 gcc_assert (loc != dv_as_opaque (dv));
5822
5823 var = (variable) *slot;
d24686d7 5824
7eb3f1f7
JJ
5825 if (! flag_var_tracking_uninit)
5826 initialized = VAR_INIT_STATUS_INITIALIZED;
5827
b5b8b0ac 5828 if (!var)
014a1138
JZ
5829 {
5830 /* Create new variable information. */
b5b8b0ac
AO
5831 var = (variable) pool_alloc (dv_pool (dv));
5832 var->dv = dv;
81f2eadb 5833 var->refcount = 1;
014a1138
JZ
5834 var->n_var_parts = 1;
5835 var->var_part[0].offset = offset;
5836 var->var_part[0].loc_chain = NULL;
5837 var->var_part[0].cur_loc = NULL;
5838 *slot = var;
5839 pos = 0;
b5b8b0ac
AO
5840 nextp = &var->var_part[0].loc_chain;
5841 if (emit_notes && dv_is_value_p (dv))
5842 add_cselib_value_chains (dv);
5843 }
5844 else if (onepart)
5845 {
5846 int r = -1, c = 0;
5847
5848 gcc_assert (dv_as_opaque (var->dv) == dv_as_opaque (dv));
5849
5850 pos = 0;
5851
5852 if (GET_CODE (loc) == VALUE)
5853 {
5854 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
5855 nextp = &node->next)
5856 if (GET_CODE (node->loc) == VALUE)
5857 {
5858 if (node->loc == loc)
5859 {
5860 r = 0;
5861 break;
5862 }
5863 if (canon_value_cmp (node->loc, loc))
5864 c++;
5865 else
5866 {
5867 r = 1;
5868 break;
5869 }
5870 }
5871 else if (REG_P (node->loc) || MEM_P (node->loc))
5872 c++;
5873 else
5874 {
5875 r = 1;
5876 break;
5877 }
5878 }
5879 else if (REG_P (loc))
5880 {
5881 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
5882 nextp = &node->next)
5883 if (REG_P (node->loc))
5884 {
5885 if (REGNO (node->loc) < REGNO (loc))
5886 c++;
5887 else
5888 {
5889 if (REGNO (node->loc) == REGNO (loc))
5890 r = 0;
5891 else
5892 r = 1;
5893 break;
5894 }
5895 }
5896 else
5897 {
5898 r = 1;
5899 break;
5900 }
5901 }
5902 else if (MEM_P (loc))
5903 {
5904 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
5905 nextp = &node->next)
5906 if (REG_P (node->loc))
5907 c++;
5908 else if (MEM_P (node->loc))
5909 {
5910 if ((r = loc_cmp (XEXP (node->loc, 0), XEXP (loc, 0))) >= 0)
5911 break;
5912 else
5913 c++;
5914 }
5915 else
5916 {
5917 r = 1;
5918 break;
5919 }
5920 }
5921 else
5922 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
5923 nextp = &node->next)
5924 if ((r = loc_cmp (node->loc, loc)) >= 0)
5925 break;
5926 else
5927 c++;
5928
5929 if (r == 0)
5930 return slot;
5931
5932 if (var->refcount > 1 || shared_hash_shared (set->vars))
5933 {
5934 slot = unshare_variable (set, slot, var, initialized);
5935 var = (variable)*slot;
5936 for (nextp = &var->var_part[0].loc_chain; c;
5937 nextp = &(*nextp)->next)
5938 c--;
5939 gcc_assert ((!node && !*nextp) || node->loc == (*nextp)->loc);
5940 }
014a1138
JZ
5941 }
5942 else
5943 {
ca787200
AO
5944 int inspos = 0;
5945
b5b8b0ac 5946 gcc_assert (dv_as_decl (var->dv) == dv_as_decl (dv));
014a1138 5947
ca787200 5948 pos = find_variable_location_part (var, offset, &inspos);
014a1138 5949
ca787200 5950 if (pos >= 0)
014a1138 5951 {
81f2eadb
JZ
5952 node = var->var_part[pos].loc_chain;
5953
5954 if (node
f8cfc6aa 5955 && ((REG_P (node->loc) && REG_P (loc)
81f2eadb
JZ
5956 && REGNO (node->loc) == REGNO (loc))
5957 || rtx_equal_p (node->loc, loc)))
5958 {
5959 /* LOC is in the beginning of the chain so we have nothing
5960 to do. */
62760ffd
CT
5961 if (node->init < initialized)
5962 node->init = initialized;
5963 if (set_src != NULL)
5964 node->set_src = set_src;
5965
b5b8b0ac 5966 return slot;
81f2eadb
JZ
5967 }
5968 else
5969 {
5970 /* We have to make a copy of a shared variable. */
d24686d7 5971 if (var->refcount > 1 || shared_hash_shared (set->vars))
b5b8b0ac
AO
5972 {
5973 slot = unshare_variable (set, slot, var, initialized);
5974 var = (variable)*slot;
5975 }
81f2eadb
JZ
5976 }
5977 }
5978 else
5979 {
5980 /* We have not found the location part, new one will be created. */
5981
5982 /* We have to make a copy of the shared variable. */
d24686d7 5983 if (var->refcount > 1 || shared_hash_shared (set->vars))
b5b8b0ac
AO
5984 {
5985 slot = unshare_variable (set, slot, var, initialized);
5986 var = (variable)*slot;
5987 }
014a1138 5988
014a1138
JZ
5989 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
5990 thus there are at most MAX_VAR_PARTS different offsets. */
b5b8b0ac
AO
5991 gcc_assert (var->n_var_parts < MAX_VAR_PARTS
5992 && (!var->n_var_parts || !dv_onepart_p (var->dv)));
014a1138 5993
ca787200
AO
5994 /* We have to move the elements of array starting at index
5995 inspos to the next position. */
5996 for (pos = var->n_var_parts; pos > inspos; pos--)
5997 var->var_part[pos] = var->var_part[pos - 1];
014a1138
JZ
5998
5999 var->n_var_parts++;
6000 var->var_part[pos].offset = offset;
6001 var->var_part[pos].loc_chain = NULL;
6002 var->var_part[pos].cur_loc = NULL;
6003 }
014a1138 6004
b5b8b0ac
AO
6005 /* Delete the location from the list. */
6006 nextp = &var->var_part[pos].loc_chain;
6007 for (node = var->var_part[pos].loc_chain; node; node = next)
014a1138 6008 {
b5b8b0ac
AO
6009 next = node->next;
6010 if ((REG_P (node->loc) && REG_P (loc)
6011 && REGNO (node->loc) == REGNO (loc))
6012 || rtx_equal_p (node->loc, loc))
6013 {
6014 /* Save these values, to assign to the new node, before
6015 deleting this one. */
6016 if (node->init > initialized)
6017 initialized = node->init;
6018 if (node->set_src != NULL && set_src == NULL)
6019 set_src = node->set_src;
6020 pool_free (loc_chain_pool, node);
6021 *nextp = next;
6022 break;
6023 }
6024 else
6025 nextp = &node->next;
014a1138 6026 }
b5b8b0ac
AO
6027
6028 nextp = &var->var_part[pos].loc_chain;
014a1138
JZ
6029 }
6030
6031 /* Add the location to the beginning. */
3d9a9f94 6032 node = (location_chain) pool_alloc (loc_chain_pool);
014a1138 6033 node->loc = loc;
62760ffd
CT
6034 node->init = initialized;
6035 node->set_src = set_src;
b5b8b0ac
AO
6036 node->next = *nextp;
6037 *nextp = node;
6038
6039 if (onepart && emit_notes)
6040 add_value_chains (var->dv, loc);
014a1138
JZ
6041
6042 /* If no location was emitted do so. */
6043 if (var->var_part[pos].cur_loc == NULL)
6044 {
6045 var->var_part[pos].cur_loc = loc;
d24686d7 6046 variable_was_changed (var, set);
014a1138 6047 }
b5b8b0ac
AO
6048
6049 return slot;
014a1138
JZ
6050}
6051
b5b8b0ac
AO
6052/* Set the part of variable's location in the dataflow set SET. The
6053 variable part is specified by variable's declaration in DV and
6054 offset OFFSET and the part's location by LOC. IOPT should be
6055 NO_INSERT if the variable is known to be in SET already and the
6056 variable hash table must not be resized, and INSERT otherwise. */
ca787200
AO
6057
6058static void
b5b8b0ac
AO
6059set_variable_part (dataflow_set *set, rtx loc,
6060 decl_or_value dv, HOST_WIDE_INT offset,
6061 enum var_init_status initialized, rtx set_src,
6062 enum insert_option iopt)
ca787200 6063{
b5b8b0ac 6064 void **slot;
ca787200 6065
b5b8b0ac
AO
6066 if (iopt == NO_INSERT)
6067 slot = shared_hash_find_slot_noinsert (set->vars, dv);
6068 else
6069 {
6070 slot = shared_hash_find_slot (set->vars, dv);
6071 if (!slot)
6072 slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt);
6073 }
6074 slot = set_slot_part (set, loc, slot, dv, offset, initialized, set_src);
6075}
ca787200 6076
b5b8b0ac
AO
6077/* Remove all recorded register locations for the given variable part
6078 from dataflow set SET, except for those that are identical to loc.
6079 The variable part is specified by variable's declaration or value
6080 DV and offset OFFSET. */
6081
6082static void **
6083clobber_slot_part (dataflow_set *set, rtx loc, void **slot,
6084 HOST_WIDE_INT offset, rtx set_src)
6085{
6086 variable var = (variable) *slot;
6087 int pos = find_variable_location_part (var, offset, NULL);
6088
6089 if (pos >= 0)
ca787200 6090 {
b5b8b0ac 6091 location_chain node, next;
ca787200 6092
b5b8b0ac
AO
6093 /* Remove the register locations from the dataflow set. */
6094 next = var->var_part[pos].loc_chain;
6095 for (node = next; node; node = next)
ca787200 6096 {
b5b8b0ac
AO
6097 next = node->next;
6098 if (node->loc != loc
6099 && (!flag_var_tracking_uninit
6100 || !set_src
6101 || MEM_P (set_src)
6102 || !rtx_equal_p (set_src, node->set_src)))
ca787200 6103 {
b5b8b0ac 6104 if (REG_P (node->loc))
d3067303 6105 {
b5b8b0ac
AO
6106 attrs anode, anext;
6107 attrs *anextp;
6108
6109 /* Remove the variable part from the register's
6110 list, but preserve any other variable parts
6111 that might be regarded as live in that same
6112 register. */
6113 anextp = &set->regs[REGNO (node->loc)];
6114 for (anode = *anextp; anode; anode = anext)
d3067303 6115 {
b5b8b0ac
AO
6116 anext = anode->next;
6117 if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
6118 && anode->offset == offset)
d3067303 6119 {
b5b8b0ac
AO
6120 pool_free (attrs_pool, anode);
6121 *anextp = anext;
d3067303 6122 }
b5b8b0ac
AO
6123 else
6124 anextp = &anode->next;
d3067303 6125 }
b5b8b0ac
AO
6126 }
6127
6128 slot = delete_slot_part (set, node->loc, slot, offset);
6129 }
6130 }
6131 }
6132
6133 return slot;
6134}
6135
6136/* Remove all recorded register locations for the given variable part
6137 from dataflow set SET, except for those that are identical to loc.
6138 The variable part is specified by variable's declaration or value
6139 DV and offset OFFSET. */
6140
6141static void
6142clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6143 HOST_WIDE_INT offset, rtx set_src)
6144{
6145 void **slot;
6146
6147 if (!dv_as_opaque (dv)
6148 || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
6149 return;
6150
6151 slot = shared_hash_find_slot_noinsert (set->vars, dv);
6152 if (!slot)
6153 return;
6154
6155 slot = clobber_slot_part (set, loc, slot, offset, set_src);
6156}
d3067303 6157
b5b8b0ac
AO
6158/* Delete the part of variable's location from dataflow set SET. The
6159 variable part is specified by its SET->vars slot SLOT and offset
6160 OFFSET and the part's location by LOC. */
6161
6162static void **
6163delete_slot_part (dataflow_set *set, rtx loc, void **slot,
6164 HOST_WIDE_INT offset)
6165{
6166 variable var = (variable) *slot;
6167 int pos = find_variable_location_part (var, offset, NULL);
6168
6169 if (pos >= 0)
6170 {
6171 location_chain node, next;
6172 location_chain *nextp;
6173 bool changed;
6174
6175 if (var->refcount > 1 || shared_hash_shared (set->vars))
6176 {
6177 /* If the variable contains the location part we have to
6178 make a copy of the variable. */
6179 for (node = var->var_part[pos].loc_chain; node;
6180 node = node->next)
6181 {
6182 if ((REG_P (node->loc) && REG_P (loc)
6183 && REGNO (node->loc) == REGNO (loc))
6184 || rtx_equal_p (node->loc, loc))
6185 {
6186 slot = unshare_variable (set, slot, var,
6187 VAR_INIT_STATUS_UNKNOWN);
6188 var = (variable)*slot;
6189 break;
d3067303 6190 }
ca787200
AO
6191 }
6192 }
b5b8b0ac
AO
6193
6194 /* Delete the location part. */
6195 nextp = &var->var_part[pos].loc_chain;
6196 for (node = *nextp; node; node = next)
6197 {
6198 next = node->next;
6199 if ((REG_P (node->loc) && REG_P (loc)
6200 && REGNO (node->loc) == REGNO (loc))
6201 || rtx_equal_p (node->loc, loc))
6202 {
6203 if (emit_notes && pos == 0 && dv_onepart_p (var->dv))
6204 remove_value_chains (var->dv, node->loc);
6205 pool_free (loc_chain_pool, node);
6206 *nextp = next;
6207 break;
6208 }
6209 else
6210 nextp = &node->next;
6211 }
6212
6213 /* If we have deleted the location which was last emitted
6214 we have to emit new location so add the variable to set
6215 of changed variables. */
6216 if (var->var_part[pos].cur_loc
6217 && ((REG_P (loc)
6218 && REG_P (var->var_part[pos].cur_loc)
6219 && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
6220 || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
6221 {
6222 changed = true;
6223 if (var->var_part[pos].loc_chain)
6224 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc;
6225 }
6226 else
6227 changed = false;
6228
6229 if (var->var_part[pos].loc_chain == NULL)
6230 {
6231 gcc_assert (changed);
6232 var->n_var_parts--;
6233 if (emit_notes && var->n_var_parts == 0 && dv_is_value_p (var->dv))
6234 remove_cselib_value_chains (var->dv);
6235 while (pos < var->n_var_parts)
6236 {
6237 var->var_part[pos] = var->var_part[pos + 1];
6238 pos++;
6239 }
6240 }
6241 if (changed)
6242 variable_was_changed (var, set);
6243 }
6244
6245 return slot;
6246}
6247
6248/* Delete the part of variable's location from dataflow set SET. The
6249 variable part is specified by variable's declaration or value DV
6250 and offset OFFSET and the part's location by LOC. */
6251
6252static void
6253delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6254 HOST_WIDE_INT offset)
6255{
6256 void **slot = shared_hash_find_slot_noinsert (set->vars, dv);
6257 if (!slot)
6258 return;
6259
6260 slot = delete_slot_part (set, loc, slot, offset);
6261}
6262
b5b8b0ac 6263/* Callback for cselib_expand_value, that looks for expressions
0b7e34d7
AO
6264 holding the value in the var-tracking hash tables. Return X for
6265 standard processing, anything else is to be used as-is. */
b5b8b0ac
AO
6266
6267static rtx
6268vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
6269{
6270 htab_t vars = (htab_t)data;
6271 decl_or_value dv;
6272 variable var;
6273 location_chain loc;
0ca5af51 6274 rtx result, subreg, xret;
b5b8b0ac 6275
0ca5af51 6276 switch (GET_CODE (x))
0b7e34d7 6277 {
0ca5af51
AO
6278 case SUBREG:
6279 subreg = SUBREG_REG (x);
0b7e34d7
AO
6280
6281 if (GET_CODE (SUBREG_REG (x)) != VALUE)
6282 return x;
6283
6284 subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
6285 max_depth - 1,
6286 vt_expand_loc_callback, data);
6287
6288 if (!subreg)
6289 return NULL;
6290
6291 result = simplify_gen_subreg (GET_MODE (x), subreg,
6292 GET_MODE (SUBREG_REG (x)),
6293 SUBREG_BYTE (x));
6294
6295 /* Invalid SUBREGs are ok in debug info. ??? We could try
6296 alternate expansions for the VALUE as well. */
6297 if (!result && (REG_P (subreg) || MEM_P (subreg)))
6298 result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
6299
6300 return result;
0b7e34d7 6301
0ca5af51 6302 case DEBUG_EXPR:
e4fb38bd 6303 dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
0ca5af51
AO
6304 xret = NULL;
6305 break;
6306
6307 case VALUE:
6308 dv = dv_from_value (x);
6309 xret = x;
6310 break;
6311
6312 default:
6313 return x;
6314 }
b5b8b0ac
AO
6315
6316 if (VALUE_RECURSED_INTO (x))
0ca5af51 6317 return NULL;
b5b8b0ac 6318
b5b8b0ac
AO
6319 var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
6320
6321 if (!var)
0ca5af51 6322 return xret;
b5b8b0ac
AO
6323
6324 if (var->n_var_parts == 0)
0ca5af51 6325 return xret;
b5b8b0ac
AO
6326
6327 gcc_assert (var->n_var_parts == 1);
6328
6329 VALUE_RECURSED_INTO (x) = true;
6330 result = NULL;
6331
6332 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
6333 {
6334 result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
6335 vt_expand_loc_callback, vars);
b5b8b0ac
AO
6336 if (result)
6337 break;
ca787200 6338 }
b5b8b0ac
AO
6339
6340 VALUE_RECURSED_INTO (x) = false;
0b7e34d7
AO
6341 if (result)
6342 return result;
6343 else
0ca5af51 6344 return xret;
ca787200
AO
6345}
6346
b5b8b0ac
AO
6347/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
6348 tables. */
014a1138 6349
b5b8b0ac
AO
6350static rtx
6351vt_expand_loc (rtx loc, htab_t vars)
014a1138 6352{
b5b8b0ac
AO
6353 if (!MAY_HAVE_DEBUG_INSNS)
6354 return loc;
81f2eadb 6355
3af4ba41
RS
6356 loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
6357 vt_expand_loc_callback, vars);
014a1138 6358
b5b8b0ac
AO
6359 if (loc && MEM_P (loc))
6360 loc = targetm.delegitimize_address (loc);
014a1138 6361
b5b8b0ac 6362 return loc;
014a1138
JZ
6363}
6364
6365/* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
6366 additional parameters: WHERE specifies whether the note shall be emitted
b5b8b0ac 6367 before or after instruction INSN. */
014a1138
JZ
6368
6369static int
6370emit_note_insn_var_location (void **varp, void *data)
6371{
b5b8b0ac 6372 variable var = (variable) *varp;
014a1138
JZ
6373 rtx insn = ((emit_note_data *)data)->insn;
6374 enum emit_note_where where = ((emit_note_data *)data)->where;
b5b8b0ac 6375 htab_t vars = ((emit_note_data *)data)->vars;
014a1138 6376 rtx note;
c938250d 6377 int i, j, n_var_parts;
014a1138 6378 bool complete;
62760ffd 6379 enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
014a1138
JZ
6380 HOST_WIDE_INT last_limit;
6381 tree type_size_unit;
c938250d
JJ
6382 HOST_WIDE_INT offsets[MAX_VAR_PARTS];
6383 rtx loc[MAX_VAR_PARTS];
b5b8b0ac 6384 tree decl;
014a1138 6385
b5b8b0ac
AO
6386 if (dv_is_value_p (var->dv))
6387 goto clear;
6388
6389 decl = dv_as_decl (var->dv);
6390
0ca5af51
AO
6391 if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
6392 goto clear;
6393
b5b8b0ac 6394 gcc_assert (decl);
014a1138
JZ
6395
6396 complete = true;
6397 last_limit = 0;
c938250d 6398 n_var_parts = 0;
014a1138
JZ
6399 for (i = 0; i < var->n_var_parts; i++)
6400 {
c938250d 6401 enum machine_mode mode, wider_mode;
b5b8b0ac 6402 rtx loc2;
c938250d 6403
014a1138
JZ
6404 if (last_limit < var->var_part[i].offset)
6405 {
6406 complete = false;
6407 break;
6408 }
c938250d
JJ
6409 else if (last_limit > var->var_part[i].offset)
6410 continue;
6411 offsets[n_var_parts] = var->var_part[i].offset;
b5b8b0ac
AO
6412 loc2 = vt_expand_loc (var->var_part[i].loc_chain->loc, vars);
6413 if (!loc2)
6414 {
6415 complete = false;
6416 continue;
6417 }
6418 loc[n_var_parts] = loc2;
c938250d 6419 mode = GET_MODE (loc[n_var_parts]);
62760ffd 6420 initialized = var->var_part[i].loc_chain->init;
c938250d
JJ
6421 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
6422
6423 /* Attempt to merge adjacent registers or memory. */
6424 wider_mode = GET_MODE_WIDER_MODE (mode);
6425 for (j = i + 1; j < var->n_var_parts; j++)
6426 if (last_limit <= var->var_part[j].offset)
6427 break;
6428 if (j < var->n_var_parts
6429 && wider_mode != VOIDmode
b5b8b0ac
AO
6430 && (loc2 = vt_expand_loc (var->var_part[j].loc_chain->loc, vars))
6431 && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2)
6432 && mode == GET_MODE (loc2)
c938250d
JJ
6433 && last_limit == var->var_part[j].offset)
6434 {
6435 rtx new_loc = NULL;
c938250d
JJ
6436
6437 if (REG_P (loc[n_var_parts])
6438 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
6439 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
09e18274 6440 && end_hard_regno (mode, REGNO (loc[n_var_parts]))
c938250d
JJ
6441 == REGNO (loc2))
6442 {
6443 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
6444 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
6445 mode, 0);
6446 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
6447 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
6448 if (new_loc)
6449 {
6450 if (!REG_P (new_loc)
6451 || REGNO (new_loc) != REGNO (loc[n_var_parts]))
6452 new_loc = NULL;
6453 else
6454 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
6455 }
6456 }
6457 else if (MEM_P (loc[n_var_parts])
6458 && GET_CODE (XEXP (loc2, 0)) == PLUS
481683e1
SZ
6459 && REG_P (XEXP (XEXP (loc2, 0), 0))
6460 && CONST_INT_P (XEXP (XEXP (loc2, 0), 1)))
c938250d 6461 {
481683e1 6462 if ((REG_P (XEXP (loc[n_var_parts], 0))
c938250d
JJ
6463 && rtx_equal_p (XEXP (loc[n_var_parts], 0),
6464 XEXP (XEXP (loc2, 0), 0))
6465 && INTVAL (XEXP (XEXP (loc2, 0), 1))
6466 == GET_MODE_SIZE (mode))
6467 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
481683e1 6468 && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1))
c938250d
JJ
6469 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
6470 XEXP (XEXP (loc2, 0), 0))
6471 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
6472 + GET_MODE_SIZE (mode)
6473 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
6474 new_loc = adjust_address_nv (loc[n_var_parts],
6475 wider_mode, 0);
6476 }
6477
6478 if (new_loc)
6479 {
6480 loc[n_var_parts] = new_loc;
6481 mode = wider_mode;
6482 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
6483 i = j;
6484 }
6485 }
6486 ++n_var_parts;
014a1138 6487 }
b5b8b0ac 6488 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl));
014a1138
JZ
6489 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
6490 complete = false;
6491
b5b8b0ac
AO
6492 if (where != EMIT_NOTE_BEFORE_INSN)
6493 {
6494 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
6495 if (where == EMIT_NOTE_AFTER_CALL_INSN)
6496 NOTE_DURING_CALL_P (note) = true;
6497 }
014a1138
JZ
6498 else
6499 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
6500
62760ffd
CT
6501 if (! flag_var_tracking_uninit)
6502 initialized = VAR_INIT_STATUS_INITIALIZED;
6503
014a1138
JZ
6504 if (!complete)
6505 {
b5b8b0ac 6506 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl,
62760ffd 6507 NULL_RTX, (int) initialized);
014a1138 6508 }
c938250d 6509 else if (n_var_parts == 1)
014a1138
JZ
6510 {
6511 rtx expr_list
c938250d 6512 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
014a1138 6513
b5b8b0ac 6514 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl,
62760ffd
CT
6515 expr_list,
6516 (int) initialized);
014a1138 6517 }
c938250d 6518 else if (n_var_parts)
014a1138 6519 {
014a1138
JZ
6520 rtx parallel;
6521
c938250d
JJ
6522 for (i = 0; i < n_var_parts; i++)
6523 loc[i]
6524 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
6525
014a1138 6526 parallel = gen_rtx_PARALLEL (VOIDmode,
c938250d 6527 gen_rtvec_v (n_var_parts, loc));
b5b8b0ac 6528 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, decl,
62760ffd
CT
6529 parallel,
6530 (int) initialized);
014a1138
JZ
6531 }
6532
b5b8b0ac
AO
6533 clear:
6534 set_dv_changed (var->dv, false);
014a1138
JZ
6535 htab_clear_slot (changed_variables, varp);
6536
014a1138
JZ
6537 /* Continue traversing the hash table. */
6538 return 1;
6539}
6540
b5b8b0ac
AO
6541DEF_VEC_P (variable);
6542DEF_VEC_ALLOC_P (variable, heap);
6543
6544/* Stack of variable_def pointers that need processing with
6545 check_changed_vars_2. */
6546
6547static VEC (variable, heap) *changed_variables_stack;
6548
6549/* Populate changed_variables_stack with variable_def pointers
6550 that need variable_was_changed called on them. */
6551
6552static int
6553check_changed_vars_1 (void **slot, void *data)
6554{
6555 variable var = (variable) *slot;
6556 htab_t htab = (htab_t) data;
6557
6558 if (dv_is_value_p (var->dv))
6559 {
6560 value_chain vc
6561 = (value_chain) htab_find_with_hash (value_chains, var->dv,
6562 dv_htab_hash (var->dv));
6563
6564 if (vc == NULL)
6565 return 1;
6566 for (vc = vc->next; vc; vc = vc->next)
6567 if (!dv_changed_p (vc->dv))
6568 {
6569 variable vcvar
6570 = (variable) htab_find_with_hash (htab, vc->dv,
6571 dv_htab_hash (vc->dv));
6572 if (vcvar)
6573 VEC_safe_push (variable, heap, changed_variables_stack,
6574 vcvar);
6575 }
6576 }
6577 return 1;
6578}
6579
6580/* Add VAR to changed_variables and also for VALUEs add recursively
6581 all DVs that aren't in changed_variables yet but reference the
6582 VALUE from its loc_chain. */
6583
6584static void
6585check_changed_vars_2 (variable var, htab_t htab)
6586{
6587 variable_was_changed (var, NULL);
6588 if (dv_is_value_p (var->dv))
6589 {
6590 value_chain vc
6591 = (value_chain) htab_find_with_hash (value_chains, var->dv,
6592 dv_htab_hash (var->dv));
6593
6594 if (vc == NULL)
6595 return;
6596 for (vc = vc->next; vc; vc = vc->next)
6597 if (!dv_changed_p (vc->dv))
6598 {
6599 variable vcvar
6600 = (variable) htab_find_with_hash (htab, vc->dv,
6601 dv_htab_hash (vc->dv));
6602 if (vcvar)
6603 check_changed_vars_2 (vcvar, htab);
6604 }
6605 }
6606}
6607
014a1138
JZ
6608/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
6609 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
6610 shall be emitted before of after instruction INSN. */
6611
6612static void
b5b8b0ac
AO
6613emit_notes_for_changes (rtx insn, enum emit_note_where where,
6614 shared_hash vars)
014a1138
JZ
6615{
6616 emit_note_data data;
b5b8b0ac
AO
6617 htab_t htab = shared_hash_htab (vars);
6618
6619 if (!htab_elements (changed_variables))
6620 return;
6621
6622 if (MAY_HAVE_DEBUG_INSNS)
6623 {
6624 /* Unfortunately this has to be done in two steps, because
6625 we can't traverse a hashtab into which we are inserting
6626 through variable_was_changed. */
6627 htab_traverse (changed_variables, check_changed_vars_1, htab);
6628 while (VEC_length (variable, changed_variables_stack) > 0)
6629 check_changed_vars_2 (VEC_pop (variable, changed_variables_stack),
6630 htab);
6631 }
014a1138
JZ
6632
6633 data.insn = insn;
6634 data.where = where;
b5b8b0ac
AO
6635 data.vars = htab;
6636
014a1138
JZ
6637 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
6638}
6639
6640/* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
6641 same variable in hash table DATA or is not there at all. */
6642
6643static int
6644emit_notes_for_differences_1 (void **slot, void *data)
6645{
6646 htab_t new_vars = (htab_t) data;
6647 variable old_var, new_var;
6648
b5b8b0ac
AO
6649 old_var = (variable) *slot;
6650 new_var = (variable) htab_find_with_hash (new_vars, old_var->dv,
6651 dv_htab_hash (old_var->dv));
014a1138
JZ
6652
6653 if (!new_var)
6654 {
6655 /* Variable has disappeared. */
6656 variable empty_var;
6657
b5b8b0ac
AO
6658 empty_var = (variable) pool_alloc (dv_pool (old_var->dv));
6659 empty_var->dv = old_var->dv;
d24686d7 6660 empty_var->refcount = 0;
014a1138 6661 empty_var->n_var_parts = 0;
b5b8b0ac
AO
6662 if (dv_onepart_p (old_var->dv))
6663 {
6664 location_chain lc;
6665
6666 gcc_assert (old_var->n_var_parts == 1);
6667 for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next)
6668 remove_value_chains (old_var->dv, lc->loc);
6669 if (dv_is_value_p (old_var->dv))
6670 remove_cselib_value_chains (old_var->dv);
6671 }
014a1138
JZ
6672 variable_was_changed (empty_var, NULL);
6673 }
83532fb7 6674 else if (variable_different_p (old_var, new_var, true))
014a1138 6675 {
b5b8b0ac
AO
6676 if (dv_onepart_p (old_var->dv))
6677 {
6678 location_chain lc1, lc2;
6679
6680 gcc_assert (old_var->n_var_parts == 1);
6681 gcc_assert (new_var->n_var_parts == 1);
6682 lc1 = old_var->var_part[0].loc_chain;
6683 lc2 = new_var->var_part[0].loc_chain;
6684 while (lc1
6685 && lc2
6686 && ((REG_P (lc1->loc) && REG_P (lc2->loc))
6687 || rtx_equal_p (lc1->loc, lc2->loc)))
6688 {
6689 lc1 = lc1->next;
6690 lc2 = lc2->next;
6691 }
6692 for (; lc2; lc2 = lc2->next)
6693 add_value_chains (old_var->dv, lc2->loc);
6694 for (; lc1; lc1 = lc1->next)
6695 remove_value_chains (old_var->dv, lc1->loc);
6696 }
014a1138
JZ
6697 variable_was_changed (new_var, NULL);
6698 }
6699
6700 /* Continue traversing the hash table. */
6701 return 1;
6702}
6703
6704/* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
6705 table DATA. */
6706
6707static int
6708emit_notes_for_differences_2 (void **slot, void *data)
6709{
6710 htab_t old_vars = (htab_t) data;
6711 variable old_var, new_var;
6712
b5b8b0ac
AO
6713 new_var = (variable) *slot;
6714 old_var = (variable) htab_find_with_hash (old_vars, new_var->dv,
6715 dv_htab_hash (new_var->dv));
014a1138
JZ
6716 if (!old_var)
6717 {
6718 /* Variable has appeared. */
b5b8b0ac
AO
6719 if (dv_onepart_p (new_var->dv))
6720 {
6721 location_chain lc;
6722
6723 gcc_assert (new_var->n_var_parts == 1);
6724 for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next)
6725 add_value_chains (new_var->dv, lc->loc);
6726 if (dv_is_value_p (new_var->dv))
6727 add_cselib_value_chains (new_var->dv);
6728 }
014a1138
JZ
6729 variable_was_changed (new_var, NULL);
6730 }
6731
6732 /* Continue traversing the hash table. */
6733 return 1;
6734}
6735
6736/* Emit notes before INSN for differences between dataflow sets OLD_SET and
6737 NEW_SET. */
6738
6739static void
6740emit_notes_for_differences (rtx insn, dataflow_set *old_set,
6741 dataflow_set *new_set)
6742{
d24686d7
JJ
6743 htab_traverse (shared_hash_htab (old_set->vars),
6744 emit_notes_for_differences_1,
6745 shared_hash_htab (new_set->vars));
6746 htab_traverse (shared_hash_htab (new_set->vars),
6747 emit_notes_for_differences_2,
6748 shared_hash_htab (old_set->vars));
b5b8b0ac 6749 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
014a1138
JZ
6750}
6751
6752/* Emit the notes for changes of location parts in the basic block BB. */
6753
6754static void
b5b8b0ac 6755emit_notes_in_bb (basic_block bb, dataflow_set *set)
014a1138
JZ
6756{
6757 int i;
014a1138 6758
b5b8b0ac
AO
6759 dataflow_set_clear (set);
6760 dataflow_set_copy (set, &VTI (bb)->in);
014a1138
JZ
6761
6762 for (i = 0; i < VTI (bb)->n_mos; i++)
6763 {
6764 rtx insn = VTI (bb)->mos[i].insn;
6765
6766 switch (VTI (bb)->mos[i].type)
6767 {
6768 case MO_CALL:
b5b8b0ac
AO
6769 dataflow_set_clear_at_call (set);
6770 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
6771 break;
6772
6773 case MO_USE:
014a1138 6774 {
b5b8b0ac 6775 rtx loc = VTI (bb)->mos[i].u.loc;
014a1138 6776
b5b8b0ac
AO
6777 if (REG_P (loc))
6778 var_reg_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
6779 else
6780 var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
6781
6782 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
014a1138
JZ
6783 }
6784 break;
6785
b5b8b0ac 6786 case MO_VAL_LOC:
dedc1e6d
AO
6787 {
6788 rtx loc = VTI (bb)->mos[i].u.loc;
b5b8b0ac
AO
6789 rtx val, vloc;
6790 tree var;
7eb3f1f7 6791
b5b8b0ac
AO
6792 if (GET_CODE (loc) == CONCAT)
6793 {
6794 val = XEXP (loc, 0);
6795 vloc = XEXP (loc, 1);
6796 }
dedc1e6d 6797 else
b5b8b0ac
AO
6798 {
6799 val = NULL_RTX;
6800 vloc = loc;
6801 }
6802
6803 var = PAT_VAR_LOCATION_DECL (vloc);
6804
6805 clobber_variable_part (set, NULL_RTX,
6806 dv_from_decl (var), 0, NULL_RTX);
6807 if (val)
6808 {
6809 if (VAL_NEEDS_RESOLUTION (loc))
6810 val_resolve (set, val, PAT_VAR_LOCATION_LOC (vloc), insn);
6811 set_variable_part (set, val, dv_from_decl (var), 0,
6812 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
6813 INSERT);
6814 }
6815
6816 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
6817 }
6818 break;
6819
6820 case MO_VAL_USE:
6821 {
6822 rtx loc = VTI (bb)->mos[i].u.loc;
6823 rtx val, vloc, uloc;
6824
6825 vloc = uloc = XEXP (loc, 1);
6826 val = XEXP (loc, 0);
6827
6828 if (GET_CODE (val) == CONCAT)
6829 {
6830 uloc = XEXP (val, 1);
6831 val = XEXP (val, 0);
6832 }
6833
6834 if (VAL_NEEDS_RESOLUTION (loc))
6835 val_resolve (set, val, vloc, insn);
6836
6837 if (VAL_HOLDS_TRACK_EXPR (loc))
6838 {
6839 if (GET_CODE (uloc) == REG)
6840 var_reg_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
6841 NULL);
6842 else if (GET_CODE (uloc) == MEM)
6843 var_mem_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
6844 NULL);
6845 }
6846
6847 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
6848 }
6849 break;
6850
6851 case MO_VAL_SET:
6852 {
6853 rtx loc = VTI (bb)->mos[i].u.loc;
6854 rtx val, vloc, uloc;
dedc1e6d 6855
b5b8b0ac
AO
6856 vloc = uloc = XEXP (loc, 1);
6857 val = XEXP (loc, 0);
6858
6859 if (GET_CODE (val) == CONCAT)
6860 {
6861 vloc = XEXP (val, 1);
6862 val = XEXP (val, 0);
6863 }
6864
6865 if (GET_CODE (vloc) == SET)
6866 {
6867 rtx vsrc = SET_SRC (vloc);
6868
6869 gcc_assert (val != vsrc);
6870 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
6871
6872 vloc = SET_DEST (vloc);
6873
6874 if (VAL_NEEDS_RESOLUTION (loc))
6875 val_resolve (set, val, vsrc, insn);
6876 }
6877 else if (VAL_NEEDS_RESOLUTION (loc))
6878 {
6879 gcc_assert (GET_CODE (uloc) == SET
6880 && GET_CODE (SET_SRC (uloc)) == REG);
6881 val_resolve (set, val, SET_SRC (uloc), insn);
6882 }
6883
6884 if (VAL_HOLDS_TRACK_EXPR (loc))
6885 {
6886 if (VAL_EXPR_IS_CLOBBERED (loc))
6887 {
6888 if (REG_P (uloc))
6889 var_reg_delete (set, uloc, true);
6890 else if (MEM_P (uloc))
6891 var_mem_delete (set, uloc, true);
6892 }
6893 else
6894 {
6895 bool copied_p = VAL_EXPR_IS_COPIED (loc);
6896 rtx set_src = NULL;
6897 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
6898
6899 if (GET_CODE (uloc) == SET)
6900 {
6901 set_src = SET_SRC (uloc);
6902 uloc = SET_DEST (uloc);
6903 }
6904
6905 if (copied_p)
6906 {
6907 status = find_src_status (set, set_src);
6908
6909 set_src = find_src_set_src (set, set_src);
6910 }
6911
6912 if (REG_P (uloc))
6913 var_reg_delete_and_set (set, uloc, !copied_p,
6914 status, set_src);
6915 else if (MEM_P (uloc))
6916 var_mem_delete_and_set (set, uloc, !copied_p,
6917 status, set_src);
6918 }
6919 }
6920 else if (REG_P (uloc))
6921 var_regno_delete (set, REGNO (uloc));
6922
6923 val_store (set, val, vloc, insn);
6924
6925 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
6926 set->vars);
dedc1e6d
AO
6927 }
6928 break;
6929
014a1138
JZ
6930 case MO_SET:
6931 {
6932 rtx loc = VTI (bb)->mos[i].u.loc;
94a7682d 6933 rtx set_src = NULL;
62760ffd 6934
94a7682d 6935 if (GET_CODE (loc) == SET)
62760ffd 6936 {
94a7682d
RS
6937 set_src = SET_SRC (loc);
6938 loc = SET_DEST (loc);
62760ffd 6939 }
014a1138 6940
f8cfc6aa 6941 if (REG_P (loc))
b5b8b0ac 6942 var_reg_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
62760ffd 6943 set_src);
014a1138 6944 else
b5b8b0ac 6945 var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
62760ffd 6946 set_src);
ca787200 6947
b5b8b0ac
AO
6948 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
6949 set->vars);
ca787200
AO
6950 }
6951 break;
6952
6953 case MO_COPY:
6954 {
6955 rtx loc = VTI (bb)->mos[i].u.loc;
62760ffd 6956 enum var_init_status src_status;
94a7682d
RS
6957 rtx set_src = NULL;
6958
6959 if (GET_CODE (loc) == SET)
6960 {
6961 set_src = SET_SRC (loc);
6962 loc = SET_DEST (loc);
6963 }
62760ffd 6964
b5b8b0ac
AO
6965 src_status = find_src_status (set, set_src);
6966 set_src = find_src_set_src (set, set_src);
ca787200
AO
6967
6968 if (REG_P (loc))
b5b8b0ac 6969 var_reg_delete_and_set (set, loc, false, src_status, set_src);
ca787200 6970 else
b5b8b0ac 6971 var_mem_delete_and_set (set, loc, false, src_status, set_src);
014a1138 6972
b5b8b0ac
AO
6973 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
6974 set->vars);
014a1138
JZ
6975 }
6976 break;
6977
6978 case MO_USE_NO_VAR:
014a1138
JZ
6979 {
6980 rtx loc = VTI (bb)->mos[i].u.loc;
6981
f8cfc6aa 6982 if (REG_P (loc))
b5b8b0ac 6983 var_reg_delete (set, loc, false);
014a1138 6984 else
b5b8b0ac 6985 var_mem_delete (set, loc, false);
ca787200 6986
b5b8b0ac 6987 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
ca787200
AO
6988 }
6989 break;
014a1138 6990
ca787200
AO
6991 case MO_CLOBBER:
6992 {
6993 rtx loc = VTI (bb)->mos[i].u.loc;
6994
6995 if (REG_P (loc))
b5b8b0ac 6996 var_reg_delete (set, loc, true);
dedc1e6d 6997 else
b5b8b0ac 6998 var_mem_delete (set, loc, true);
ca787200 6999
b5b8b0ac
AO
7000 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7001 set->vars);
014a1138
JZ
7002 }
7003 break;
7004
7005 case MO_ADJUST:
b5b8b0ac 7006 set->stack_adjust += VTI (bb)->mos[i].u.adjust;
014a1138
JZ
7007 break;
7008 }
7009 }
014a1138
JZ
7010}
7011
7012/* Emit notes for the whole function. */
7013
7014static void
7015vt_emit_notes (void)
7016{
7017 basic_block bb;
b5b8b0ac 7018 dataflow_set cur;
014a1138 7019
fbc848cc 7020 gcc_assert (!htab_elements (changed_variables));
014a1138 7021
b5b8b0ac
AO
7022 /* Free memory occupied by the out hash tables, as they aren't used
7023 anymore. */
7024 FOR_EACH_BB (bb)
7025 dataflow_set_clear (&VTI (bb)->out);
7026
014a1138
JZ
7027 /* Enable emitting notes by functions (mainly by set_variable_part and
7028 delete_variable_part). */
7029 emit_notes = true;
7030
b5b8b0ac
AO
7031 if (MAY_HAVE_DEBUG_INSNS)
7032 changed_variables_stack = VEC_alloc (variable, heap, 40);
7033
7034 dataflow_set_init (&cur);
014a1138
JZ
7035
7036 FOR_EACH_BB (bb)
7037 {
7038 /* Emit the notes for changes of variable locations between two
7039 subsequent basic blocks. */
b5b8b0ac 7040 emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
014a1138
JZ
7041
7042 /* Emit the notes for the changes in the basic block itself. */
b5b8b0ac 7043 emit_notes_in_bb (bb, &cur);
014a1138 7044
b5b8b0ac
AO
7045 /* Free memory occupied by the in hash table, we won't need it
7046 again. */
7047 dataflow_set_clear (&VTI (bb)->in);
014a1138 7048 }
b5b8b0ac
AO
7049#ifdef ENABLE_CHECKING
7050 htab_traverse (shared_hash_htab (cur.vars),
7051 emit_notes_for_differences_1,
7052 shared_hash_htab (empty_shared_hash));
7053 if (MAY_HAVE_DEBUG_INSNS)
7054 gcc_assert (htab_elements (value_chains) == 0);
7055#endif
7056 dataflow_set_destroy (&cur);
7057
7058 if (MAY_HAVE_DEBUG_INSNS)
7059 VEC_free (variable, heap, changed_variables_stack);
7060
014a1138
JZ
7061 emit_notes = false;
7062}
7063
7064/* If there is a declaration and offset associated with register/memory RTL
7065 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
7066
7067static bool
7068vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
7069{
f8cfc6aa 7070 if (REG_P (rtl))
014a1138
JZ
7071 {
7072 if (REG_ATTRS (rtl))
7073 {
7074 *declp = REG_EXPR (rtl);
7075 *offsetp = REG_OFFSET (rtl);
7076 return true;
7077 }
7078 }
3c0cb5de 7079 else if (MEM_P (rtl))
014a1138
JZ
7080 {
7081 if (MEM_ATTRS (rtl))
7082 {
7083 *declp = MEM_EXPR (rtl);
8c6c36a3 7084 *offsetp = INT_MEM_OFFSET (rtl);
014a1138
JZ
7085 return true;
7086 }
7087 }
7088 return false;
7089}
7090
7091/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
7092
7093static void
7094vt_add_function_parameters (void)
7095{
7096 tree parm;
014a1138 7097
014a1138
JZ
7098 for (parm = DECL_ARGUMENTS (current_function_decl);
7099 parm; parm = TREE_CHAIN (parm))
7100 {
7101 rtx decl_rtl = DECL_RTL_IF_SET (parm);
7102 rtx incoming = DECL_INCOMING_RTL (parm);
7103 tree decl;
38ae7651 7104 enum machine_mode mode;
014a1138 7105 HOST_WIDE_INT offset;
81f2eadb 7106 dataflow_set *out;
b5b8b0ac 7107 decl_or_value dv;
014a1138
JZ
7108
7109 if (TREE_CODE (parm) != PARM_DECL)
7110 continue;
7111
7112 if (!DECL_NAME (parm))
7113 continue;
7114
7115 if (!decl_rtl || !incoming)
7116 continue;
7117
7118 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
7119 continue;
7120
7121 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
38ae7651 7122 {
08ab0acf
JJ
7123 if (REG_P (incoming) || MEM_P (incoming))
7124 {
7125 /* This means argument is passed by invisible reference. */
7126 offset = 0;
7127 decl = parm;
7128 incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
7129 }
7130 else
7131 {
7132 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
7133 continue;
7134 offset += byte_lowpart_offset (GET_MODE (incoming),
7135 GET_MODE (decl_rtl));
7136 }
38ae7651 7137 }
014a1138
JZ
7138
7139 if (!decl)
7140 continue;
7141
3d7e23f6
RH
7142 if (parm != decl)
7143 {
7144 /* Assume that DECL_RTL was a pseudo that got spilled to
7145 memory. The spill slot sharing code will force the
7146 memory to reference spill_slot_decl (%sfp), so we don't
7147 match above. That's ok, the pseudo must have referenced
7148 the entire parameter, so just reset OFFSET. */
7149 gcc_assert (decl == get_spill_slot_decl (false));
7150 offset = 0;
7151 }
014a1138 7152
38ae7651
RS
7153 if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
7154 continue;
7155
014a1138
JZ
7156 out = &VTI (ENTRY_BLOCK_PTR)->out;
7157
b5b8b0ac
AO
7158 dv = dv_from_decl (parm);
7159
7160 if (target_for_debug_bind (parm)
7161 /* We can't deal with these right now, because this kind of
7162 variable is single-part. ??? We could handle parallels
7163 that describe multiple locations for the same single
7164 value, but ATM we don't. */
7165 && GET_CODE (incoming) != PARALLEL)
7166 {
7167 cselib_val *val;
7168
7169 /* ??? We shouldn't ever hit this, but it may happen because
7170 arguments passed by invisible reference aren't dealt with
7171 above: incoming-rtl will have Pmode rather than the
7172 expected mode for the type. */
7173 if (offset)
7174 continue;
7175
7176 val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
7177
7178 /* ??? Float-typed values in memory are not handled by
7179 cselib. */
7180 if (val)
7181 {
7182 cselib_preserve_value (val);
7183 set_variable_part (out, val->val_rtx, dv, offset,
7184 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
7185 dv = dv_from_value (val->val_rtx);
7186 }
7187 }
7188
f8cfc6aa 7189 if (REG_P (incoming))
014a1138 7190 {
38ae7651 7191 incoming = var_lowpart (mode, incoming);
fbc848cc 7192 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
b5b8b0ac
AO
7193 attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
7194 incoming);
7195 set_variable_part (out, incoming, dv, offset,
7196 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
014a1138 7197 }
3c0cb5de 7198 else if (MEM_P (incoming))
38ae7651
RS
7199 {
7200 incoming = var_lowpart (mode, incoming);
b5b8b0ac
AO
7201 set_variable_part (out, incoming, dv, offset,
7202 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
38ae7651 7203 }
014a1138 7204 }
b5b8b0ac
AO
7205
7206 if (MAY_HAVE_DEBUG_INSNS)
7207 {
7208 cselib_preserve_only_values (true);
7209 cselib_reset_table_with_next_value (cselib_get_next_unknown_value ());
7210 }
7211
014a1138
JZ
7212}
7213
7214/* Allocate and initialize the data structures for variable tracking
7215 and parse the RTL to get the micro operations. */
7216
7217static void
7218vt_initialize (void)
7219{
7220 basic_block bb;
7221
7222 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
7223
b5b8b0ac
AO
7224 if (MAY_HAVE_DEBUG_INSNS)
7225 {
7226 cselib_init (true);
7227 scratch_regs = BITMAP_ALLOC (NULL);
7228 valvar_pool = create_alloc_pool ("small variable_def pool",
7229 sizeof (struct variable_def), 256);
7230 }
7231 else
7232 {
7233 scratch_regs = NULL;
7234 valvar_pool = NULL;
7235 }
7236
014a1138
JZ
7237 FOR_EACH_BB (bb)
7238 {
7239 rtx insn;
7b39f38b 7240 HOST_WIDE_INT pre, post = 0;
b5b8b0ac
AO
7241 int count;
7242 unsigned int next_value_before = cselib_get_next_unknown_value ();
7243 unsigned int next_value_after = next_value_before;
7244
7245 if (MAY_HAVE_DEBUG_INSNS)
7246 {
7247 cselib_record_sets_hook = count_with_sets;
7248 if (dump_file && (dump_flags & TDF_DETAILS))
7249 fprintf (dump_file, "first value: %i\n",
7250 cselib_get_next_unknown_value ());
7251 }
014a1138
JZ
7252
7253 /* Count the number of micro operations. */
7254 VTI (bb)->n_mos = 0;
7255 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
7256 insn = NEXT_INSN (insn))
7257 {
7258 if (INSN_P (insn))
7259 {
7260 if (!frame_pointer_needed)
7261 {
7262 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
7263 if (pre)
b5b8b0ac
AO
7264 {
7265 VTI (bb)->n_mos++;
7266 if (dump_file && (dump_flags & TDF_DETAILS))
7267 log_op_type (GEN_INT (pre), bb, insn,
7268 MO_ADJUST, dump_file);
7269 }
014a1138 7270 if (post)
b5b8b0ac
AO
7271 {
7272 VTI (bb)->n_mos++;
7273 if (dump_file && (dump_flags & TDF_DETAILS))
7274 log_op_type (GEN_INT (post), bb, insn,
7275 MO_ADJUST, dump_file);
7276 }
7277 }
7278 cselib_hook_called = false;
7279 if (MAY_HAVE_DEBUG_INSNS)
7280 {
7281 cselib_process_insn (insn);
7282 if (dump_file && (dump_flags & TDF_DETAILS))
7283 {
7284 print_rtl_single (dump_file, insn);
7285 dump_cselib_table (dump_file);
7286 }
014a1138 7287 }
b5b8b0ac
AO
7288 if (!cselib_hook_called)
7289 count_with_sets (insn, 0, 0);
4b4bf941 7290 if (CALL_P (insn))
b5b8b0ac
AO
7291 {
7292 VTI (bb)->n_mos++;
7293 if (dump_file && (dump_flags & TDF_DETAILS))
7294 log_op_type (PATTERN (insn), bb, insn,
7295 MO_CALL, dump_file);
7296 }
014a1138
JZ
7297 }
7298 }
7299
b5b8b0ac
AO
7300 count = VTI (bb)->n_mos;
7301
7302 if (MAY_HAVE_DEBUG_INSNS)
7303 {
7304 cselib_preserve_only_values (false);
7305 next_value_after = cselib_get_next_unknown_value ();
7306 cselib_reset_table_with_next_value (next_value_before);
7307 cselib_record_sets_hook = add_with_sets;
7308 if (dump_file && (dump_flags & TDF_DETAILS))
7309 fprintf (dump_file, "first value: %i\n",
7310 cselib_get_next_unknown_value ());
7311 }
7312
fb0840fc 7313 /* Add the micro-operations to the array. */
5ed6ace5 7314 VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos);
014a1138
JZ
7315 VTI (bb)->n_mos = 0;
7316 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
7317 insn = NEXT_INSN (insn))
7318 {
7319 if (INSN_P (insn))
7320 {
014a1138
JZ
7321 if (!frame_pointer_needed)
7322 {
7323 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
7324 if (pre)
7325 {
7326 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
7327
7328 mo->type = MO_ADJUST;
7329 mo->u.adjust = pre;
7330 mo->insn = insn;
014a1138 7331
b5b8b0ac
AO
7332 if (dump_file && (dump_flags & TDF_DETAILS))
7333 log_op_type (PATTERN (insn), bb, insn,
7334 MO_ADJUST, dump_file);
014a1138
JZ
7335 }
7336 }
7337
b5b8b0ac
AO
7338 cselib_hook_called = false;
7339 if (MAY_HAVE_DEBUG_INSNS)
014a1138 7340 {
b5b8b0ac
AO
7341 cselib_process_insn (insn);
7342 if (dump_file && (dump_flags & TDF_DETAILS))
014a1138 7343 {
b5b8b0ac
AO
7344 print_rtl_single (dump_file, insn);
7345 dump_cselib_table (dump_file);
014a1138
JZ
7346 }
7347 }
b5b8b0ac
AO
7348 if (!cselib_hook_called)
7349 add_with_sets (insn, 0, 0);
014a1138
JZ
7350
7351 if (!frame_pointer_needed && post)
7352 {
7353 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
7354
7355 mo->type = MO_ADJUST;
7356 mo->u.adjust = post;
7357 mo->insn = insn;
b5b8b0ac
AO
7358
7359 if (dump_file && (dump_flags & TDF_DETAILS))
7360 log_op_type (PATTERN (insn), bb, insn,
7361 MO_ADJUST, dump_file);
014a1138
JZ
7362 }
7363 }
7364 }
b5b8b0ac
AO
7365 gcc_assert (count == VTI (bb)->n_mos);
7366 if (MAY_HAVE_DEBUG_INSNS)
7367 {
7368 cselib_preserve_only_values (true);
7369 gcc_assert (next_value_after == cselib_get_next_unknown_value ());
7370 cselib_reset_table_with_next_value (next_value_after);
7371 cselib_record_sets_hook = NULL;
7372 }
014a1138
JZ
7373 }
7374
014a1138
JZ
7375 attrs_pool = create_alloc_pool ("attrs_def pool",
7376 sizeof (struct attrs_def), 1024);
7377 var_pool = create_alloc_pool ("variable_def pool",
b5b8b0ac
AO
7378 sizeof (struct variable_def)
7379 + (MAX_VAR_PARTS - 1)
7380 * sizeof (((variable)NULL)->var_part[0]), 64);
014a1138
JZ
7381 loc_chain_pool = create_alloc_pool ("location_chain_def pool",
7382 sizeof (struct location_chain_def),
7383 1024);
d24686d7
JJ
7384 shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
7385 sizeof (struct shared_hash_def), 256);
7386 empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
7387 empty_shared_hash->refcount = 1;
7388 empty_shared_hash->htab
7389 = htab_create (1, variable_htab_hash, variable_htab_eq,
7390 variable_htab_free);
014a1138 7391 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
d24686d7 7392 variable_htab_free);
b5b8b0ac
AO
7393 if (MAY_HAVE_DEBUG_INSNS)
7394 {
7395 value_chain_pool = create_alloc_pool ("value_chain_def pool",
7396 sizeof (struct value_chain_def),
7397 1024);
7398 value_chains = htab_create (32, value_chain_htab_hash,
7399 value_chain_htab_eq, NULL);
7400 }
d24686d7
JJ
7401
7402 /* Init the IN and OUT sets. */
7403 FOR_ALL_BB (bb)
7404 {
7405 VTI (bb)->visited = false;
b5b8b0ac 7406 VTI (bb)->flooded = false;
d24686d7
JJ
7407 dataflow_set_init (&VTI (bb)->in);
7408 dataflow_set_init (&VTI (bb)->out);
b5b8b0ac 7409 VTI (bb)->permp = NULL;
d24686d7
JJ
7410 }
7411
b5b8b0ac 7412 VTI (ENTRY_BLOCK_PTR)->flooded = true;
014a1138 7413 vt_add_function_parameters ();
014a1138
JZ
7414}
7415
b5b8b0ac
AO
7416/* Get rid of all debug insns from the insn stream. */
7417
7418static void
7419delete_debug_insns (void)
7420{
7421 basic_block bb;
7422 rtx insn, next;
7423
7424 if (!MAY_HAVE_DEBUG_INSNS)
7425 return;
7426
7427 FOR_EACH_BB (bb)
7428 {
7429 FOR_BB_INSNS_SAFE (bb, insn, next)
7430 if (DEBUG_INSN_P (insn))
7431 delete_insn (insn);
7432 }
7433}
7434
7435/* Run a fast, BB-local only version of var tracking, to take care of
7436 information that we don't do global analysis on, such that not all
7437 information is lost. If SKIPPED holds, we're skipping the global
7438 pass entirely, so we should try to use information it would have
7439 handled as well.. */
7440
7441static void
7442vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
7443{
7444 /* ??? Just skip it all for now. */
7445 delete_debug_insns ();
7446}
7447
014a1138
JZ
7448/* Free the data structures needed for variable tracking. */
7449
7450static void
7451vt_finalize (void)
7452{
7453 basic_block bb;
7454
7455 FOR_EACH_BB (bb)
7456 {
7457 free (VTI (bb)->mos);
7458 }
7459
7460 FOR_ALL_BB (bb)
7461 {
7462 dataflow_set_destroy (&VTI (bb)->in);
7463 dataflow_set_destroy (&VTI (bb)->out);
b5b8b0ac
AO
7464 if (VTI (bb)->permp)
7465 {
7466 dataflow_set_destroy (VTI (bb)->permp);
7467 XDELETE (VTI (bb)->permp);
7468 }
014a1138
JZ
7469 }
7470 free_aux_for_blocks ();
d24686d7
JJ
7471 htab_delete (empty_shared_hash->htab);
7472 htab_delete (changed_variables);
014a1138
JZ
7473 free_alloc_pool (attrs_pool);
7474 free_alloc_pool (var_pool);
7475 free_alloc_pool (loc_chain_pool);
d24686d7 7476 free_alloc_pool (shared_hash_pool);
b5b8b0ac
AO
7477
7478 if (MAY_HAVE_DEBUG_INSNS)
7479 {
7480 htab_delete (value_chains);
7481 free_alloc_pool (value_chain_pool);
7482 free_alloc_pool (valvar_pool);
7483 cselib_finish ();
7484 BITMAP_FREE (scratch_regs);
7485 scratch_regs = NULL;
7486 }
7487
7eb3f1f7 7488 if (vui_vec)
b5b8b0ac 7489 XDELETEVEC (vui_vec);
7eb3f1f7
JJ
7490 vui_vec = NULL;
7491 vui_allocated = 0;
014a1138
JZ
7492}
7493
7494/* The entry point to variable tracking pass. */
7495
c2924966 7496unsigned int
014a1138
JZ
7497variable_tracking_main (void)
7498{
b5b8b0ac
AO
7499 if (flag_var_tracking_assignments < 0)
7500 {
7501 delete_debug_insns ();
7502 return 0;
7503 }
7504
014a1138 7505 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
b5b8b0ac
AO
7506 {
7507 vt_debug_insns_local (true);
7508 return 0;
7509 }
014a1138
JZ
7510
7511 mark_dfs_back_edges ();
7512 vt_initialize ();
7513 if (!frame_pointer_needed)
7514 {
7515 if (!vt_stack_adjustments ())
7516 {
7517 vt_finalize ();
b5b8b0ac 7518 vt_debug_insns_local (true);
c2924966 7519 return 0;
014a1138
JZ
7520 }
7521 }
7522
7523 vt_find_locations ();
014a1138 7524
5b4fdb20 7525 if (dump_file && (dump_flags & TDF_DETAILS))
014a1138
JZ
7526 {
7527 dump_dataflow_sets ();
5b4fdb20 7528 dump_flow_info (dump_file, dump_flags);
014a1138
JZ
7529 }
7530
b5b8b0ac
AO
7531 vt_emit_notes ();
7532
014a1138 7533 vt_finalize ();
b5b8b0ac 7534 vt_debug_insns_local (false);
c2924966 7535 return 0;
014a1138 7536}
ef330312
PB
7537\f
7538static bool
7539gate_handle_var_tracking (void)
7540{
7541 return (flag_var_tracking);
7542}
7543
7544
7545
8ddbbcae 7546struct rtl_opt_pass pass_variable_tracking =
ef330312 7547{
8ddbbcae
JH
7548 {
7549 RTL_PASS,
ef330312
PB
7550 "vartrack", /* name */
7551 gate_handle_var_tracking, /* gate */
7552 variable_tracking_main, /* execute */
7553 NULL, /* sub */
7554 NULL, /* next */
7555 0, /* static_pass_number */
7556 TV_VAR_TRACKING, /* tv_id */
7557 0, /* properties_required */
7558 0, /* properties_provided */
7559 0, /* properties_destroyed */
7560 0, /* todo_flags_start */
8ddbbcae
JH
7561 TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */
7562 }
ef330312 7563};