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