(Synchronize with addition made to binutils sources):
[gcc.git] / gcc / var-tracking.c
1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
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
110 /* Type of micro operation. */
111 enum micro_operation_type
112 {
113 MO_USE, /* Use location (REG or MEM). */
114 MO_USE_NO_VAR,/* Use location which is not associated with a variable
115 or the variable is not trackable. */
116 MO_SET, /* Set location. */
117 MO_COPY, /* Copy the same portion of a variable from one
118 location to another. */
119 MO_CLOBBER, /* Clobber location. */
120 MO_CALL, /* Call insn. */
121 MO_ADJUST /* Adjust stack pointer. */
122 };
123
124 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
125 enum emit_note_where
126 {
127 EMIT_NOTE_BEFORE_INSN,
128 EMIT_NOTE_AFTER_INSN
129 };
130
131 /* Structure holding information about micro operation. */
132 typedef struct micro_operation_def
133 {
134 /* Type of micro operation. */
135 enum micro_operation_type type;
136
137 union {
138 /* Location. For MO_SET and MO_COPY, this is the SET that performs
139 the assignment, if known, otherwise it is the target of the
140 assignment. */
141 rtx loc;
142
143 /* Stack adjustment. */
144 HOST_WIDE_INT adjust;
145 } u;
146
147 /* The instruction which the micro operation is in, for MO_USE,
148 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
149 instruction or note in the original flow (before any var-tracking
150 notes are inserted, to simplify emission of notes), for MO_SET
151 and MO_CLOBBER. */
152 rtx insn;
153 } micro_operation;
154
155 /* Structure for passing some other parameters to function
156 emit_note_insn_var_location. */
157 typedef struct emit_note_data_def
158 {
159 /* The instruction which the note will be emitted before/after. */
160 rtx insn;
161
162 /* Where the note will be emitted (before/after insn)? */
163 enum emit_note_where where;
164 } emit_note_data;
165
166 /* Description of location of a part of a variable. The content of a physical
167 register is described by a chain of these structures.
168 The chains are pretty short (usually 1 or 2 elements) and thus
169 chain is the best data structure. */
170 typedef struct attrs_def
171 {
172 /* Pointer to next member of the list. */
173 struct attrs_def *next;
174
175 /* The rtx of register. */
176 rtx loc;
177
178 /* The declaration corresponding to LOC. */
179 tree decl;
180
181 /* Offset from start of DECL. */
182 HOST_WIDE_INT offset;
183 } *attrs;
184
185 /* Structure holding the IN or OUT set for a basic block. */
186 typedef struct dataflow_set_def
187 {
188 /* Adjustment of stack offset. */
189 HOST_WIDE_INT stack_adjust;
190
191 /* Attributes for registers (lists of attrs). */
192 attrs regs[FIRST_PSEUDO_REGISTER];
193
194 /* Variable locations. */
195 htab_t vars;
196 } dataflow_set;
197
198 /* The structure (one for each basic block) containing the information
199 needed for variable tracking. */
200 typedef struct variable_tracking_info_def
201 {
202 /* Number of micro operations stored in the MOS array. */
203 int n_mos;
204
205 /* The array of micro operations. */
206 micro_operation *mos;
207
208 /* The IN and OUT set for dataflow analysis. */
209 dataflow_set in;
210 dataflow_set out;
211
212 /* Has the block been visited in DFS? */
213 bool visited;
214 } *variable_tracking_info;
215
216 /* Structure for chaining the locations. */
217 typedef struct location_chain_def
218 {
219 /* Next element in the chain. */
220 struct location_chain_def *next;
221
222 /* The location (REG or MEM). */
223 rtx loc;
224
225 /* The "value" stored in this location. */
226 rtx set_src;
227
228 /* Initialized? */
229 enum var_init_status init;
230 } *location_chain;
231
232 /* Structure describing one part of variable. */
233 typedef struct variable_part_def
234 {
235 /* Chain of locations of the part. */
236 location_chain loc_chain;
237
238 /* Location which was last emitted to location list. */
239 rtx cur_loc;
240
241 /* The offset in the variable. */
242 HOST_WIDE_INT offset;
243 } variable_part;
244
245 /* Maximum number of location parts. */
246 #define MAX_VAR_PARTS 16
247
248 /* Structure describing where the variable is located. */
249 typedef struct variable_def
250 {
251 /* The declaration of the variable. */
252 tree decl;
253
254 /* Reference count. */
255 int refcount;
256
257 /* Number of variable parts. */
258 int n_var_parts;
259
260 /* The variable parts. */
261 variable_part var_part[MAX_VAR_PARTS];
262 } *variable;
263 typedef const struct variable_def *const_variable;
264
265 /* Hash function for DECL for VARIABLE_HTAB. */
266 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
267
268 /* Pointer to the BB's information specific to variable tracking pass. */
269 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
270
271 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
272 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
273
274 /* Alloc pool for struct attrs_def. */
275 static alloc_pool attrs_pool;
276
277 /* Alloc pool for struct variable_def. */
278 static alloc_pool var_pool;
279
280 /* Alloc pool for struct location_chain_def. */
281 static alloc_pool loc_chain_pool;
282
283 /* Changed variables, notes will be emitted for them. */
284 static htab_t changed_variables;
285
286 /* Shall notes be emitted? */
287 static bool emit_notes;
288
289 /* Local function prototypes. */
290 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
291 HOST_WIDE_INT *);
292 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
293 HOST_WIDE_INT *);
294 static void bb_stack_adjust_offset (basic_block);
295 static bool vt_stack_adjustments (void);
296 static rtx adjust_stack_reference (rtx, HOST_WIDE_INT);
297 static hashval_t variable_htab_hash (const void *);
298 static int variable_htab_eq (const void *, const void *);
299 static void variable_htab_free (void *);
300
301 static void init_attrs_list_set (attrs *);
302 static void attrs_list_clear (attrs *);
303 static attrs attrs_list_member (attrs, tree, HOST_WIDE_INT);
304 static void attrs_list_insert (attrs *, tree, HOST_WIDE_INT, rtx);
305 static void attrs_list_copy (attrs *, attrs);
306 static void attrs_list_union (attrs *, attrs);
307
308 static void vars_clear (htab_t);
309 static variable unshare_variable (dataflow_set *set, variable var,
310 enum var_init_status);
311 static int vars_copy_1 (void **, void *);
312 static void vars_copy (htab_t, htab_t);
313 static tree var_debug_decl (tree);
314 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
315 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
316 enum var_init_status, rtx);
317 static void var_reg_delete (dataflow_set *, rtx, bool);
318 static void var_regno_delete (dataflow_set *, int);
319 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
320 static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
321 enum var_init_status, rtx);
322 static void var_mem_delete (dataflow_set *, rtx, bool);
323
324 static void dataflow_set_init (dataflow_set *, int);
325 static void dataflow_set_clear (dataflow_set *);
326 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
327 static int variable_union_info_cmp_pos (const void *, const void *);
328 static int variable_union (void **, void *);
329 static void dataflow_set_union (dataflow_set *, dataflow_set *);
330 static bool variable_part_different_p (variable_part *, variable_part *);
331 static bool variable_different_p (variable, variable, bool);
332 static int dataflow_set_different_1 (void **, void *);
333 static int dataflow_set_different_2 (void **, void *);
334 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
335 static void dataflow_set_destroy (dataflow_set *);
336
337 static bool contains_symbol_ref (rtx);
338 static bool track_expr_p (tree);
339 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
340 static int count_uses (rtx *, void *);
341 static void count_uses_1 (rtx *, void *);
342 static void count_stores (rtx, const_rtx, void *);
343 static int add_uses (rtx *, void *);
344 static void add_uses_1 (rtx *, void *);
345 static void add_stores (rtx, const_rtx, void *);
346 static bool compute_bb_dataflow (basic_block);
347 static void vt_find_locations (void);
348
349 static void dump_attrs_list (attrs);
350 static int dump_variable (void **, void *);
351 static void dump_vars (htab_t);
352 static void dump_dataflow_set (dataflow_set *);
353 static void dump_dataflow_sets (void);
354
355 static void variable_was_changed (variable, htab_t);
356 static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
357 enum var_init_status, rtx);
358 static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
359 rtx);
360 static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
361 static int emit_note_insn_var_location (void **, void *);
362 static void emit_notes_for_changes (rtx, enum emit_note_where);
363 static int emit_notes_for_differences_1 (void **, void *);
364 static int emit_notes_for_differences_2 (void **, void *);
365 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
366 static void emit_notes_in_bb (basic_block);
367 static void vt_emit_notes (void);
368
369 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
370 static void vt_add_function_parameters (void);
371 static void vt_initialize (void);
372 static void vt_finalize (void);
373
374 /* Given a SET, calculate the amount of stack adjustment it contains
375 PRE- and POST-modifying stack pointer.
376 This function is similar to stack_adjust_offset. */
377
378 static void
379 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
380 HOST_WIDE_INT *post)
381 {
382 rtx src = SET_SRC (pattern);
383 rtx dest = SET_DEST (pattern);
384 enum rtx_code code;
385
386 if (dest == stack_pointer_rtx)
387 {
388 /* (set (reg sp) (plus (reg sp) (const_int))) */
389 code = GET_CODE (src);
390 if (! (code == PLUS || code == MINUS)
391 || XEXP (src, 0) != stack_pointer_rtx
392 || GET_CODE (XEXP (src, 1)) != CONST_INT)
393 return;
394
395 if (code == MINUS)
396 *post += INTVAL (XEXP (src, 1));
397 else
398 *post -= INTVAL (XEXP (src, 1));
399 }
400 else if (MEM_P (dest))
401 {
402 /* (set (mem (pre_dec (reg sp))) (foo)) */
403 src = XEXP (dest, 0);
404 code = GET_CODE (src);
405
406 switch (code)
407 {
408 case PRE_MODIFY:
409 case POST_MODIFY:
410 if (XEXP (src, 0) == stack_pointer_rtx)
411 {
412 rtx val = XEXP (XEXP (src, 1), 1);
413 /* We handle only adjustments by constant amount. */
414 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
415 GET_CODE (val) == CONST_INT);
416
417 if (code == PRE_MODIFY)
418 *pre -= INTVAL (val);
419 else
420 *post -= INTVAL (val);
421 break;
422 }
423 return;
424
425 case PRE_DEC:
426 if (XEXP (src, 0) == stack_pointer_rtx)
427 {
428 *pre += GET_MODE_SIZE (GET_MODE (dest));
429 break;
430 }
431 return;
432
433 case POST_DEC:
434 if (XEXP (src, 0) == stack_pointer_rtx)
435 {
436 *post += GET_MODE_SIZE (GET_MODE (dest));
437 break;
438 }
439 return;
440
441 case PRE_INC:
442 if (XEXP (src, 0) == stack_pointer_rtx)
443 {
444 *pre -= GET_MODE_SIZE (GET_MODE (dest));
445 break;
446 }
447 return;
448
449 case POST_INC:
450 if (XEXP (src, 0) == stack_pointer_rtx)
451 {
452 *post -= GET_MODE_SIZE (GET_MODE (dest));
453 break;
454 }
455 return;
456
457 default:
458 return;
459 }
460 }
461 }
462
463 /* Given an INSN, calculate the amount of stack adjustment it contains
464 PRE- and POST-modifying stack pointer. */
465
466 static void
467 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
468 HOST_WIDE_INT *post)
469 {
470 rtx pattern;
471
472 *pre = 0;
473 *post = 0;
474
475 pattern = PATTERN (insn);
476 if (RTX_FRAME_RELATED_P (insn))
477 {
478 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
479 if (expr)
480 pattern = XEXP (expr, 0);
481 }
482
483 if (GET_CODE (pattern) == SET)
484 stack_adjust_offset_pre_post (pattern, pre, post);
485 else if (GET_CODE (pattern) == PARALLEL
486 || GET_CODE (pattern) == SEQUENCE)
487 {
488 int i;
489
490 /* There may be stack adjustments inside compound insns. Search
491 for them. */
492 for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
493 if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
494 stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
495 }
496 }
497
498 /* Compute stack adjustment in basic block BB. */
499
500 static void
501 bb_stack_adjust_offset (basic_block bb)
502 {
503 HOST_WIDE_INT offset;
504 int i;
505
506 offset = VTI (bb)->in.stack_adjust;
507 for (i = 0; i < VTI (bb)->n_mos; i++)
508 {
509 if (VTI (bb)->mos[i].type == MO_ADJUST)
510 offset += VTI (bb)->mos[i].u.adjust;
511 else if (VTI (bb)->mos[i].type != MO_CALL)
512 {
513 if (MEM_P (VTI (bb)->mos[i].u.loc))
514 {
515 VTI (bb)->mos[i].u.loc
516 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
517 }
518 }
519 }
520 VTI (bb)->out.stack_adjust = offset;
521 }
522
523 /* Compute stack adjustments for all blocks by traversing DFS tree.
524 Return true when the adjustments on all incoming edges are consistent.
525 Heavily borrowed from pre_and_rev_post_order_compute. */
526
527 static bool
528 vt_stack_adjustments (void)
529 {
530 edge_iterator *stack;
531 int sp;
532
533 /* Initialize entry block. */
534 VTI (ENTRY_BLOCK_PTR)->visited = true;
535 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
536
537 /* Allocate stack for back-tracking up CFG. */
538 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
539 sp = 0;
540
541 /* Push the first edge on to the stack. */
542 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
543
544 while (sp)
545 {
546 edge_iterator ei;
547 basic_block src;
548 basic_block dest;
549
550 /* Look at the edge on the top of the stack. */
551 ei = stack[sp - 1];
552 src = ei_edge (ei)->src;
553 dest = ei_edge (ei)->dest;
554
555 /* Check if the edge destination has been visited yet. */
556 if (!VTI (dest)->visited)
557 {
558 VTI (dest)->visited = true;
559 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
560 bb_stack_adjust_offset (dest);
561
562 if (EDGE_COUNT (dest->succs) > 0)
563 /* Since the DEST node has been visited for the first
564 time, check its successors. */
565 stack[sp++] = ei_start (dest->succs);
566 }
567 else
568 {
569 /* Check whether the adjustments on the edges are the same. */
570 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
571 {
572 free (stack);
573 return false;
574 }
575
576 if (! ei_one_before_end_p (ei))
577 /* Go to the next edge. */
578 ei_next (&stack[sp - 1]);
579 else
580 /* Return to previous level if there are no more edges. */
581 sp--;
582 }
583 }
584
585 free (stack);
586 return true;
587 }
588
589 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
590 to the argument pointer. Return the new rtx. */
591
592 static rtx
593 adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
594 {
595 rtx addr, cfa, tmp;
596
597 #ifdef FRAME_POINTER_CFA_OFFSET
598 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
599 cfa = plus_constant (frame_pointer_rtx, adjustment);
600 #else
601 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
602 cfa = plus_constant (arg_pointer_rtx, adjustment);
603 #endif
604
605 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
606 tmp = simplify_rtx (addr);
607 if (tmp)
608 addr = tmp;
609
610 return replace_equiv_address_nv (mem, addr);
611 }
612
613 /* The hash function for variable_htab, computes the hash value
614 from the declaration of variable X. */
615
616 static hashval_t
617 variable_htab_hash (const void *x)
618 {
619 const_variable const v = (const_variable) x;
620
621 return (VARIABLE_HASH_VAL (v->decl));
622 }
623
624 /* Compare the declaration of variable X with declaration Y. */
625
626 static int
627 variable_htab_eq (const void *x, const void *y)
628 {
629 const_variable const v = (const_variable) x;
630 const_tree const decl = (const_tree) y;
631
632 return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
633 }
634
635 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
636
637 static void
638 variable_htab_free (void *elem)
639 {
640 int i;
641 variable var = (variable) elem;
642 location_chain node, next;
643
644 gcc_assert (var->refcount > 0);
645
646 var->refcount--;
647 if (var->refcount > 0)
648 return;
649
650 for (i = 0; i < var->n_var_parts; i++)
651 {
652 for (node = var->var_part[i].loc_chain; node; node = next)
653 {
654 next = node->next;
655 pool_free (loc_chain_pool, node);
656 }
657 var->var_part[i].loc_chain = NULL;
658 }
659 pool_free (var_pool, var);
660 }
661
662 /* Initialize the set (array) SET of attrs to empty lists. */
663
664 static void
665 init_attrs_list_set (attrs *set)
666 {
667 int i;
668
669 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
670 set[i] = NULL;
671 }
672
673 /* Make the list *LISTP empty. */
674
675 static void
676 attrs_list_clear (attrs *listp)
677 {
678 attrs list, next;
679
680 for (list = *listp; list; list = next)
681 {
682 next = list->next;
683 pool_free (attrs_pool, list);
684 }
685 *listp = NULL;
686 }
687
688 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
689
690 static attrs
691 attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset)
692 {
693 for (; list; list = list->next)
694 if (list->decl == decl && list->offset == offset)
695 return list;
696 return NULL;
697 }
698
699 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
700
701 static void
702 attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc)
703 {
704 attrs list;
705
706 list = (attrs) pool_alloc (attrs_pool);
707 list->loc = loc;
708 list->decl = decl;
709 list->offset = offset;
710 list->next = *listp;
711 *listp = list;
712 }
713
714 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
715
716 static void
717 attrs_list_copy (attrs *dstp, attrs src)
718 {
719 attrs n;
720
721 attrs_list_clear (dstp);
722 for (; src; src = src->next)
723 {
724 n = (attrs) pool_alloc (attrs_pool);
725 n->loc = src->loc;
726 n->decl = src->decl;
727 n->offset = src->offset;
728 n->next = *dstp;
729 *dstp = n;
730 }
731 }
732
733 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
734
735 static void
736 attrs_list_union (attrs *dstp, attrs src)
737 {
738 for (; src; src = src->next)
739 {
740 if (!attrs_list_member (*dstp, src->decl, src->offset))
741 attrs_list_insert (dstp, src->decl, src->offset, src->loc);
742 }
743 }
744
745 /* Delete all variables from hash table VARS. */
746
747 static void
748 vars_clear (htab_t vars)
749 {
750 htab_empty (vars);
751 }
752
753 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
754
755 static variable
756 unshare_variable (dataflow_set *set, variable var,
757 enum var_init_status initialized)
758 {
759 void **slot;
760 variable new_var;
761 int i;
762
763 new_var = (variable) pool_alloc (var_pool);
764 new_var->decl = var->decl;
765 new_var->refcount = 1;
766 var->refcount--;
767 new_var->n_var_parts = var->n_var_parts;
768
769 for (i = 0; i < var->n_var_parts; i++)
770 {
771 location_chain node;
772 location_chain *nextp;
773
774 new_var->var_part[i].offset = var->var_part[i].offset;
775 nextp = &new_var->var_part[i].loc_chain;
776 for (node = var->var_part[i].loc_chain; node; node = node->next)
777 {
778 location_chain new_lc;
779
780 new_lc = (location_chain) pool_alloc (loc_chain_pool);
781 new_lc->next = NULL;
782 if (node->init > initialized)
783 new_lc->init = node->init;
784 else
785 new_lc->init = initialized;
786 if (node->set_src && !(MEM_P (node->set_src)))
787 new_lc->set_src = node->set_src;
788 else
789 new_lc->set_src = NULL;
790 new_lc->loc = node->loc;
791
792 *nextp = new_lc;
793 nextp = &new_lc->next;
794 }
795
796 /* We are at the basic block boundary when copying variable description
797 so set the CUR_LOC to be the first element of the chain. */
798 if (new_var->var_part[i].loc_chain)
799 new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
800 else
801 new_var->var_part[i].cur_loc = NULL;
802 }
803
804 slot = htab_find_slot_with_hash (set->vars, new_var->decl,
805 VARIABLE_HASH_VAL (new_var->decl),
806 INSERT);
807 *slot = new_var;
808 return new_var;
809 }
810
811 /* Add a variable from *SLOT to hash table DATA and increase its reference
812 count. */
813
814 static int
815 vars_copy_1 (void **slot, void *data)
816 {
817 htab_t dst = (htab_t) data;
818 variable src, *dstp;
819
820 src = *(variable *) slot;
821 src->refcount++;
822
823 dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
824 VARIABLE_HASH_VAL (src->decl),
825 INSERT);
826 *dstp = src;
827
828 /* Continue traversing the hash table. */
829 return 1;
830 }
831
832 /* Copy all variables from hash table SRC to hash table DST. */
833
834 static void
835 vars_copy (htab_t dst, htab_t src)
836 {
837 vars_clear (dst);
838 htab_traverse (src, vars_copy_1, dst);
839 }
840
841 /* Map a decl to its main debug decl. */
842
843 static inline tree
844 var_debug_decl (tree decl)
845 {
846 if (decl && DECL_P (decl)
847 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
848 && DECL_P (DECL_DEBUG_EXPR (decl)))
849 decl = DECL_DEBUG_EXPR (decl);
850
851 return decl;
852 }
853
854 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
855
856 static void
857 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
858 rtx set_src)
859 {
860 tree decl = REG_EXPR (loc);
861 HOST_WIDE_INT offset = REG_OFFSET (loc);
862 attrs node;
863
864 decl = var_debug_decl (decl);
865
866 for (node = set->regs[REGNO (loc)]; node; node = node->next)
867 if (node->decl == decl && node->offset == offset)
868 break;
869 if (!node)
870 attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
871 set_variable_part (set, loc, decl, offset, initialized, set_src);
872 }
873
874 static enum var_init_status
875 get_init_value (dataflow_set *set, rtx loc, tree decl)
876 {
877 void **slot;
878 variable var;
879 int i;
880 enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
881
882 if (! flag_var_tracking_uninit)
883 return VAR_INIT_STATUS_INITIALIZED;
884
885 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
886 NO_INSERT);
887 if (slot)
888 {
889 var = * (variable *) slot;
890 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
891 {
892 location_chain nextp;
893 for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
894 if (rtx_equal_p (nextp->loc, loc))
895 {
896 ret_val = nextp->init;
897 break;
898 }
899 }
900 }
901
902 return ret_val;
903 }
904
905 /* Delete current content of register LOC in dataflow set SET and set
906 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
907 MODIFY is true, any other live copies of the same variable part are
908 also deleted from the dataflow set, otherwise the variable part is
909 assumed to be copied from another location holding the same
910 part. */
911
912 static void
913 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
914 enum var_init_status initialized, rtx set_src)
915 {
916 tree decl = REG_EXPR (loc);
917 HOST_WIDE_INT offset = REG_OFFSET (loc);
918 attrs node, next;
919 attrs *nextp;
920
921 decl = var_debug_decl (decl);
922
923 if (initialized == VAR_INIT_STATUS_UNKNOWN)
924 initialized = get_init_value (set, loc, decl);
925
926 nextp = &set->regs[REGNO (loc)];
927 for (node = *nextp; node; node = next)
928 {
929 next = node->next;
930 if (node->decl != decl || node->offset != offset)
931 {
932 delete_variable_part (set, node->loc, node->decl, node->offset);
933 pool_free (attrs_pool, node);
934 *nextp = next;
935 }
936 else
937 {
938 node->loc = loc;
939 nextp = &node->next;
940 }
941 }
942 if (modify)
943 clobber_variable_part (set, loc, decl, offset, set_src);
944 var_reg_set (set, loc, initialized, set_src);
945 }
946
947 /* Delete current content of register LOC in dataflow set SET. If
948 CLOBBER is true, also delete any other live copies of the same
949 variable part. */
950
951 static void
952 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
953 {
954 attrs *reg = &set->regs[REGNO (loc)];
955 attrs node, next;
956
957 if (clobber)
958 {
959 tree decl = REG_EXPR (loc);
960 HOST_WIDE_INT offset = REG_OFFSET (loc);
961
962 decl = var_debug_decl (decl);
963
964 clobber_variable_part (set, NULL, decl, offset, NULL);
965 }
966
967 for (node = *reg; node; node = next)
968 {
969 next = node->next;
970 delete_variable_part (set, node->loc, node->decl, node->offset);
971 pool_free (attrs_pool, node);
972 }
973 *reg = NULL;
974 }
975
976 /* Delete content of register with number REGNO in dataflow set SET. */
977
978 static void
979 var_regno_delete (dataflow_set *set, int regno)
980 {
981 attrs *reg = &set->regs[regno];
982 attrs node, next;
983
984 for (node = *reg; node; node = next)
985 {
986 next = node->next;
987 delete_variable_part (set, node->loc, node->decl, node->offset);
988 pool_free (attrs_pool, node);
989 }
990 *reg = NULL;
991 }
992
993 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
994 SET to LOC.
995 Adjust the address first if it is stack pointer based. */
996
997 static void
998 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
999 rtx set_src)
1000 {
1001 tree decl = MEM_EXPR (loc);
1002 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1003
1004 decl = var_debug_decl (decl);
1005
1006 set_variable_part (set, loc, decl, offset, initialized, set_src);
1007 }
1008
1009 /* Delete and set the location part of variable MEM_EXPR (LOC) in
1010 dataflow set SET to LOC. If MODIFY is true, any other live copies
1011 of the same variable part are also deleted from the dataflow set,
1012 otherwise the variable part is assumed to be copied from another
1013 location holding the same part.
1014 Adjust the address first if it is stack pointer based. */
1015
1016 static void
1017 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1018 enum var_init_status initialized, rtx set_src)
1019 {
1020 tree decl = MEM_EXPR (loc);
1021 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1022
1023 decl = var_debug_decl (decl);
1024
1025 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1026 initialized = get_init_value (set, loc, decl);
1027
1028 if (modify)
1029 clobber_variable_part (set, NULL, decl, offset, set_src);
1030 var_mem_set (set, loc, initialized, set_src);
1031 }
1032
1033 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
1034 true, also delete any other live copies of the same variable part.
1035 Adjust the address first if it is stack pointer based. */
1036
1037 static void
1038 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1039 {
1040 tree decl = MEM_EXPR (loc);
1041 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1042
1043 decl = var_debug_decl (decl);
1044 if (clobber)
1045 clobber_variable_part (set, NULL, decl, offset, NULL);
1046 delete_variable_part (set, loc, decl, offset);
1047 }
1048
1049 /* Initialize dataflow set SET to be empty.
1050 VARS_SIZE is the initial size of hash table VARS. */
1051
1052 static void
1053 dataflow_set_init (dataflow_set *set, int vars_size)
1054 {
1055 init_attrs_list_set (set->regs);
1056 set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq,
1057 variable_htab_free);
1058 set->stack_adjust = 0;
1059 }
1060
1061 /* Delete the contents of dataflow set SET. */
1062
1063 static void
1064 dataflow_set_clear (dataflow_set *set)
1065 {
1066 int i;
1067
1068 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1069 attrs_list_clear (&set->regs[i]);
1070
1071 vars_clear (set->vars);
1072 }
1073
1074 /* Copy the contents of dataflow set SRC to DST. */
1075
1076 static void
1077 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1078 {
1079 int i;
1080
1081 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1082 attrs_list_copy (&dst->regs[i], src->regs[i]);
1083
1084 vars_copy (dst->vars, src->vars);
1085 dst->stack_adjust = src->stack_adjust;
1086 }
1087
1088 /* Information for merging lists of locations for a given offset of variable.
1089 */
1090 struct variable_union_info
1091 {
1092 /* Node of the location chain. */
1093 location_chain lc;
1094
1095 /* The sum of positions in the input chains. */
1096 int pos;
1097
1098 /* The position in the chains of SRC and DST dataflow sets. */
1099 int pos_src;
1100 int pos_dst;
1101 };
1102
1103 /* Compare function for qsort, order the structures by POS element. */
1104
1105 static int
1106 variable_union_info_cmp_pos (const void *n1, const void *n2)
1107 {
1108 const struct variable_union_info *const i1 =
1109 (const struct variable_union_info *) n1;
1110 const struct variable_union_info *const i2 =
1111 ( const struct variable_union_info *) n2;
1112
1113 if (i1->pos != i2->pos)
1114 return i1->pos - i2->pos;
1115
1116 return (i1->pos_dst - i2->pos_dst);
1117 }
1118
1119 /* Compute union of location parts of variable *SLOT and the same variable
1120 from hash table DATA. Compute "sorted" union of the location chains
1121 for common offsets, i.e. the locations of a variable part are sorted by
1122 a priority where the priority is the sum of the positions in the 2 chains
1123 (if a location is only in one list the position in the second list is
1124 defined to be larger than the length of the chains).
1125 When we are updating the location parts the newest location is in the
1126 beginning of the chain, so when we do the described "sorted" union
1127 we keep the newest locations in the beginning. */
1128
1129 static int
1130 variable_union (void **slot, void *data)
1131 {
1132 variable src, dst, *dstp;
1133 dataflow_set *set = (dataflow_set *) data;
1134 int i, j, k;
1135
1136 src = *(variable *) slot;
1137 dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl,
1138 VARIABLE_HASH_VAL (src->decl),
1139 INSERT);
1140 if (!*dstp)
1141 {
1142 src->refcount++;
1143
1144 /* If CUR_LOC of some variable part is not the first element of
1145 the location chain we are going to change it so we have to make
1146 a copy of the variable. */
1147 for (k = 0; k < src->n_var_parts; k++)
1148 {
1149 gcc_assert (!src->var_part[k].loc_chain
1150 == !src->var_part[k].cur_loc);
1151 if (src->var_part[k].loc_chain)
1152 {
1153 gcc_assert (src->var_part[k].cur_loc);
1154 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
1155 break;
1156 }
1157 }
1158 if (k < src->n_var_parts)
1159 {
1160 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1161
1162 if (! flag_var_tracking_uninit)
1163 status = VAR_INIT_STATUS_INITIALIZED;
1164
1165 unshare_variable (set, src, status);
1166 }
1167 else
1168 *dstp = src;
1169
1170 /* Continue traversing the hash table. */
1171 return 1;
1172 }
1173 else
1174 dst = *dstp;
1175
1176 gcc_assert (src->n_var_parts);
1177
1178 /* Count the number of location parts, result is K. */
1179 for (i = 0, j = 0, k = 0;
1180 i < src->n_var_parts && j < dst->n_var_parts; k++)
1181 {
1182 if (src->var_part[i].offset == dst->var_part[j].offset)
1183 {
1184 i++;
1185 j++;
1186 }
1187 else if (src->var_part[i].offset < dst->var_part[j].offset)
1188 i++;
1189 else
1190 j++;
1191 }
1192 k += src->n_var_parts - i;
1193 k += dst->n_var_parts - j;
1194
1195 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1196 thus there are at most MAX_VAR_PARTS different offsets. */
1197 gcc_assert (k <= MAX_VAR_PARTS);
1198
1199 if (dst->refcount > 1 && dst->n_var_parts != k)
1200 {
1201 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1202
1203 if (! flag_var_tracking_uninit)
1204 status = VAR_INIT_STATUS_INITIALIZED;
1205 dst = unshare_variable (set, dst, status);
1206 }
1207
1208 i = src->n_var_parts - 1;
1209 j = dst->n_var_parts - 1;
1210 dst->n_var_parts = k;
1211
1212 for (k--; k >= 0; k--)
1213 {
1214 location_chain node, node2;
1215
1216 if (i >= 0 && j >= 0
1217 && src->var_part[i].offset == dst->var_part[j].offset)
1218 {
1219 /* Compute the "sorted" union of the chains, i.e. the locations which
1220 are in both chains go first, they are sorted by the sum of
1221 positions in the chains. */
1222 int dst_l, src_l;
1223 int ii, jj, n;
1224 struct variable_union_info *vui;
1225
1226 /* If DST is shared compare the location chains.
1227 If they are different we will modify the chain in DST with
1228 high probability so make a copy of DST. */
1229 if (dst->refcount > 1)
1230 {
1231 for (node = src->var_part[i].loc_chain,
1232 node2 = dst->var_part[j].loc_chain; node && node2;
1233 node = node->next, node2 = node2->next)
1234 {
1235 if (!((REG_P (node2->loc)
1236 && REG_P (node->loc)
1237 && REGNO (node2->loc) == REGNO (node->loc))
1238 || rtx_equal_p (node2->loc, node->loc)))
1239 {
1240 if (node2->init < node->init)
1241 node2->init = node->init;
1242 break;
1243 }
1244 }
1245 if (node || node2)
1246 dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
1247 }
1248
1249 src_l = 0;
1250 for (node = src->var_part[i].loc_chain; node; node = node->next)
1251 src_l++;
1252 dst_l = 0;
1253 for (node = dst->var_part[j].loc_chain; node; node = node->next)
1254 dst_l++;
1255 vui = XCNEWVEC (struct variable_union_info, src_l + dst_l);
1256
1257 /* Fill in the locations from DST. */
1258 for (node = dst->var_part[j].loc_chain, jj = 0; node;
1259 node = node->next, jj++)
1260 {
1261 vui[jj].lc = node;
1262 vui[jj].pos_dst = jj;
1263
1264 /* Value larger than a sum of 2 valid positions. */
1265 vui[jj].pos_src = src_l + dst_l;
1266 }
1267
1268 /* Fill in the locations from SRC. */
1269 n = dst_l;
1270 for (node = src->var_part[i].loc_chain, ii = 0; node;
1271 node = node->next, ii++)
1272 {
1273 /* Find location from NODE. */
1274 for (jj = 0; jj < dst_l; jj++)
1275 {
1276 if ((REG_P (vui[jj].lc->loc)
1277 && REG_P (node->loc)
1278 && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
1279 || rtx_equal_p (vui[jj].lc->loc, node->loc))
1280 {
1281 vui[jj].pos_src = ii;
1282 break;
1283 }
1284 }
1285 if (jj >= dst_l) /* The location has not been found. */
1286 {
1287 location_chain new_node;
1288
1289 /* Copy the location from SRC. */
1290 new_node = (location_chain) pool_alloc (loc_chain_pool);
1291 new_node->loc = node->loc;
1292 new_node->init = node->init;
1293 if (!node->set_src || MEM_P (node->set_src))
1294 new_node->set_src = NULL;
1295 else
1296 new_node->set_src = node->set_src;
1297 vui[n].lc = new_node;
1298 vui[n].pos_src = ii;
1299 vui[n].pos_dst = src_l + dst_l;
1300 n++;
1301 }
1302 }
1303
1304 for (ii = 0; ii < src_l + dst_l; ii++)
1305 vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst;
1306
1307 qsort (vui, n, sizeof (struct variable_union_info),
1308 variable_union_info_cmp_pos);
1309
1310 /* Reconnect the nodes in sorted order. */
1311 for (ii = 1; ii < n; ii++)
1312 vui[ii - 1].lc->next = vui[ii].lc;
1313 vui[n - 1].lc->next = NULL;
1314
1315 dst->var_part[k].loc_chain = vui[0].lc;
1316 dst->var_part[k].offset = dst->var_part[j].offset;
1317
1318 free (vui);
1319 i--;
1320 j--;
1321 }
1322 else if ((i >= 0 && j >= 0
1323 && src->var_part[i].offset < dst->var_part[j].offset)
1324 || i < 0)
1325 {
1326 dst->var_part[k] = dst->var_part[j];
1327 j--;
1328 }
1329 else if ((i >= 0 && j >= 0
1330 && src->var_part[i].offset > dst->var_part[j].offset)
1331 || j < 0)
1332 {
1333 location_chain *nextp;
1334
1335 /* Copy the chain from SRC. */
1336 nextp = &dst->var_part[k].loc_chain;
1337 for (node = src->var_part[i].loc_chain; node; node = node->next)
1338 {
1339 location_chain new_lc;
1340
1341 new_lc = (location_chain) pool_alloc (loc_chain_pool);
1342 new_lc->next = NULL;
1343 new_lc->init = node->init;
1344 if (!node->set_src || MEM_P (node->set_src))
1345 new_lc->set_src = NULL;
1346 else
1347 new_lc->set_src = node->set_src;
1348 new_lc->loc = node->loc;
1349
1350 *nextp = new_lc;
1351 nextp = &new_lc->next;
1352 }
1353
1354 dst->var_part[k].offset = src->var_part[i].offset;
1355 i--;
1356 }
1357
1358 /* We are at the basic block boundary when computing union
1359 so set the CUR_LOC to be the first element of the chain. */
1360 if (dst->var_part[k].loc_chain)
1361 dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc;
1362 else
1363 dst->var_part[k].cur_loc = NULL;
1364 }
1365
1366 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
1367 {
1368 location_chain node, node2;
1369 for (node = src->var_part[i].loc_chain; node; node = node->next)
1370 for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
1371 if (rtx_equal_p (node->loc, node2->loc))
1372 {
1373 if (node->init > node2->init)
1374 node2->init = node->init;
1375 }
1376 }
1377
1378 /* Continue traversing the hash table. */
1379 return 1;
1380 }
1381
1382 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1383
1384 static void
1385 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
1386 {
1387 int i;
1388
1389 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1390 attrs_list_union (&dst->regs[i], src->regs[i]);
1391
1392 htab_traverse (src->vars, variable_union, dst);
1393 }
1394
1395 /* Flag whether two dataflow sets being compared contain different data. */
1396 static bool
1397 dataflow_set_different_value;
1398
1399 static bool
1400 variable_part_different_p (variable_part *vp1, variable_part *vp2)
1401 {
1402 location_chain lc1, lc2;
1403
1404 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
1405 {
1406 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
1407 {
1408 if (REG_P (lc1->loc) && REG_P (lc2->loc))
1409 {
1410 if (REGNO (lc1->loc) == REGNO (lc2->loc))
1411 break;
1412 }
1413 if (rtx_equal_p (lc1->loc, lc2->loc))
1414 break;
1415 }
1416 if (!lc2)
1417 return true;
1418 }
1419 return false;
1420 }
1421
1422 /* Return true if variables VAR1 and VAR2 are different.
1423 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1424 variable part. */
1425
1426 static bool
1427 variable_different_p (variable var1, variable var2,
1428 bool compare_current_location)
1429 {
1430 int i;
1431
1432 if (var1 == var2)
1433 return false;
1434
1435 if (var1->n_var_parts != var2->n_var_parts)
1436 return true;
1437
1438 for (i = 0; i < var1->n_var_parts; i++)
1439 {
1440 if (var1->var_part[i].offset != var2->var_part[i].offset)
1441 return true;
1442 if (compare_current_location)
1443 {
1444 if (!((REG_P (var1->var_part[i].cur_loc)
1445 && REG_P (var2->var_part[i].cur_loc)
1446 && (REGNO (var1->var_part[i].cur_loc)
1447 == REGNO (var2->var_part[i].cur_loc)))
1448 || rtx_equal_p (var1->var_part[i].cur_loc,
1449 var2->var_part[i].cur_loc)))
1450 return true;
1451 }
1452 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
1453 return true;
1454 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
1455 return true;
1456 }
1457 return false;
1458 }
1459
1460 /* Compare variable *SLOT with the same variable in hash table DATA
1461 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1462
1463 static int
1464 dataflow_set_different_1 (void **slot, void *data)
1465 {
1466 htab_t htab = (htab_t) data;
1467 variable var1, var2;
1468
1469 var1 = *(variable *) slot;
1470 var2 = (variable) htab_find_with_hash (htab, var1->decl,
1471 VARIABLE_HASH_VAL (var1->decl));
1472 if (!var2)
1473 {
1474 dataflow_set_different_value = true;
1475
1476 /* Stop traversing the hash table. */
1477 return 0;
1478 }
1479
1480 if (variable_different_p (var1, var2, false))
1481 {
1482 dataflow_set_different_value = true;
1483
1484 /* Stop traversing the hash table. */
1485 return 0;
1486 }
1487
1488 /* Continue traversing the hash table. */
1489 return 1;
1490 }
1491
1492 /* Compare variable *SLOT with the same variable in hash table DATA
1493 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1494
1495 static int
1496 dataflow_set_different_2 (void **slot, void *data)
1497 {
1498 htab_t htab = (htab_t) data;
1499 variable var1, var2;
1500
1501 var1 = *(variable *) slot;
1502 var2 = (variable) htab_find_with_hash (htab, var1->decl,
1503 VARIABLE_HASH_VAL (var1->decl));
1504 if (!var2)
1505 {
1506 dataflow_set_different_value = true;
1507
1508 /* Stop traversing the hash table. */
1509 return 0;
1510 }
1511
1512 /* If both variables are defined they have been already checked for
1513 equivalence. */
1514 gcc_assert (!variable_different_p (var1, var2, false));
1515
1516 /* Continue traversing the hash table. */
1517 return 1;
1518 }
1519
1520 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1521
1522 static bool
1523 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
1524 {
1525 dataflow_set_different_value = false;
1526
1527 htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars);
1528 if (!dataflow_set_different_value)
1529 {
1530 /* We have compared the variables which are in both hash tables
1531 so now only check whether there are some variables in NEW_SET->VARS
1532 which are not in OLD_SET->VARS. */
1533 htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars);
1534 }
1535 return dataflow_set_different_value;
1536 }
1537
1538 /* Free the contents of dataflow set SET. */
1539
1540 static void
1541 dataflow_set_destroy (dataflow_set *set)
1542 {
1543 int i;
1544
1545 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1546 attrs_list_clear (&set->regs[i]);
1547
1548 htab_delete (set->vars);
1549 set->vars = NULL;
1550 }
1551
1552 /* Return true if RTL X contains a SYMBOL_REF. */
1553
1554 static bool
1555 contains_symbol_ref (rtx x)
1556 {
1557 const char *fmt;
1558 RTX_CODE code;
1559 int i;
1560
1561 if (!x)
1562 return false;
1563
1564 code = GET_CODE (x);
1565 if (code == SYMBOL_REF)
1566 return true;
1567
1568 fmt = GET_RTX_FORMAT (code);
1569 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1570 {
1571 if (fmt[i] == 'e')
1572 {
1573 if (contains_symbol_ref (XEXP (x, i)))
1574 return true;
1575 }
1576 else if (fmt[i] == 'E')
1577 {
1578 int j;
1579 for (j = 0; j < XVECLEN (x, i); j++)
1580 if (contains_symbol_ref (XVECEXP (x, i, j)))
1581 return true;
1582 }
1583 }
1584
1585 return false;
1586 }
1587
1588 /* Shall EXPR be tracked? */
1589
1590 static bool
1591 track_expr_p (tree expr)
1592 {
1593 rtx decl_rtl;
1594 tree realdecl;
1595
1596 /* If EXPR is not a parameter or a variable do not track it. */
1597 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
1598 return 0;
1599
1600 /* It also must have a name... */
1601 if (!DECL_NAME (expr))
1602 return 0;
1603
1604 /* ... and a RTL assigned to it. */
1605 decl_rtl = DECL_RTL_IF_SET (expr);
1606 if (!decl_rtl)
1607 return 0;
1608
1609 /* If this expression is really a debug alias of some other declaration, we
1610 don't need to track this expression if the ultimate declaration is
1611 ignored. */
1612 realdecl = expr;
1613 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
1614 {
1615 realdecl = DECL_DEBUG_EXPR (realdecl);
1616 /* ??? We don't yet know how to emit DW_OP_piece for variable
1617 that has been SRA'ed. */
1618 if (!DECL_P (realdecl))
1619 return 0;
1620 }
1621
1622 /* Do not track EXPR if REALDECL it should be ignored for debugging
1623 purposes. */
1624 if (DECL_IGNORED_P (realdecl))
1625 return 0;
1626
1627 /* Do not track global variables until we are able to emit correct location
1628 list for them. */
1629 if (TREE_STATIC (realdecl))
1630 return 0;
1631
1632 /* When the EXPR is a DECL for alias of some variable (see example)
1633 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1634 DECL_RTL contains SYMBOL_REF.
1635
1636 Example:
1637 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1638 char **_dl_argv;
1639 */
1640 if (MEM_P (decl_rtl)
1641 && contains_symbol_ref (XEXP (decl_rtl, 0)))
1642 return 0;
1643
1644 /* If RTX is a memory it should not be very large (because it would be
1645 an array or struct). */
1646 if (MEM_P (decl_rtl))
1647 {
1648 /* Do not track structures and arrays. */
1649 if (GET_MODE (decl_rtl) == BLKmode
1650 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
1651 return 0;
1652 if (MEM_SIZE (decl_rtl)
1653 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
1654 return 0;
1655 }
1656
1657 return 1;
1658 }
1659
1660 /* Determine whether a given LOC refers to the same variable part as
1661 EXPR+OFFSET. */
1662
1663 static bool
1664 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
1665 {
1666 tree expr2;
1667 HOST_WIDE_INT offset2;
1668
1669 if (! DECL_P (expr))
1670 return false;
1671
1672 if (REG_P (loc))
1673 {
1674 expr2 = REG_EXPR (loc);
1675 offset2 = REG_OFFSET (loc);
1676 }
1677 else if (MEM_P (loc))
1678 {
1679 expr2 = MEM_EXPR (loc);
1680 offset2 = INT_MEM_OFFSET (loc);
1681 }
1682 else
1683 return false;
1684
1685 if (! expr2 || ! DECL_P (expr2))
1686 return false;
1687
1688 expr = var_debug_decl (expr);
1689 expr2 = var_debug_decl (expr2);
1690
1691 return (expr == expr2 && offset == offset2);
1692 }
1693
1694 /* LOC is a REG or MEM that we would like to track if possible.
1695 If EXPR is null, we don't know what expression LOC refers to,
1696 otherwise it refers to EXPR + OFFSET. STORE_REG_P is true if
1697 LOC is an lvalue register.
1698
1699 Return true if EXPR is nonnull and if LOC, or some lowpart of it,
1700 is something we can track. When returning true, store the mode of
1701 the lowpart we can track in *MODE_OUT (if nonnull) and its offset
1702 from EXPR in *OFFSET_OUT (if nonnull). */
1703
1704 static bool
1705 track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
1706 enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
1707 {
1708 enum machine_mode mode;
1709
1710 if (expr == NULL || !track_expr_p (expr))
1711 return false;
1712
1713 /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
1714 whole subreg, but only the old inner part is really relevant. */
1715 mode = GET_MODE (loc);
1716 if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
1717 {
1718 enum machine_mode pseudo_mode;
1719
1720 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
1721 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
1722 {
1723 offset += byte_lowpart_offset (pseudo_mode, mode);
1724 mode = pseudo_mode;
1725 }
1726 }
1727
1728 /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
1729 Do the same if we are storing to a register and EXPR occupies
1730 the whole of register LOC; in that case, the whole of EXPR is
1731 being changed. We exclude complex modes from the second case
1732 because the real and imaginary parts are represented as separate
1733 pseudo registers, even if the whole complex value fits into one
1734 hard register. */
1735 if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
1736 || (store_reg_p
1737 && !COMPLEX_MODE_P (DECL_MODE (expr))
1738 && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
1739 && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
1740 {
1741 mode = DECL_MODE (expr);
1742 offset = 0;
1743 }
1744
1745 if (offset < 0 || offset >= MAX_VAR_PARTS)
1746 return false;
1747
1748 if (mode_out)
1749 *mode_out = mode;
1750 if (offset_out)
1751 *offset_out = offset;
1752 return true;
1753 }
1754
1755 /* Return the MODE lowpart of LOC, or null if LOC is not something we
1756 want to track. When returning nonnull, make sure that the attributes
1757 on the returned value are updated. */
1758
1759 static rtx
1760 var_lowpart (enum machine_mode mode, rtx loc)
1761 {
1762 unsigned int offset, reg_offset, regno;
1763
1764 if (!REG_P (loc) && !MEM_P (loc))
1765 return NULL;
1766
1767 if (GET_MODE (loc) == mode)
1768 return loc;
1769
1770 offset = byte_lowpart_offset (mode, GET_MODE (loc));
1771
1772 if (MEM_P (loc))
1773 return adjust_address_nv (loc, mode, offset);
1774
1775 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
1776 regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
1777 reg_offset, mode);
1778 return gen_rtx_REG_offset (loc, mode, regno, offset);
1779 }
1780
1781 /* Count uses (register and memory references) LOC which will be tracked.
1782 INSN is instruction which the LOC is part of. */
1783
1784 static int
1785 count_uses (rtx *loc, void *insn)
1786 {
1787 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1788
1789 if (REG_P (*loc))
1790 {
1791 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
1792 VTI (bb)->n_mos++;
1793 }
1794 else if (MEM_P (*loc)
1795 && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
1796 false, NULL, NULL))
1797 {
1798 VTI (bb)->n_mos++;
1799 }
1800
1801 return 0;
1802 }
1803
1804 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1805
1806 static void
1807 count_uses_1 (rtx *x, void *insn)
1808 {
1809 for_each_rtx (x, count_uses, insn);
1810 }
1811
1812 /* Count stores (register and memory references) LOC which will be tracked.
1813 INSN is instruction which the LOC is part of. */
1814
1815 static void
1816 count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *insn)
1817 {
1818 count_uses (&loc, insn);
1819 }
1820
1821 /* Add uses (register and memory references) LOC which will be tracked
1822 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
1823
1824 static int
1825 add_uses (rtx *loc, void *insn)
1826 {
1827 enum machine_mode mode;
1828
1829 if (REG_P (*loc))
1830 {
1831 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1832 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1833
1834 if (track_loc_p (*loc, REG_EXPR (*loc), REG_OFFSET (*loc),
1835 false, &mode, NULL))
1836 {
1837 mo->type = MO_USE;
1838 mo->u.loc = var_lowpart (mode, *loc);
1839 }
1840 else
1841 {
1842 mo->type = MO_USE_NO_VAR;
1843 mo->u.loc = *loc;
1844 }
1845 mo->insn = (rtx) insn;
1846 }
1847 else if (MEM_P (*loc)
1848 && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
1849 false, &mode, NULL))
1850 {
1851 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1852 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1853
1854 mo->type = MO_USE;
1855 mo->u.loc = var_lowpart (mode, *loc);
1856 mo->insn = (rtx) insn;
1857 }
1858
1859 return 0;
1860 }
1861
1862 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1863
1864 static void
1865 add_uses_1 (rtx *x, void *insn)
1866 {
1867 for_each_rtx (x, add_uses, insn);
1868 }
1869
1870 /* Add stores (register and memory references) LOC which will be tracked
1871 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
1872 INSN is instruction which the LOC is part of. */
1873
1874 static void
1875 add_stores (rtx loc, const_rtx expr, void *insn)
1876 {
1877 enum machine_mode mode;
1878
1879 if (REG_P (loc))
1880 {
1881 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1882 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1883
1884 if (GET_CODE (expr) == CLOBBER
1885 || !track_loc_p (loc, REG_EXPR (loc), REG_OFFSET (loc),
1886 true, &mode, NULL))
1887 {
1888 mo->type = MO_CLOBBER;
1889 mo->u.loc = loc;
1890 }
1891 else
1892 {
1893 rtx src = NULL;
1894
1895 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1896 src = var_lowpart (mode, SET_SRC (expr));
1897 loc = var_lowpart (mode, loc);
1898
1899 if (src == NULL)
1900 {
1901 mo->type = MO_SET;
1902 mo->u.loc = loc;
1903 }
1904 else
1905 {
1906 if (SET_SRC (expr) != src)
1907 expr = gen_rtx_SET (VOIDmode, loc, src);
1908 if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
1909 mo->type = MO_COPY;
1910 else
1911 mo->type = MO_SET;
1912 mo->u.loc = CONST_CAST_RTX (expr);
1913 }
1914 }
1915 mo->insn = (rtx) insn;
1916 }
1917 else if (MEM_P (loc)
1918 && track_loc_p (loc, MEM_EXPR (loc), INT_MEM_OFFSET (loc),
1919 false, &mode, NULL))
1920 {
1921 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1922 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1923
1924 if (GET_CODE (expr) == CLOBBER)
1925 {
1926 mo->type = MO_CLOBBER;
1927 mo->u.loc = var_lowpart (mode, loc);
1928 }
1929 else
1930 {
1931 rtx src = NULL;
1932
1933 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1934 src = var_lowpart (mode, SET_SRC (expr));
1935 loc = var_lowpart (mode, loc);
1936
1937 if (src == NULL)
1938 {
1939 mo->type = MO_SET;
1940 mo->u.loc = loc;
1941 }
1942 else
1943 {
1944 if (SET_SRC (expr) != src)
1945 expr = gen_rtx_SET (VOIDmode, loc, src);
1946 if (same_variable_part_p (SET_SRC (expr),
1947 MEM_EXPR (loc),
1948 INT_MEM_OFFSET (loc)))
1949 mo->type = MO_COPY;
1950 else
1951 mo->type = MO_SET;
1952 mo->u.loc = CONST_CAST_RTX (expr);
1953 }
1954 }
1955 mo->insn = (rtx) insn;
1956 }
1957 }
1958
1959 static enum var_init_status
1960 find_src_status (dataflow_set *in, rtx src)
1961 {
1962 tree decl = NULL_TREE;
1963 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
1964
1965 if (! flag_var_tracking_uninit)
1966 status = VAR_INIT_STATUS_INITIALIZED;
1967
1968 if (src && REG_P (src))
1969 decl = var_debug_decl (REG_EXPR (src));
1970 else if (src && MEM_P (src))
1971 decl = var_debug_decl (MEM_EXPR (src));
1972
1973 if (src && decl)
1974 status = get_init_value (in, src, decl);
1975
1976 return status;
1977 }
1978
1979 /* SRC is the source of an assignment. Use SET to try to find what
1980 was ultimately assigned to SRC. Return that value if known,
1981 otherwise return SRC itself. */
1982
1983 static rtx
1984 find_src_set_src (dataflow_set *set, rtx src)
1985 {
1986 tree decl = NULL_TREE; /* The variable being copied around. */
1987 rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
1988 void **slot;
1989 variable var;
1990 location_chain nextp;
1991 int i;
1992 bool found;
1993
1994 if (src && REG_P (src))
1995 decl = var_debug_decl (REG_EXPR (src));
1996 else if (src && MEM_P (src))
1997 decl = var_debug_decl (MEM_EXPR (src));
1998
1999 if (src && decl)
2000 {
2001 slot = htab_find_slot_with_hash (set->vars, decl,
2002 VARIABLE_HASH_VAL (decl), NO_INSERT);
2003
2004 if (slot)
2005 {
2006 var = *(variable *) slot;
2007 found = false;
2008 for (i = 0; i < var->n_var_parts && !found; i++)
2009 for (nextp = var->var_part[i].loc_chain; nextp && !found;
2010 nextp = nextp->next)
2011 if (rtx_equal_p (nextp->loc, src))
2012 {
2013 set_src = nextp->set_src;
2014 found = true;
2015 }
2016
2017 }
2018 }
2019
2020 return set_src;
2021 }
2022
2023 /* Compute the changes of variable locations in the basic block BB. */
2024
2025 static bool
2026 compute_bb_dataflow (basic_block bb)
2027 {
2028 int i, n, r;
2029 bool changed;
2030 dataflow_set old_out;
2031 dataflow_set *in = &VTI (bb)->in;
2032 dataflow_set *out = &VTI (bb)->out;
2033
2034 dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3);
2035 dataflow_set_copy (&old_out, out);
2036 dataflow_set_copy (out, in);
2037
2038 n = VTI (bb)->n_mos;
2039 for (i = 0; i < n; i++)
2040 {
2041 switch (VTI (bb)->mos[i].type)
2042 {
2043 case MO_CALL:
2044 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
2045 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
2046 var_regno_delete (out, r);
2047 break;
2048
2049 case MO_USE:
2050 {
2051 rtx loc = VTI (bb)->mos[i].u.loc;
2052 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
2053
2054 if (! flag_var_tracking_uninit)
2055 status = VAR_INIT_STATUS_INITIALIZED;
2056
2057 if (GET_CODE (loc) == REG)
2058 var_reg_set (out, loc, status, NULL);
2059 else if (GET_CODE (loc) == MEM)
2060 var_mem_set (out, loc, status, NULL);
2061 }
2062 break;
2063
2064 case MO_SET:
2065 {
2066 rtx loc = VTI (bb)->mos[i].u.loc;
2067 rtx set_src = NULL;
2068
2069 if (GET_CODE (loc) == SET)
2070 {
2071 set_src = SET_SRC (loc);
2072 loc = SET_DEST (loc);
2073 }
2074
2075 if (REG_P (loc))
2076 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2077 set_src);
2078 else if (MEM_P (loc))
2079 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2080 set_src);
2081 }
2082 break;
2083
2084 case MO_COPY:
2085 {
2086 rtx loc = VTI (bb)->mos[i].u.loc;
2087 enum var_init_status src_status;
2088 rtx set_src = NULL;
2089
2090 if (GET_CODE (loc) == SET)
2091 {
2092 set_src = SET_SRC (loc);
2093 loc = SET_DEST (loc);
2094 }
2095
2096 if (! flag_var_tracking_uninit)
2097 src_status = VAR_INIT_STATUS_INITIALIZED;
2098 else
2099 src_status = find_src_status (in, set_src);
2100
2101 if (src_status == VAR_INIT_STATUS_UNKNOWN)
2102 src_status = find_src_status (out, set_src);
2103
2104 set_src = find_src_set_src (in, set_src);
2105
2106 if (REG_P (loc))
2107 var_reg_delete_and_set (out, loc, false, src_status, set_src);
2108 else if (MEM_P (loc))
2109 var_mem_delete_and_set (out, loc, false, src_status, set_src);
2110 }
2111 break;
2112
2113 case MO_USE_NO_VAR:
2114 {
2115 rtx loc = VTI (bb)->mos[i].u.loc;
2116
2117 if (REG_P (loc))
2118 var_reg_delete (out, loc, false);
2119 else if (MEM_P (loc))
2120 var_mem_delete (out, loc, false);
2121 }
2122 break;
2123
2124 case MO_CLOBBER:
2125 {
2126 rtx loc = VTI (bb)->mos[i].u.loc;
2127
2128 if (REG_P (loc))
2129 var_reg_delete (out, loc, true);
2130 else if (MEM_P (loc))
2131 var_mem_delete (out, loc, true);
2132 }
2133 break;
2134
2135 case MO_ADJUST:
2136 out->stack_adjust += VTI (bb)->mos[i].u.adjust;
2137 break;
2138 }
2139 }
2140
2141 changed = dataflow_set_different (&old_out, out);
2142 dataflow_set_destroy (&old_out);
2143 return changed;
2144 }
2145
2146 /* Find the locations of variables in the whole function. */
2147
2148 static void
2149 vt_find_locations (void)
2150 {
2151 fibheap_t worklist, pending, fibheap_swap;
2152 sbitmap visited, in_worklist, in_pending, sbitmap_swap;
2153 basic_block bb;
2154 edge e;
2155 int *bb_order;
2156 int *rc_order;
2157 int i;
2158
2159 /* Compute reverse completion order of depth first search of the CFG
2160 so that the data-flow runs faster. */
2161 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
2162 bb_order = XNEWVEC (int, last_basic_block);
2163 pre_and_rev_post_order_compute (NULL, rc_order, false);
2164 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
2165 bb_order[rc_order[i]] = i;
2166 free (rc_order);
2167
2168 worklist = fibheap_new ();
2169 pending = fibheap_new ();
2170 visited = sbitmap_alloc (last_basic_block);
2171 in_worklist = sbitmap_alloc (last_basic_block);
2172 in_pending = sbitmap_alloc (last_basic_block);
2173 sbitmap_zero (in_worklist);
2174
2175 FOR_EACH_BB (bb)
2176 fibheap_insert (pending, bb_order[bb->index], bb);
2177 sbitmap_ones (in_pending);
2178
2179 while (!fibheap_empty (pending))
2180 {
2181 fibheap_swap = pending;
2182 pending = worklist;
2183 worklist = fibheap_swap;
2184 sbitmap_swap = in_pending;
2185 in_pending = in_worklist;
2186 in_worklist = sbitmap_swap;
2187
2188 sbitmap_zero (visited);
2189
2190 while (!fibheap_empty (worklist))
2191 {
2192 bb = (basic_block) fibheap_extract_min (worklist);
2193 RESET_BIT (in_worklist, bb->index);
2194 if (!TEST_BIT (visited, bb->index))
2195 {
2196 bool changed;
2197 edge_iterator ei;
2198
2199 SET_BIT (visited, bb->index);
2200
2201 /* Calculate the IN set as union of predecessor OUT sets. */
2202 dataflow_set_clear (&VTI (bb)->in);
2203 FOR_EACH_EDGE (e, ei, bb->preds)
2204 {
2205 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
2206 }
2207
2208 changed = compute_bb_dataflow (bb);
2209 if (changed)
2210 {
2211 FOR_EACH_EDGE (e, ei, bb->succs)
2212 {
2213 if (e->dest == EXIT_BLOCK_PTR)
2214 continue;
2215
2216 if (e->dest == bb)
2217 continue;
2218
2219 if (TEST_BIT (visited, e->dest->index))
2220 {
2221 if (!TEST_BIT (in_pending, e->dest->index))
2222 {
2223 /* Send E->DEST to next round. */
2224 SET_BIT (in_pending, e->dest->index);
2225 fibheap_insert (pending,
2226 bb_order[e->dest->index],
2227 e->dest);
2228 }
2229 }
2230 else if (!TEST_BIT (in_worklist, e->dest->index))
2231 {
2232 /* Add E->DEST to current round. */
2233 SET_BIT (in_worklist, e->dest->index);
2234 fibheap_insert (worklist, bb_order[e->dest->index],
2235 e->dest);
2236 }
2237 }
2238 }
2239 }
2240 }
2241 }
2242
2243 free (bb_order);
2244 fibheap_delete (worklist);
2245 fibheap_delete (pending);
2246 sbitmap_free (visited);
2247 sbitmap_free (in_worklist);
2248 sbitmap_free (in_pending);
2249 }
2250
2251 /* Print the content of the LIST to dump file. */
2252
2253 static void
2254 dump_attrs_list (attrs list)
2255 {
2256 for (; list; list = list->next)
2257 {
2258 print_mem_expr (dump_file, list->decl);
2259 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
2260 }
2261 fprintf (dump_file, "\n");
2262 }
2263
2264 /* Print the information about variable *SLOT to dump file. */
2265
2266 static int
2267 dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
2268 {
2269 variable var = *(variable *) slot;
2270 int i;
2271 location_chain node;
2272
2273 fprintf (dump_file, " name: %s",
2274 IDENTIFIER_POINTER (DECL_NAME (var->decl)));
2275 if (dump_flags & TDF_UID)
2276 fprintf (dump_file, " D.%u\n", DECL_UID (var->decl));
2277 else
2278 fprintf (dump_file, "\n");
2279
2280 for (i = 0; i < var->n_var_parts; i++)
2281 {
2282 fprintf (dump_file, " offset %ld\n",
2283 (long) var->var_part[i].offset);
2284 for (node = var->var_part[i].loc_chain; node; node = node->next)
2285 {
2286 fprintf (dump_file, " ");
2287 if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
2288 fprintf (dump_file, "[uninit]");
2289 print_rtl_single (dump_file, node->loc);
2290 }
2291 }
2292
2293 /* Continue traversing the hash table. */
2294 return 1;
2295 }
2296
2297 /* Print the information about variables from hash table VARS to dump file. */
2298
2299 static void
2300 dump_vars (htab_t vars)
2301 {
2302 if (htab_elements (vars) > 0)
2303 {
2304 fprintf (dump_file, "Variables:\n");
2305 htab_traverse (vars, dump_variable, NULL);
2306 }
2307 }
2308
2309 /* Print the dataflow set SET to dump file. */
2310
2311 static void
2312 dump_dataflow_set (dataflow_set *set)
2313 {
2314 int i;
2315
2316 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
2317 set->stack_adjust);
2318 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2319 {
2320 if (set->regs[i])
2321 {
2322 fprintf (dump_file, "Reg %d:", i);
2323 dump_attrs_list (set->regs[i]);
2324 }
2325 }
2326 dump_vars (set->vars);
2327 fprintf (dump_file, "\n");
2328 }
2329
2330 /* Print the IN and OUT sets for each basic block to dump file. */
2331
2332 static void
2333 dump_dataflow_sets (void)
2334 {
2335 basic_block bb;
2336
2337 FOR_EACH_BB (bb)
2338 {
2339 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
2340 fprintf (dump_file, "IN:\n");
2341 dump_dataflow_set (&VTI (bb)->in);
2342 fprintf (dump_file, "OUT:\n");
2343 dump_dataflow_set (&VTI (bb)->out);
2344 }
2345 }
2346
2347 /* Add variable VAR to the hash table of changed variables and
2348 if it has no locations delete it from hash table HTAB. */
2349
2350 static void
2351 variable_was_changed (variable var, htab_t htab)
2352 {
2353 hashval_t hash = VARIABLE_HASH_VAL (var->decl);
2354
2355 if (emit_notes)
2356 {
2357 variable *slot;
2358
2359 slot = (variable *) htab_find_slot_with_hash (changed_variables,
2360 var->decl, hash, INSERT);
2361
2362 if (htab && var->n_var_parts == 0)
2363 {
2364 variable empty_var;
2365 void **old;
2366
2367 empty_var = (variable) pool_alloc (var_pool);
2368 empty_var->decl = var->decl;
2369 empty_var->refcount = 1;
2370 empty_var->n_var_parts = 0;
2371 *slot = empty_var;
2372
2373 old = htab_find_slot_with_hash (htab, var->decl, hash,
2374 NO_INSERT);
2375 if (old)
2376 htab_clear_slot (htab, old);
2377 }
2378 else
2379 {
2380 *slot = var;
2381 }
2382 }
2383 else
2384 {
2385 gcc_assert (htab);
2386 if (var->n_var_parts == 0)
2387 {
2388 void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
2389 NO_INSERT);
2390 if (slot)
2391 htab_clear_slot (htab, slot);
2392 }
2393 }
2394 }
2395
2396 /* Look for the index in VAR->var_part corresponding to OFFSET.
2397 Return -1 if not found. If INSERTION_POINT is non-NULL, the
2398 referenced int will be set to the index that the part has or should
2399 have, if it should be inserted. */
2400
2401 static inline int
2402 find_variable_location_part (variable var, HOST_WIDE_INT offset,
2403 int *insertion_point)
2404 {
2405 int pos, low, high;
2406
2407 /* Find the location part. */
2408 low = 0;
2409 high = var->n_var_parts;
2410 while (low != high)
2411 {
2412 pos = (low + high) / 2;
2413 if (var->var_part[pos].offset < offset)
2414 low = pos + 1;
2415 else
2416 high = pos;
2417 }
2418 pos = low;
2419
2420 if (insertion_point)
2421 *insertion_point = pos;
2422
2423 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
2424 return pos;
2425
2426 return -1;
2427 }
2428
2429 /* Set the part of variable's location in the dataflow set SET. The variable
2430 part is specified by variable's declaration DECL and offset OFFSET and the
2431 part's location by LOC. */
2432
2433 static void
2434 set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset,
2435 enum var_init_status initialized, rtx set_src)
2436 {
2437 int pos;
2438 location_chain node, next;
2439 location_chain *nextp;
2440 variable var;
2441 void **slot;
2442
2443 slot = htab_find_slot_with_hash (set->vars, decl,
2444 VARIABLE_HASH_VAL (decl), INSERT);
2445 if (!*slot)
2446 {
2447 /* Create new variable information. */
2448 var = (variable) pool_alloc (var_pool);
2449 var->decl = decl;
2450 var->refcount = 1;
2451 var->n_var_parts = 1;
2452 var->var_part[0].offset = offset;
2453 var->var_part[0].loc_chain = NULL;
2454 var->var_part[0].cur_loc = NULL;
2455 *slot = var;
2456 pos = 0;
2457 }
2458 else
2459 {
2460 int inspos = 0;
2461
2462 var = (variable) *slot;
2463
2464 pos = find_variable_location_part (var, offset, &inspos);
2465
2466 if (pos >= 0)
2467 {
2468 node = var->var_part[pos].loc_chain;
2469
2470 if (node
2471 && ((REG_P (node->loc) && REG_P (loc)
2472 && REGNO (node->loc) == REGNO (loc))
2473 || rtx_equal_p (node->loc, loc)))
2474 {
2475 /* LOC is in the beginning of the chain so we have nothing
2476 to do. */
2477 if (node->init < initialized)
2478 node->init = initialized;
2479 if (set_src != NULL)
2480 node->set_src = set_src;
2481
2482 *slot = var;
2483 return;
2484 }
2485 else
2486 {
2487 /* We have to make a copy of a shared variable. */
2488 if (var->refcount > 1)
2489 var = unshare_variable (set, var, initialized);
2490 }
2491 }
2492 else
2493 {
2494 /* We have not found the location part, new one will be created. */
2495
2496 /* We have to make a copy of the shared variable. */
2497 if (var->refcount > 1)
2498 var = unshare_variable (set, var, initialized);
2499
2500 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2501 thus there are at most MAX_VAR_PARTS different offsets. */
2502 gcc_assert (var->n_var_parts < MAX_VAR_PARTS);
2503
2504 /* We have to move the elements of array starting at index
2505 inspos to the next position. */
2506 for (pos = var->n_var_parts; pos > inspos; pos--)
2507 var->var_part[pos] = var->var_part[pos - 1];
2508
2509 var->n_var_parts++;
2510 var->var_part[pos].offset = offset;
2511 var->var_part[pos].loc_chain = NULL;
2512 var->var_part[pos].cur_loc = NULL;
2513 }
2514 }
2515
2516 /* Delete the location from the list. */
2517 nextp = &var->var_part[pos].loc_chain;
2518 for (node = var->var_part[pos].loc_chain; node; node = next)
2519 {
2520 next = node->next;
2521 if ((REG_P (node->loc) && REG_P (loc)
2522 && REGNO (node->loc) == REGNO (loc))
2523 || rtx_equal_p (node->loc, loc))
2524 {
2525 /* Save these values, to assign to the new node, before
2526 deleting this one. */
2527 if (node->init > initialized)
2528 initialized = node->init;
2529 if (node->set_src != NULL && set_src == NULL)
2530 set_src = node->set_src;
2531 pool_free (loc_chain_pool, node);
2532 *nextp = next;
2533 break;
2534 }
2535 else
2536 nextp = &node->next;
2537 }
2538
2539 /* Add the location to the beginning. */
2540 node = (location_chain) pool_alloc (loc_chain_pool);
2541 node->loc = loc;
2542 node->init = initialized;
2543 node->set_src = set_src;
2544 node->next = var->var_part[pos].loc_chain;
2545 var->var_part[pos].loc_chain = node;
2546
2547 /* If no location was emitted do so. */
2548 if (var->var_part[pos].cur_loc == NULL)
2549 {
2550 var->var_part[pos].cur_loc = loc;
2551 variable_was_changed (var, set->vars);
2552 }
2553 }
2554
2555 /* Remove all recorded register locations for the given variable part
2556 from dataflow set SET, except for those that are identical to loc.
2557 The variable part is specified by variable's declaration DECL and
2558 offset OFFSET. */
2559
2560 static void
2561 clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
2562 HOST_WIDE_INT offset, rtx set_src)
2563 {
2564 void **slot;
2565
2566 if (! decl || ! DECL_P (decl))
2567 return;
2568
2569 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2570 NO_INSERT);
2571 if (slot)
2572 {
2573 variable var = (variable) *slot;
2574 int pos = find_variable_location_part (var, offset, NULL);
2575
2576 if (pos >= 0)
2577 {
2578 location_chain node, next;
2579
2580 /* Remove the register locations from the dataflow set. */
2581 next = var->var_part[pos].loc_chain;
2582 for (node = next; node; node = next)
2583 {
2584 next = node->next;
2585 if (node->loc != loc
2586 && (!flag_var_tracking_uninit
2587 || !set_src
2588 || MEM_P (set_src)
2589 || !rtx_equal_p (set_src, node->set_src)))
2590 {
2591 if (REG_P (node->loc))
2592 {
2593 attrs anode, anext;
2594 attrs *anextp;
2595
2596 /* Remove the variable part from the register's
2597 list, but preserve any other variable parts
2598 that might be regarded as live in that same
2599 register. */
2600 anextp = &set->regs[REGNO (node->loc)];
2601 for (anode = *anextp; anode; anode = anext)
2602 {
2603 anext = anode->next;
2604 if (anode->decl == decl
2605 && anode->offset == offset)
2606 {
2607 pool_free (attrs_pool, anode);
2608 *anextp = anext;
2609 }
2610 else
2611 anextp = &anode->next;
2612 }
2613 }
2614
2615 delete_variable_part (set, node->loc, decl, offset);
2616 }
2617 }
2618 }
2619 }
2620 }
2621
2622 /* Delete the part of variable's location from dataflow set SET. The variable
2623 part is specified by variable's declaration DECL and offset OFFSET and the
2624 part's location by LOC. */
2625
2626 static void
2627 delete_variable_part (dataflow_set *set, rtx loc, tree decl,
2628 HOST_WIDE_INT offset)
2629 {
2630 void **slot;
2631
2632 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2633 NO_INSERT);
2634 if (slot)
2635 {
2636 variable var = (variable) *slot;
2637 int pos = find_variable_location_part (var, offset, NULL);
2638
2639 if (pos >= 0)
2640 {
2641 location_chain node, next;
2642 location_chain *nextp;
2643 bool changed;
2644
2645 if (var->refcount > 1)
2646 {
2647 /* If the variable contains the location part we have to
2648 make a copy of the variable. */
2649 for (node = var->var_part[pos].loc_chain; node;
2650 node = node->next)
2651 {
2652 if ((REG_P (node->loc) && REG_P (loc)
2653 && REGNO (node->loc) == REGNO (loc))
2654 || rtx_equal_p (node->loc, loc))
2655 {
2656 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
2657 if (! flag_var_tracking_uninit)
2658 status = VAR_INIT_STATUS_INITIALIZED;
2659 var = unshare_variable (set, var, status);
2660 break;
2661 }
2662 }
2663 }
2664
2665 /* Delete the location part. */
2666 nextp = &var->var_part[pos].loc_chain;
2667 for (node = *nextp; node; node = next)
2668 {
2669 next = node->next;
2670 if ((REG_P (node->loc) && REG_P (loc)
2671 && REGNO (node->loc) == REGNO (loc))
2672 || rtx_equal_p (node->loc, loc))
2673 {
2674 pool_free (loc_chain_pool, node);
2675 *nextp = next;
2676 break;
2677 }
2678 else
2679 nextp = &node->next;
2680 }
2681
2682 /* If we have deleted the location which was last emitted
2683 we have to emit new location so add the variable to set
2684 of changed variables. */
2685 if (var->var_part[pos].cur_loc
2686 && ((REG_P (loc)
2687 && REG_P (var->var_part[pos].cur_loc)
2688 && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
2689 || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
2690 {
2691 changed = true;
2692 if (var->var_part[pos].loc_chain)
2693 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc;
2694 }
2695 else
2696 changed = false;
2697
2698 if (var->var_part[pos].loc_chain == NULL)
2699 {
2700 var->n_var_parts--;
2701 while (pos < var->n_var_parts)
2702 {
2703 var->var_part[pos] = var->var_part[pos + 1];
2704 pos++;
2705 }
2706 }
2707 if (changed)
2708 variable_was_changed (var, set->vars);
2709 }
2710 }
2711 }
2712
2713 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2714 additional parameters: WHERE specifies whether the note shall be emitted
2715 before of after instruction INSN. */
2716
2717 static int
2718 emit_note_insn_var_location (void **varp, void *data)
2719 {
2720 variable var = *(variable *) varp;
2721 rtx insn = ((emit_note_data *)data)->insn;
2722 enum emit_note_where where = ((emit_note_data *)data)->where;
2723 rtx note;
2724 int i, j, n_var_parts;
2725 bool complete;
2726 enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
2727 HOST_WIDE_INT last_limit;
2728 tree type_size_unit;
2729 HOST_WIDE_INT offsets[MAX_VAR_PARTS];
2730 rtx loc[MAX_VAR_PARTS];
2731
2732 gcc_assert (var->decl);
2733
2734 if (! flag_var_tracking_uninit)
2735 initialized = VAR_INIT_STATUS_INITIALIZED;
2736
2737 complete = true;
2738 last_limit = 0;
2739 n_var_parts = 0;
2740 for (i = 0; i < var->n_var_parts; i++)
2741 {
2742 enum machine_mode mode, wider_mode;
2743
2744 if (last_limit < var->var_part[i].offset)
2745 {
2746 complete = false;
2747 break;
2748 }
2749 else if (last_limit > var->var_part[i].offset)
2750 continue;
2751 offsets[n_var_parts] = var->var_part[i].offset;
2752 loc[n_var_parts] = var->var_part[i].loc_chain->loc;
2753 mode = GET_MODE (loc[n_var_parts]);
2754 initialized = var->var_part[i].loc_chain->init;
2755 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
2756
2757 /* Attempt to merge adjacent registers or memory. */
2758 wider_mode = GET_MODE_WIDER_MODE (mode);
2759 for (j = i + 1; j < var->n_var_parts; j++)
2760 if (last_limit <= var->var_part[j].offset)
2761 break;
2762 if (j < var->n_var_parts
2763 && wider_mode != VOIDmode
2764 && GET_CODE (loc[n_var_parts])
2765 == GET_CODE (var->var_part[j].loc_chain->loc)
2766 && mode == GET_MODE (var->var_part[j].loc_chain->loc)
2767 && last_limit == var->var_part[j].offset)
2768 {
2769 rtx new_loc = NULL;
2770 rtx loc2 = var->var_part[j].loc_chain->loc;
2771
2772 if (REG_P (loc[n_var_parts])
2773 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
2774 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
2775 && end_hard_regno (mode, REGNO (loc[n_var_parts]))
2776 == REGNO (loc2))
2777 {
2778 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
2779 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
2780 mode, 0);
2781 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
2782 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
2783 if (new_loc)
2784 {
2785 if (!REG_P (new_loc)
2786 || REGNO (new_loc) != REGNO (loc[n_var_parts]))
2787 new_loc = NULL;
2788 else
2789 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
2790 }
2791 }
2792 else if (MEM_P (loc[n_var_parts])
2793 && GET_CODE (XEXP (loc2, 0)) == PLUS
2794 && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG
2795 && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT)
2796 {
2797 if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG
2798 && rtx_equal_p (XEXP (loc[n_var_parts], 0),
2799 XEXP (XEXP (loc2, 0), 0))
2800 && INTVAL (XEXP (XEXP (loc2, 0), 1))
2801 == GET_MODE_SIZE (mode))
2802 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
2803 && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1))
2804 == CONST_INT
2805 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
2806 XEXP (XEXP (loc2, 0), 0))
2807 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
2808 + GET_MODE_SIZE (mode)
2809 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
2810 new_loc = adjust_address_nv (loc[n_var_parts],
2811 wider_mode, 0);
2812 }
2813
2814 if (new_loc)
2815 {
2816 loc[n_var_parts] = new_loc;
2817 mode = wider_mode;
2818 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
2819 i = j;
2820 }
2821 }
2822 ++n_var_parts;
2823 }
2824 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
2825 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
2826 complete = false;
2827
2828 if (where == EMIT_NOTE_AFTER_INSN)
2829 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
2830 else
2831 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
2832
2833 if (! flag_var_tracking_uninit)
2834 initialized = VAR_INIT_STATUS_INITIALIZED;
2835
2836 if (!complete)
2837 {
2838 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2839 NULL_RTX, (int) initialized);
2840 }
2841 else if (n_var_parts == 1)
2842 {
2843 rtx expr_list
2844 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
2845
2846 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2847 expr_list,
2848 (int) initialized);
2849 }
2850 else if (n_var_parts)
2851 {
2852 rtx parallel;
2853
2854 for (i = 0; i < n_var_parts; i++)
2855 loc[i]
2856 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
2857
2858 parallel = gen_rtx_PARALLEL (VOIDmode,
2859 gen_rtvec_v (n_var_parts, loc));
2860 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2861 parallel,
2862 (int) initialized);
2863 }
2864
2865 htab_clear_slot (changed_variables, varp);
2866
2867 /* When there are no location parts the variable has been already
2868 removed from hash table and a new empty variable was created.
2869 Free the empty variable. */
2870 if (var->n_var_parts == 0)
2871 {
2872 pool_free (var_pool, var);
2873 }
2874
2875 /* Continue traversing the hash table. */
2876 return 1;
2877 }
2878
2879 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
2880 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
2881 shall be emitted before of after instruction INSN. */
2882
2883 static void
2884 emit_notes_for_changes (rtx insn, enum emit_note_where where)
2885 {
2886 emit_note_data data;
2887
2888 data.insn = insn;
2889 data.where = where;
2890 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
2891 }
2892
2893 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
2894 same variable in hash table DATA or is not there at all. */
2895
2896 static int
2897 emit_notes_for_differences_1 (void **slot, void *data)
2898 {
2899 htab_t new_vars = (htab_t) data;
2900 variable old_var, new_var;
2901
2902 old_var = *(variable *) slot;
2903 new_var = (variable) htab_find_with_hash (new_vars, old_var->decl,
2904 VARIABLE_HASH_VAL (old_var->decl));
2905
2906 if (!new_var)
2907 {
2908 /* Variable has disappeared. */
2909 variable empty_var;
2910
2911 empty_var = (variable) pool_alloc (var_pool);
2912 empty_var->decl = old_var->decl;
2913 empty_var->refcount = 1;
2914 empty_var->n_var_parts = 0;
2915 variable_was_changed (empty_var, NULL);
2916 }
2917 else if (variable_different_p (old_var, new_var, true))
2918 {
2919 variable_was_changed (new_var, NULL);
2920 }
2921
2922 /* Continue traversing the hash table. */
2923 return 1;
2924 }
2925
2926 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2927 table DATA. */
2928
2929 static int
2930 emit_notes_for_differences_2 (void **slot, void *data)
2931 {
2932 htab_t old_vars = (htab_t) data;
2933 variable old_var, new_var;
2934
2935 new_var = *(variable *) slot;
2936 old_var = (variable) htab_find_with_hash (old_vars, new_var->decl,
2937 VARIABLE_HASH_VAL (new_var->decl));
2938 if (!old_var)
2939 {
2940 /* Variable has appeared. */
2941 variable_was_changed (new_var, NULL);
2942 }
2943
2944 /* Continue traversing the hash table. */
2945 return 1;
2946 }
2947
2948 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2949 NEW_SET. */
2950
2951 static void
2952 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
2953 dataflow_set *new_set)
2954 {
2955 htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars);
2956 htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars);
2957 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
2958 }
2959
2960 /* Emit the notes for changes of location parts in the basic block BB. */
2961
2962 static void
2963 emit_notes_in_bb (basic_block bb)
2964 {
2965 int i;
2966 dataflow_set set;
2967
2968 dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3);
2969 dataflow_set_copy (&set, &VTI (bb)->in);
2970
2971 for (i = 0; i < VTI (bb)->n_mos; i++)
2972 {
2973 rtx insn = VTI (bb)->mos[i].insn;
2974
2975 switch (VTI (bb)->mos[i].type)
2976 {
2977 case MO_CALL:
2978 {
2979 int r;
2980
2981 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
2982 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
2983 {
2984 var_regno_delete (&set, r);
2985 }
2986 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
2987 }
2988 break;
2989
2990 case MO_USE:
2991 {
2992 rtx loc = VTI (bb)->mos[i].u.loc;
2993
2994 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
2995 if (! flag_var_tracking_uninit)
2996 status = VAR_INIT_STATUS_INITIALIZED;
2997 if (GET_CODE (loc) == REG)
2998 var_reg_set (&set, loc, status, NULL);
2999 else
3000 var_mem_set (&set, loc, status, NULL);
3001
3002 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3003 }
3004 break;
3005
3006 case MO_SET:
3007 {
3008 rtx loc = VTI (bb)->mos[i].u.loc;
3009 rtx set_src = NULL;
3010
3011 if (GET_CODE (loc) == SET)
3012 {
3013 set_src = SET_SRC (loc);
3014 loc = SET_DEST (loc);
3015 }
3016
3017 if (REG_P (loc))
3018 var_reg_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
3019 set_src);
3020 else
3021 var_mem_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
3022 set_src);
3023
3024 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3025 }
3026 break;
3027
3028 case MO_COPY:
3029 {
3030 rtx loc = VTI (bb)->mos[i].u.loc;
3031 enum var_init_status src_status;
3032 rtx set_src = NULL;
3033
3034 if (GET_CODE (loc) == SET)
3035 {
3036 set_src = SET_SRC (loc);
3037 loc = SET_DEST (loc);
3038 }
3039
3040 src_status = find_src_status (&set, set_src);
3041 set_src = find_src_set_src (&set, set_src);
3042
3043 if (REG_P (loc))
3044 var_reg_delete_and_set (&set, loc, false, src_status, set_src);
3045 else
3046 var_mem_delete_and_set (&set, loc, false, src_status, set_src);
3047
3048 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3049 }
3050 break;
3051
3052 case MO_USE_NO_VAR:
3053 {
3054 rtx loc = VTI (bb)->mos[i].u.loc;
3055
3056 if (REG_P (loc))
3057 var_reg_delete (&set, loc, false);
3058 else
3059 var_mem_delete (&set, loc, false);
3060
3061 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3062 }
3063 break;
3064
3065 case MO_CLOBBER:
3066 {
3067 rtx loc = VTI (bb)->mos[i].u.loc;
3068
3069 if (REG_P (loc))
3070 var_reg_delete (&set, loc, true);
3071 else
3072 var_mem_delete (&set, loc, true);
3073
3074 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3075 }
3076 break;
3077
3078 case MO_ADJUST:
3079 set.stack_adjust += VTI (bb)->mos[i].u.adjust;
3080 break;
3081 }
3082 }
3083 dataflow_set_destroy (&set);
3084 }
3085
3086 /* Emit notes for the whole function. */
3087
3088 static void
3089 vt_emit_notes (void)
3090 {
3091 basic_block bb;
3092 dataflow_set *last_out;
3093 dataflow_set empty;
3094
3095 gcc_assert (!htab_elements (changed_variables));
3096
3097 /* Enable emitting notes by functions (mainly by set_variable_part and
3098 delete_variable_part). */
3099 emit_notes = true;
3100
3101 dataflow_set_init (&empty, 7);
3102 last_out = &empty;
3103
3104 FOR_EACH_BB (bb)
3105 {
3106 /* Emit the notes for changes of variable locations between two
3107 subsequent basic blocks. */
3108 emit_notes_for_differences (BB_HEAD (bb), last_out, &VTI (bb)->in);
3109
3110 /* Emit the notes for the changes in the basic block itself. */
3111 emit_notes_in_bb (bb);
3112
3113 last_out = &VTI (bb)->out;
3114 }
3115 dataflow_set_destroy (&empty);
3116 emit_notes = false;
3117 }
3118
3119 /* If there is a declaration and offset associated with register/memory RTL
3120 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
3121
3122 static bool
3123 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
3124 {
3125 if (REG_P (rtl))
3126 {
3127 if (REG_ATTRS (rtl))
3128 {
3129 *declp = REG_EXPR (rtl);
3130 *offsetp = REG_OFFSET (rtl);
3131 return true;
3132 }
3133 }
3134 else if (MEM_P (rtl))
3135 {
3136 if (MEM_ATTRS (rtl))
3137 {
3138 *declp = MEM_EXPR (rtl);
3139 *offsetp = INT_MEM_OFFSET (rtl);
3140 return true;
3141 }
3142 }
3143 return false;
3144 }
3145
3146 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3147
3148 static void
3149 vt_add_function_parameters (void)
3150 {
3151 tree parm;
3152
3153 for (parm = DECL_ARGUMENTS (current_function_decl);
3154 parm; parm = TREE_CHAIN (parm))
3155 {
3156 rtx decl_rtl = DECL_RTL_IF_SET (parm);
3157 rtx incoming = DECL_INCOMING_RTL (parm);
3158 tree decl;
3159 enum machine_mode mode;
3160 HOST_WIDE_INT offset;
3161 dataflow_set *out;
3162
3163 if (TREE_CODE (parm) != PARM_DECL)
3164 continue;
3165
3166 if (!DECL_NAME (parm))
3167 continue;
3168
3169 if (!decl_rtl || !incoming)
3170 continue;
3171
3172 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
3173 continue;
3174
3175 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
3176 {
3177 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
3178 continue;
3179 offset += byte_lowpart_offset (GET_MODE (incoming),
3180 GET_MODE (decl_rtl));
3181 }
3182
3183 if (!decl)
3184 continue;
3185
3186 if (parm != decl)
3187 {
3188 /* Assume that DECL_RTL was a pseudo that got spilled to
3189 memory. The spill slot sharing code will force the
3190 memory to reference spill_slot_decl (%sfp), so we don't
3191 match above. That's ok, the pseudo must have referenced
3192 the entire parameter, so just reset OFFSET. */
3193 gcc_assert (decl == get_spill_slot_decl (false));
3194 offset = 0;
3195 }
3196
3197 if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
3198 continue;
3199
3200 out = &VTI (ENTRY_BLOCK_PTR)->out;
3201
3202 if (REG_P (incoming))
3203 {
3204 incoming = var_lowpart (mode, incoming);
3205 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
3206 attrs_list_insert (&out->regs[REGNO (incoming)],
3207 parm, offset, incoming);
3208 set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
3209 NULL);
3210 }
3211 else if (MEM_P (incoming))
3212 {
3213 incoming = var_lowpart (mode, incoming);
3214 set_variable_part (out, incoming, parm, offset,
3215 VAR_INIT_STATUS_INITIALIZED, NULL);
3216 }
3217 }
3218 }
3219
3220 /* Allocate and initialize the data structures for variable tracking
3221 and parse the RTL to get the micro operations. */
3222
3223 static void
3224 vt_initialize (void)
3225 {
3226 basic_block bb;
3227
3228 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
3229
3230 FOR_EACH_BB (bb)
3231 {
3232 rtx insn;
3233 HOST_WIDE_INT pre, post = 0;
3234
3235 /* Count the number of micro operations. */
3236 VTI (bb)->n_mos = 0;
3237 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3238 insn = NEXT_INSN (insn))
3239 {
3240 if (INSN_P (insn))
3241 {
3242 if (!frame_pointer_needed)
3243 {
3244 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3245 if (pre)
3246 VTI (bb)->n_mos++;
3247 if (post)
3248 VTI (bb)->n_mos++;
3249 }
3250 note_uses (&PATTERN (insn), count_uses_1, insn);
3251 note_stores (PATTERN (insn), count_stores, insn);
3252 if (CALL_P (insn))
3253 VTI (bb)->n_mos++;
3254 }
3255 }
3256
3257 /* Add the micro-operations to the array. */
3258 VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos);
3259 VTI (bb)->n_mos = 0;
3260 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3261 insn = NEXT_INSN (insn))
3262 {
3263 if (INSN_P (insn))
3264 {
3265 int n1, n2;
3266
3267 if (!frame_pointer_needed)
3268 {
3269 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3270 if (pre)
3271 {
3272 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3273
3274 mo->type = MO_ADJUST;
3275 mo->u.adjust = pre;
3276 mo->insn = insn;
3277 }
3278 }
3279
3280 n1 = VTI (bb)->n_mos;
3281 note_uses (&PATTERN (insn), add_uses_1, insn);
3282 n2 = VTI (bb)->n_mos - 1;
3283
3284 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
3285 while (n1 < n2)
3286 {
3287 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
3288 n1++;
3289 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR)
3290 n2--;
3291 if (n1 < n2)
3292 {
3293 micro_operation sw;
3294
3295 sw = VTI (bb)->mos[n1];
3296 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3297 VTI (bb)->mos[n2] = sw;
3298 }
3299 }
3300
3301 if (CALL_P (insn))
3302 {
3303 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3304
3305 mo->type = MO_CALL;
3306 mo->insn = insn;
3307 }
3308
3309 n1 = VTI (bb)->n_mos;
3310 /* This will record NEXT_INSN (insn), such that we can
3311 insert notes before it without worrying about any
3312 notes that MO_USEs might emit after the insn. */
3313 note_stores (PATTERN (insn), add_stores, insn);
3314 n2 = VTI (bb)->n_mos - 1;
3315
3316 /* Order the MO_CLOBBERs to be before MO_SETs. */
3317 while (n1 < n2)
3318 {
3319 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
3320 n1++;
3321 while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET
3322 || VTI (bb)->mos[n2].type == MO_COPY))
3323 n2--;
3324 if (n1 < n2)
3325 {
3326 micro_operation sw;
3327
3328 sw = VTI (bb)->mos[n1];
3329 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3330 VTI (bb)->mos[n2] = sw;
3331 }
3332 }
3333
3334 if (!frame_pointer_needed && post)
3335 {
3336 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3337
3338 mo->type = MO_ADJUST;
3339 mo->u.adjust = post;
3340 mo->insn = insn;
3341 }
3342 }
3343 }
3344 }
3345
3346 /* Init the IN and OUT sets. */
3347 FOR_ALL_BB (bb)
3348 {
3349 VTI (bb)->visited = false;
3350 dataflow_set_init (&VTI (bb)->in, 7);
3351 dataflow_set_init (&VTI (bb)->out, 7);
3352 }
3353
3354 attrs_pool = create_alloc_pool ("attrs_def pool",
3355 sizeof (struct attrs_def), 1024);
3356 var_pool = create_alloc_pool ("variable_def pool",
3357 sizeof (struct variable_def), 64);
3358 loc_chain_pool = create_alloc_pool ("location_chain_def pool",
3359 sizeof (struct location_chain_def),
3360 1024);
3361 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
3362 NULL);
3363 vt_add_function_parameters ();
3364 }
3365
3366 /* Free the data structures needed for variable tracking. */
3367
3368 static void
3369 vt_finalize (void)
3370 {
3371 basic_block bb;
3372
3373 FOR_EACH_BB (bb)
3374 {
3375 free (VTI (bb)->mos);
3376 }
3377
3378 FOR_ALL_BB (bb)
3379 {
3380 dataflow_set_destroy (&VTI (bb)->in);
3381 dataflow_set_destroy (&VTI (bb)->out);
3382 }
3383 free_aux_for_blocks ();
3384 free_alloc_pool (attrs_pool);
3385 free_alloc_pool (var_pool);
3386 free_alloc_pool (loc_chain_pool);
3387 htab_delete (changed_variables);
3388 }
3389
3390 /* The entry point to variable tracking pass. */
3391
3392 unsigned int
3393 variable_tracking_main (void)
3394 {
3395 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
3396 return 0;
3397
3398 mark_dfs_back_edges ();
3399 vt_initialize ();
3400 if (!frame_pointer_needed)
3401 {
3402 if (!vt_stack_adjustments ())
3403 {
3404 vt_finalize ();
3405 return 0;
3406 }
3407 }
3408
3409 vt_find_locations ();
3410 vt_emit_notes ();
3411
3412 if (dump_file && (dump_flags & TDF_DETAILS))
3413 {
3414 dump_dataflow_sets ();
3415 dump_flow_info (dump_file, dump_flags);
3416 }
3417
3418 vt_finalize ();
3419 return 0;
3420 }
3421 \f
3422 static bool
3423 gate_handle_var_tracking (void)
3424 {
3425 return (flag_var_tracking);
3426 }
3427
3428
3429
3430 struct rtl_opt_pass pass_variable_tracking =
3431 {
3432 {
3433 RTL_PASS,
3434 "vartrack", /* name */
3435 gate_handle_var_tracking, /* gate */
3436 variable_tracking_main, /* execute */
3437 NULL, /* sub */
3438 NULL, /* next */
3439 0, /* static_pass_number */
3440 TV_VAR_TRACKING, /* tv_id */
3441 0, /* properties_required */
3442 0, /* properties_provided */
3443 0, /* properties_destroyed */
3444 0, /* todo_flags_start */
3445 TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */
3446 }
3447 };