PR c++/30897
[official-gcc.git] / gcc / var-tracking.c
blob9599b5aac7b768f4296a09caba6873926c14d629
1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This file contains the variable tracking pass. It computes where
21 variables are located (which registers or where in memory) at each position
22 in instruction stream and emits notes describing the locations.
23 Debug information (DWARF2 location lists) is finally generated from
24 these notes.
25 With this debug information, it is possible to show variables
26 even when debugging optimized code.
28 How does the variable tracking pass work?
30 First, it scans RTL code for uses, stores and clobbers (register/memory
31 references in instructions), for call insns and for stack adjustments
32 separately for each basic block and saves them to an array of micro
33 operations.
34 The micro operations of one instruction are ordered so that
35 pre-modifying stack adjustment < use < use with no var < call insn <
36 < set < clobber < post-modifying stack adjustment
38 Then, a forward dataflow analysis is performed to find out how locations
39 of variables change through code and to propagate the variable locations
40 along control flow graph.
41 The IN set for basic block BB is computed as a union of OUT sets of BB's
42 predecessors, the OUT set for BB is copied from the IN set for BB and
43 is changed according to micro operations in BB.
45 The IN and OUT sets for basic blocks consist of a current stack adjustment
46 (used for adjusting offset of variables addressed using stack pointer),
47 the table of structures describing the locations of parts of a variable
48 and for each physical register a linked list for each physical register.
49 The linked list is a list of variable parts stored in the register,
50 i.e. it is a list of triplets (reg, decl, offset) where decl is
51 REG_EXPR (reg) and offset is REG_OFFSET (reg). The linked list is used for
52 effective deleting appropriate variable parts when we set or clobber the
53 register.
55 There may be more than one variable part in a register. The linked lists
56 should be pretty short so it is a good data structure here.
57 For example in the following code, register allocator may assign same
58 register to variables A and B, and both of them are stored in the same
59 register in CODE:
61 if (cond)
62 set A;
63 else
64 set B;
65 CODE;
66 if (cond)
67 use A;
68 else
69 use B;
71 Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
72 are emitted to appropriate positions in RTL code. Each such a note describes
73 the location of one variable at the point in instruction stream where the
74 note is. There is no need to emit a note for each variable before each
75 instruction, we only emit these notes where the location of variable changes
76 (this means that we also emit notes for changes between the OUT set of the
77 previous block and the IN set of the current block).
79 The notes consist of two parts:
80 1. the declaration (from REG_EXPR or MEM_EXPR)
81 2. the location of a variable - it is either a simple register/memory
82 reference (for simple variables, for example int),
83 or a parallel of register/memory references (for a large variables
84 which consist of several parts, for example long long).
88 #include "config.h"
89 #include "system.h"
90 #include "coretypes.h"
91 #include "tm.h"
92 #include "rtl.h"
93 #include "tree.h"
94 #include "hard-reg-set.h"
95 #include "basic-block.h"
96 #include "flags.h"
97 #include "output.h"
98 #include "insn-config.h"
99 #include "reload.h"
100 #include "sbitmap.h"
101 #include "alloc-pool.h"
102 #include "fibheap.h"
103 #include "hashtab.h"
104 #include "regs.h"
105 #include "expr.h"
106 #include "timevar.h"
107 #include "tree-pass.h"
109 /* Type of micro operation. */
110 enum micro_operation_type
112 MO_USE, /* Use location (REG or MEM). */
113 MO_USE_NO_VAR,/* Use location which is not associated with a variable
114 or the variable is not trackable. */
115 MO_SET, /* Set location. */
116 MO_COPY, /* Copy the same portion of a variable from one
117 location to another. */
118 MO_CLOBBER, /* Clobber location. */
119 MO_CALL, /* Call insn. */
120 MO_ADJUST /* Adjust stack pointer. */
123 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
124 enum emit_note_where
126 EMIT_NOTE_BEFORE_INSN,
127 EMIT_NOTE_AFTER_INSN
130 /* Structure holding information about micro operation. */
131 typedef struct micro_operation_def
133 /* Type of micro operation. */
134 enum micro_operation_type type;
136 union {
137 /* Location. For MO_SET and MO_COPY, this is the SET that performs
138 the assignment, if known, otherwise it is the target of the
139 assignment. */
140 rtx loc;
142 /* Stack adjustment. */
143 HOST_WIDE_INT adjust;
144 } u;
146 /* The instruction which the micro operation is in, for MO_USE,
147 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
148 instruction or note in the original flow (before any var-tracking
149 notes are inserted, to simplify emission of notes), for MO_SET
150 and MO_CLOBBER. */
151 rtx insn;
152 } micro_operation;
154 /* Structure for passing some other parameters to function
155 emit_note_insn_var_location. */
156 typedef struct emit_note_data_def
158 /* The instruction which the note will be emitted before/after. */
159 rtx insn;
161 /* Where the note will be emitted (before/after insn)? */
162 enum emit_note_where where;
163 } emit_note_data;
165 /* Description of location of a part of a variable. The content of a physical
166 register is described by a chain of these structures.
167 The chains are pretty short (usually 1 or 2 elements) and thus
168 chain is the best data structure. */
169 typedef struct attrs_def
171 /* Pointer to next member of the list. */
172 struct attrs_def *next;
174 /* The rtx of register. */
175 rtx loc;
177 /* The declaration corresponding to LOC. */
178 tree decl;
180 /* Offset from start of DECL. */
181 HOST_WIDE_INT offset;
182 } *attrs;
184 /* Structure holding the IN or OUT set for a basic block. */
185 typedef struct dataflow_set_def
187 /* Adjustment of stack offset. */
188 HOST_WIDE_INT stack_adjust;
190 /* Attributes for registers (lists of attrs). */
191 attrs regs[FIRST_PSEUDO_REGISTER];
193 /* Variable locations. */
194 htab_t vars;
195 } dataflow_set;
197 /* The structure (one for each basic block) containing the information
198 needed for variable tracking. */
199 typedef struct variable_tracking_info_def
201 /* Number of micro operations stored in the MOS array. */
202 int n_mos;
204 /* The array of micro operations. */
205 micro_operation *mos;
207 /* The IN and OUT set for dataflow analysis. */
208 dataflow_set in;
209 dataflow_set out;
211 /* Has the block been visited in DFS? */
212 bool visited;
213 } *variable_tracking_info;
215 /* Structure for chaining the locations. */
216 typedef struct location_chain_def
218 /* Next element in the chain. */
219 struct location_chain_def *next;
221 /* The location (REG or MEM). */
222 rtx loc;
224 /* The "value" stored in this location. */
225 rtx set_src;
227 /* Initialized? */
228 enum var_init_status init;
229 } *location_chain;
231 /* Structure describing one part of variable. */
232 typedef struct variable_part_def
234 /* Chain of locations of the part. */
235 location_chain loc_chain;
237 /* Location which was last emitted to location list. */
238 rtx cur_loc;
240 /* The offset in the variable. */
241 HOST_WIDE_INT offset;
242 } variable_part;
244 /* Maximum number of location parts. */
245 #define MAX_VAR_PARTS 16
247 /* Structure describing where the variable is located. */
248 typedef struct variable_def
250 /* The declaration of the variable. */
251 tree decl;
253 /* Reference count. */
254 int refcount;
256 /* Number of variable parts. */
257 int n_var_parts;
259 /* The variable parts. */
260 variable_part var_part[MAX_VAR_PARTS];
261 } *variable;
262 typedef const struct variable_def *const_variable;
264 /* Hash function for DECL for VARIABLE_HTAB. */
265 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
267 /* Pointer to the BB's information specific to variable tracking pass. */
268 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
270 /* Alloc pool for struct attrs_def. */
271 static alloc_pool attrs_pool;
273 /* Alloc pool for struct variable_def. */
274 static alloc_pool var_pool;
276 /* Alloc pool for struct location_chain_def. */
277 static alloc_pool loc_chain_pool;
279 /* Changed variables, notes will be emitted for them. */
280 static htab_t changed_variables;
282 /* Shall notes be emitted? */
283 static bool emit_notes;
285 /* Local function prototypes. */
286 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
287 HOST_WIDE_INT *);
288 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
289 HOST_WIDE_INT *);
290 static void bb_stack_adjust_offset (basic_block);
291 static bool vt_stack_adjustments (void);
292 static rtx adjust_stack_reference (rtx, HOST_WIDE_INT);
293 static hashval_t variable_htab_hash (const void *);
294 static int variable_htab_eq (const void *, const void *);
295 static void variable_htab_free (void *);
297 static void init_attrs_list_set (attrs *);
298 static void attrs_list_clear (attrs *);
299 static attrs attrs_list_member (attrs, tree, HOST_WIDE_INT);
300 static void attrs_list_insert (attrs *, tree, HOST_WIDE_INT, rtx);
301 static void attrs_list_copy (attrs *, attrs);
302 static void attrs_list_union (attrs *, attrs);
304 static void vars_clear (htab_t);
305 static variable unshare_variable (dataflow_set *set, variable var,
306 enum var_init_status);
307 static int vars_copy_1 (void **, void *);
308 static void vars_copy (htab_t, htab_t);
309 static tree var_debug_decl (tree);
310 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
311 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
312 enum var_init_status, rtx);
313 static void var_reg_delete (dataflow_set *, rtx, bool);
314 static void var_regno_delete (dataflow_set *, int);
315 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
316 static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
317 enum var_init_status, rtx);
318 static void var_mem_delete (dataflow_set *, rtx, bool);
320 static void dataflow_set_init (dataflow_set *, int);
321 static void dataflow_set_clear (dataflow_set *);
322 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
323 static int variable_union_info_cmp_pos (const void *, const void *);
324 static int variable_union (void **, void *);
325 static void dataflow_set_union (dataflow_set *, dataflow_set *);
326 static bool variable_part_different_p (variable_part *, variable_part *);
327 static bool variable_different_p (variable, variable, bool);
328 static int dataflow_set_different_1 (void **, void *);
329 static int dataflow_set_different_2 (void **, void *);
330 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
331 static void dataflow_set_destroy (dataflow_set *);
333 static bool contains_symbol_ref (rtx);
334 static bool track_expr_p (tree);
335 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
336 static int count_uses (rtx *, void *);
337 static void count_uses_1 (rtx *, void *);
338 static void count_stores (rtx, const_rtx, void *);
339 static int add_uses (rtx *, void *);
340 static void add_uses_1 (rtx *, void *);
341 static void add_stores (rtx, const_rtx, void *);
342 static bool compute_bb_dataflow (basic_block);
343 static void vt_find_locations (void);
345 static void dump_attrs_list (attrs);
346 static int dump_variable (void **, void *);
347 static void dump_vars (htab_t);
348 static void dump_dataflow_set (dataflow_set *);
349 static void dump_dataflow_sets (void);
351 static void variable_was_changed (variable, htab_t);
352 static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
353 enum var_init_status, rtx);
354 static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT,
355 rtx);
356 static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
357 static int emit_note_insn_var_location (void **, void *);
358 static void emit_notes_for_changes (rtx, enum emit_note_where);
359 static int emit_notes_for_differences_1 (void **, void *);
360 static int emit_notes_for_differences_2 (void **, void *);
361 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
362 static void emit_notes_in_bb (basic_block);
363 static void vt_emit_notes (void);
365 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
366 static void vt_add_function_parameters (void);
367 static void vt_initialize (void);
368 static void vt_finalize (void);
370 /* Given a SET, calculate the amount of stack adjustment it contains
371 PRE- and POST-modifying stack pointer.
372 This function is similar to stack_adjust_offset. */
374 static void
375 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
376 HOST_WIDE_INT *post)
378 rtx src = SET_SRC (pattern);
379 rtx dest = SET_DEST (pattern);
380 enum rtx_code code;
382 if (dest == stack_pointer_rtx)
384 /* (set (reg sp) (plus (reg sp) (const_int))) */
385 code = GET_CODE (src);
386 if (! (code == PLUS || code == MINUS)
387 || XEXP (src, 0) != stack_pointer_rtx
388 || GET_CODE (XEXP (src, 1)) != CONST_INT)
389 return;
391 if (code == MINUS)
392 *post += INTVAL (XEXP (src, 1));
393 else
394 *post -= INTVAL (XEXP (src, 1));
396 else if (MEM_P (dest))
398 /* (set (mem (pre_dec (reg sp))) (foo)) */
399 src = XEXP (dest, 0);
400 code = GET_CODE (src);
402 switch (code)
404 case PRE_MODIFY:
405 case POST_MODIFY:
406 if (XEXP (src, 0) == stack_pointer_rtx)
408 rtx val = XEXP (XEXP (src, 1), 1);
409 /* We handle only adjustments by constant amount. */
410 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
411 GET_CODE (val) == CONST_INT);
413 if (code == PRE_MODIFY)
414 *pre -= INTVAL (val);
415 else
416 *post -= INTVAL (val);
417 break;
419 return;
421 case PRE_DEC:
422 if (XEXP (src, 0) == stack_pointer_rtx)
424 *pre += GET_MODE_SIZE (GET_MODE (dest));
425 break;
427 return;
429 case POST_DEC:
430 if (XEXP (src, 0) == stack_pointer_rtx)
432 *post += GET_MODE_SIZE (GET_MODE (dest));
433 break;
435 return;
437 case PRE_INC:
438 if (XEXP (src, 0) == stack_pointer_rtx)
440 *pre -= GET_MODE_SIZE (GET_MODE (dest));
441 break;
443 return;
445 case POST_INC:
446 if (XEXP (src, 0) == stack_pointer_rtx)
448 *post -= GET_MODE_SIZE (GET_MODE (dest));
449 break;
451 return;
453 default:
454 return;
459 /* Given an INSN, calculate the amount of stack adjustment it contains
460 PRE- and POST-modifying stack pointer. */
462 static void
463 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
464 HOST_WIDE_INT *post)
466 *pre = 0;
467 *post = 0;
469 if (GET_CODE (PATTERN (insn)) == SET)
470 stack_adjust_offset_pre_post (PATTERN (insn), pre, post);
471 else if (GET_CODE (PATTERN (insn)) == PARALLEL
472 || GET_CODE (PATTERN (insn)) == SEQUENCE)
474 int i;
476 /* There may be stack adjustments inside compound insns. Search
477 for them. */
478 for ( i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
479 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
480 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn), 0, i),
481 pre, post);
485 /* Compute stack adjustment in basic block BB. */
487 static void
488 bb_stack_adjust_offset (basic_block bb)
490 HOST_WIDE_INT offset;
491 int i;
493 offset = VTI (bb)->in.stack_adjust;
494 for (i = 0; i < VTI (bb)->n_mos; i++)
496 if (VTI (bb)->mos[i].type == MO_ADJUST)
497 offset += VTI (bb)->mos[i].u.adjust;
498 else if (VTI (bb)->mos[i].type != MO_CALL)
500 if (MEM_P (VTI (bb)->mos[i].u.loc))
502 VTI (bb)->mos[i].u.loc
503 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
507 VTI (bb)->out.stack_adjust = offset;
510 /* Compute stack adjustments for all blocks by traversing DFS tree.
511 Return true when the adjustments on all incoming edges are consistent.
512 Heavily borrowed from pre_and_rev_post_order_compute. */
514 static bool
515 vt_stack_adjustments (void)
517 edge_iterator *stack;
518 int sp;
520 /* Initialize entry block. */
521 VTI (ENTRY_BLOCK_PTR)->visited = true;
522 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
524 /* Allocate stack for back-tracking up CFG. */
525 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
526 sp = 0;
528 /* Push the first edge on to the stack. */
529 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
531 while (sp)
533 edge_iterator ei;
534 basic_block src;
535 basic_block dest;
537 /* Look at the edge on the top of the stack. */
538 ei = stack[sp - 1];
539 src = ei_edge (ei)->src;
540 dest = ei_edge (ei)->dest;
542 /* Check if the edge destination has been visited yet. */
543 if (!VTI (dest)->visited)
545 VTI (dest)->visited = true;
546 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
547 bb_stack_adjust_offset (dest);
549 if (EDGE_COUNT (dest->succs) > 0)
550 /* Since the DEST node has been visited for the first
551 time, check its successors. */
552 stack[sp++] = ei_start (dest->succs);
554 else
556 /* Check whether the adjustments on the edges are the same. */
557 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
559 free (stack);
560 return false;
563 if (! ei_one_before_end_p (ei))
564 /* Go to the next edge. */
565 ei_next (&stack[sp - 1]);
566 else
567 /* Return to previous level if there are no more edges. */
568 sp--;
572 free (stack);
573 return true;
576 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
577 to the argument pointer. Return the new rtx. */
579 static rtx
580 adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
582 rtx addr, cfa, tmp;
584 #ifdef FRAME_POINTER_CFA_OFFSET
585 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
586 cfa = plus_constant (frame_pointer_rtx, adjustment);
587 #else
588 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
589 cfa = plus_constant (arg_pointer_rtx, adjustment);
590 #endif
592 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
593 tmp = simplify_rtx (addr);
594 if (tmp)
595 addr = tmp;
597 return replace_equiv_address_nv (mem, addr);
600 /* The hash function for variable_htab, computes the hash value
601 from the declaration of variable X. */
603 static hashval_t
604 variable_htab_hash (const void *x)
606 const_variable const v = (const_variable) x;
608 return (VARIABLE_HASH_VAL (v->decl));
611 /* Compare the declaration of variable X with declaration Y. */
613 static int
614 variable_htab_eq (const void *x, const void *y)
616 const_variable const v = (const_variable) x;
617 const_tree const decl = (const_tree) y;
619 return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
622 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
624 static void
625 variable_htab_free (void *elem)
627 int i;
628 variable var = (variable) elem;
629 location_chain node, next;
631 gcc_assert (var->refcount > 0);
633 var->refcount--;
634 if (var->refcount > 0)
635 return;
637 for (i = 0; i < var->n_var_parts; i++)
639 for (node = var->var_part[i].loc_chain; node; node = next)
641 next = node->next;
642 pool_free (loc_chain_pool, node);
644 var->var_part[i].loc_chain = NULL;
646 pool_free (var_pool, var);
649 /* Initialize the set (array) SET of attrs to empty lists. */
651 static void
652 init_attrs_list_set (attrs *set)
654 int i;
656 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
657 set[i] = NULL;
660 /* Make the list *LISTP empty. */
662 static void
663 attrs_list_clear (attrs *listp)
665 attrs list, next;
667 for (list = *listp; list; list = next)
669 next = list->next;
670 pool_free (attrs_pool, list);
672 *listp = NULL;
675 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
677 static attrs
678 attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset)
680 for (; list; list = list->next)
681 if (list->decl == decl && list->offset == offset)
682 return list;
683 return NULL;
686 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
688 static void
689 attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc)
691 attrs list;
693 list = pool_alloc (attrs_pool);
694 list->loc = loc;
695 list->decl = decl;
696 list->offset = offset;
697 list->next = *listp;
698 *listp = list;
701 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
703 static void
704 attrs_list_copy (attrs *dstp, attrs src)
706 attrs n;
708 attrs_list_clear (dstp);
709 for (; src; src = src->next)
711 n = pool_alloc (attrs_pool);
712 n->loc = src->loc;
713 n->decl = src->decl;
714 n->offset = src->offset;
715 n->next = *dstp;
716 *dstp = n;
720 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
722 static void
723 attrs_list_union (attrs *dstp, attrs src)
725 for (; src; src = src->next)
727 if (!attrs_list_member (*dstp, src->decl, src->offset))
728 attrs_list_insert (dstp, src->decl, src->offset, src->loc);
732 /* Delete all variables from hash table VARS. */
734 static void
735 vars_clear (htab_t vars)
737 htab_empty (vars);
740 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
742 static variable
743 unshare_variable (dataflow_set *set, variable var,
744 enum var_init_status initialized)
746 void **slot;
747 variable new_var;
748 int i;
750 new_var = pool_alloc (var_pool);
751 new_var->decl = var->decl;
752 new_var->refcount = 1;
753 var->refcount--;
754 new_var->n_var_parts = var->n_var_parts;
756 for (i = 0; i < var->n_var_parts; i++)
758 location_chain node;
759 location_chain *nextp;
761 new_var->var_part[i].offset = var->var_part[i].offset;
762 nextp = &new_var->var_part[i].loc_chain;
763 for (node = var->var_part[i].loc_chain; node; node = node->next)
765 location_chain new_lc;
767 new_lc = pool_alloc (loc_chain_pool);
768 new_lc->next = NULL;
769 if (node->init > initialized)
770 new_lc->init = node->init;
771 else
772 new_lc->init = initialized;
773 if (node->set_src && !(MEM_P (node->set_src)))
774 new_lc->set_src = node->set_src;
775 else
776 new_lc->set_src = NULL;
777 new_lc->loc = node->loc;
779 *nextp = new_lc;
780 nextp = &new_lc->next;
783 /* We are at the basic block boundary when copying variable description
784 so set the CUR_LOC to be the first element of the chain. */
785 if (new_var->var_part[i].loc_chain)
786 new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
787 else
788 new_var->var_part[i].cur_loc = NULL;
791 slot = htab_find_slot_with_hash (set->vars, new_var->decl,
792 VARIABLE_HASH_VAL (new_var->decl),
793 INSERT);
794 *slot = new_var;
795 return new_var;
798 /* Add a variable from *SLOT to hash table DATA and increase its reference
799 count. */
801 static int
802 vars_copy_1 (void **slot, void *data)
804 htab_t dst = (htab_t) data;
805 variable src, *dstp;
807 src = *(variable *) slot;
808 src->refcount++;
810 dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
811 VARIABLE_HASH_VAL (src->decl),
812 INSERT);
813 *dstp = src;
815 /* Continue traversing the hash table. */
816 return 1;
819 /* Copy all variables from hash table SRC to hash table DST. */
821 static void
822 vars_copy (htab_t dst, htab_t src)
824 vars_clear (dst);
825 htab_traverse (src, vars_copy_1, dst);
828 /* Map a decl to its main debug decl. */
830 static inline tree
831 var_debug_decl (tree decl)
833 if (decl && DECL_P (decl)
834 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
835 && DECL_P (DECL_DEBUG_EXPR (decl)))
836 decl = DECL_DEBUG_EXPR (decl);
838 return decl;
841 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
843 static void
844 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
845 rtx set_src)
847 tree decl = REG_EXPR (loc);
848 HOST_WIDE_INT offset = REG_OFFSET (loc);
849 attrs node;
851 decl = var_debug_decl (decl);
853 for (node = set->regs[REGNO (loc)]; node; node = node->next)
854 if (node->decl == decl && node->offset == offset)
855 break;
856 if (!node)
857 attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
858 set_variable_part (set, loc, decl, offset, initialized, set_src);
861 static int
862 get_init_value (dataflow_set *set, rtx loc, tree decl)
864 void **slot;
865 variable var;
866 int i;
867 int ret_val = VAR_INIT_STATUS_UNKNOWN;
869 if (! flag_var_tracking_uninit)
870 return VAR_INIT_STATUS_INITIALIZED;
872 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
873 NO_INSERT);
874 if (slot)
876 var = * (variable *) slot;
877 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
879 location_chain nextp;
880 for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
881 if (rtx_equal_p (nextp->loc, loc))
883 ret_val = nextp->init;
884 break;
889 return ret_val;
892 /* Delete current content of register LOC in dataflow set SET and set
893 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
894 MODIFY is true, any other live copies of the same variable part are
895 also deleted from the dataflow set, otherwise the variable part is
896 assumed to be copied from another location holding the same
897 part. */
899 static void
900 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
901 enum var_init_status initialized, rtx set_src)
903 tree decl = REG_EXPR (loc);
904 HOST_WIDE_INT offset = REG_OFFSET (loc);
905 attrs node, next;
906 attrs *nextp;
908 decl = var_debug_decl (decl);
910 if (initialized == VAR_INIT_STATUS_UNKNOWN)
911 initialized = get_init_value (set, loc, decl);
913 nextp = &set->regs[REGNO (loc)];
914 for (node = *nextp; node; node = next)
916 next = node->next;
917 if (node->decl != decl || node->offset != offset)
919 delete_variable_part (set, node->loc, node->decl, node->offset);
920 pool_free (attrs_pool, node);
921 *nextp = next;
923 else
925 node->loc = loc;
926 nextp = &node->next;
929 if (modify)
930 clobber_variable_part (set, loc, decl, offset, set_src);
931 var_reg_set (set, loc, initialized, set_src);
934 /* Delete current content of register LOC in dataflow set SET. If
935 CLOBBER is true, also delete any other live copies of the same
936 variable part. */
938 static void
939 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
941 attrs *reg = &set->regs[REGNO (loc)];
942 attrs node, next;
944 if (clobber)
946 tree decl = REG_EXPR (loc);
947 HOST_WIDE_INT offset = REG_OFFSET (loc);
949 decl = var_debug_decl (decl);
951 clobber_variable_part (set, NULL, decl, offset, NULL);
954 for (node = *reg; node; node = next)
956 next = node->next;
957 delete_variable_part (set, node->loc, node->decl, node->offset);
958 pool_free (attrs_pool, node);
960 *reg = NULL;
963 /* Delete content of register with number REGNO in dataflow set SET. */
965 static void
966 var_regno_delete (dataflow_set *set, int regno)
968 attrs *reg = &set->regs[regno];
969 attrs node, next;
971 for (node = *reg; node; node = next)
973 next = node->next;
974 delete_variable_part (set, node->loc, node->decl, node->offset);
975 pool_free (attrs_pool, node);
977 *reg = NULL;
980 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
981 SET to LOC.
982 Adjust the address first if it is stack pointer based. */
984 static void
985 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
986 rtx set_src)
988 tree decl = MEM_EXPR (loc);
989 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
991 decl = var_debug_decl (decl);
993 set_variable_part (set, loc, decl, offset, initialized, set_src);
996 /* Delete and set the location part of variable MEM_EXPR (LOC) in
997 dataflow set SET to LOC. If MODIFY is true, any other live copies
998 of the same variable part are also deleted from the dataflow set,
999 otherwise the variable part is assumed to be copied from another
1000 location holding the same part.
1001 Adjust the address first if it is stack pointer based. */
1003 static void
1004 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1005 enum var_init_status initialized, rtx set_src)
1007 tree decl = MEM_EXPR (loc);
1008 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
1010 decl = var_debug_decl (decl);
1012 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1013 initialized = get_init_value (set, loc, decl);
1015 if (modify)
1016 clobber_variable_part (set, NULL, decl, offset, set_src);
1017 var_mem_set (set, loc, initialized, set_src);
1020 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
1021 true, also delete any other live copies of the same variable part.
1022 Adjust the address first if it is stack pointer based. */
1024 static void
1025 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1027 tree decl = MEM_EXPR (loc);
1028 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
1030 decl = var_debug_decl (decl);
1031 if (clobber)
1032 clobber_variable_part (set, NULL, decl, offset, NULL);
1033 delete_variable_part (set, loc, decl, offset);
1036 /* Initialize dataflow set SET to be empty.
1037 VARS_SIZE is the initial size of hash table VARS. */
1039 static void
1040 dataflow_set_init (dataflow_set *set, int vars_size)
1042 init_attrs_list_set (set->regs);
1043 set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq,
1044 variable_htab_free);
1045 set->stack_adjust = 0;
1048 /* Delete the contents of dataflow set SET. */
1050 static void
1051 dataflow_set_clear (dataflow_set *set)
1053 int i;
1055 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1056 attrs_list_clear (&set->regs[i]);
1058 vars_clear (set->vars);
1061 /* Copy the contents of dataflow set SRC to DST. */
1063 static void
1064 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1066 int i;
1068 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1069 attrs_list_copy (&dst->regs[i], src->regs[i]);
1071 vars_copy (dst->vars, src->vars);
1072 dst->stack_adjust = src->stack_adjust;
1075 /* Information for merging lists of locations for a given offset of variable.
1077 struct variable_union_info
1079 /* Node of the location chain. */
1080 location_chain lc;
1082 /* The sum of positions in the input chains. */
1083 int pos;
1085 /* The position in the chains of SRC and DST dataflow sets. */
1086 int pos_src;
1087 int pos_dst;
1090 /* Compare function for qsort, order the structures by POS element. */
1092 static int
1093 variable_union_info_cmp_pos (const void *n1, const void *n2)
1095 const struct variable_union_info *i1 = n1;
1096 const struct variable_union_info *i2 = n2;
1098 if (i1->pos != i2->pos)
1099 return i1->pos - i2->pos;
1101 return (i1->pos_dst - i2->pos_dst);
1104 /* Compute union of location parts of variable *SLOT and the same variable
1105 from hash table DATA. Compute "sorted" union of the location chains
1106 for common offsets, i.e. the locations of a variable part are sorted by
1107 a priority where the priority is the sum of the positions in the 2 chains
1108 (if a location is only in one list the position in the second list is
1109 defined to be larger than the length of the chains).
1110 When we are updating the location parts the newest location is in the
1111 beginning of the chain, so when we do the described "sorted" union
1112 we keep the newest locations in the beginning. */
1114 static int
1115 variable_union (void **slot, void *data)
1117 variable src, dst, *dstp;
1118 dataflow_set *set = (dataflow_set *) data;
1119 int i, j, k;
1121 src = *(variable *) slot;
1122 dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl,
1123 VARIABLE_HASH_VAL (src->decl),
1124 INSERT);
1125 if (!*dstp)
1127 src->refcount++;
1129 /* If CUR_LOC of some variable part is not the first element of
1130 the location chain we are going to change it so we have to make
1131 a copy of the variable. */
1132 for (k = 0; k < src->n_var_parts; k++)
1134 gcc_assert (!src->var_part[k].loc_chain
1135 == !src->var_part[k].cur_loc);
1136 if (src->var_part[k].loc_chain)
1138 gcc_assert (src->var_part[k].cur_loc);
1139 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
1140 break;
1143 if (k < src->n_var_parts)
1145 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1147 if (! flag_var_tracking_uninit)
1148 status = VAR_INIT_STATUS_INITIALIZED;
1150 unshare_variable (set, src, status);
1152 else
1153 *dstp = src;
1155 /* Continue traversing the hash table. */
1156 return 1;
1158 else
1159 dst = *dstp;
1161 gcc_assert (src->n_var_parts);
1163 /* Count the number of location parts, result is K. */
1164 for (i = 0, j = 0, k = 0;
1165 i < src->n_var_parts && j < dst->n_var_parts; k++)
1167 if (src->var_part[i].offset == dst->var_part[j].offset)
1169 i++;
1170 j++;
1172 else if (src->var_part[i].offset < dst->var_part[j].offset)
1173 i++;
1174 else
1175 j++;
1177 k += src->n_var_parts - i;
1178 k += dst->n_var_parts - j;
1180 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1181 thus there are at most MAX_VAR_PARTS different offsets. */
1182 gcc_assert (k <= MAX_VAR_PARTS);
1184 if (dst->refcount > 1 && dst->n_var_parts != k)
1186 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1188 if (! flag_var_tracking_uninit)
1189 status = VAR_INIT_STATUS_INITIALIZED;
1190 dst = unshare_variable (set, dst, status);
1193 i = src->n_var_parts - 1;
1194 j = dst->n_var_parts - 1;
1195 dst->n_var_parts = k;
1197 for (k--; k >= 0; k--)
1199 location_chain node, node2;
1201 if (i >= 0 && j >= 0
1202 && src->var_part[i].offset == dst->var_part[j].offset)
1204 /* Compute the "sorted" union of the chains, i.e. the locations which
1205 are in both chains go first, they are sorted by the sum of
1206 positions in the chains. */
1207 int dst_l, src_l;
1208 int ii, jj, n;
1209 struct variable_union_info *vui;
1211 /* If DST is shared compare the location chains.
1212 If they are different we will modify the chain in DST with
1213 high probability so make a copy of DST. */
1214 if (dst->refcount > 1)
1216 for (node = src->var_part[i].loc_chain,
1217 node2 = dst->var_part[j].loc_chain; node && node2;
1218 node = node->next, node2 = node2->next)
1220 if (!((REG_P (node2->loc)
1221 && REG_P (node->loc)
1222 && REGNO (node2->loc) == REGNO (node->loc))
1223 || rtx_equal_p (node2->loc, node->loc)))
1225 if (node2->init < node->init)
1226 node2->init = node->init;
1227 break;
1230 if (node || node2)
1231 dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
1234 src_l = 0;
1235 for (node = src->var_part[i].loc_chain; node; node = node->next)
1236 src_l++;
1237 dst_l = 0;
1238 for (node = dst->var_part[j].loc_chain; node; node = node->next)
1239 dst_l++;
1240 vui = XCNEWVEC (struct variable_union_info, src_l + dst_l);
1242 /* Fill in the locations from DST. */
1243 for (node = dst->var_part[j].loc_chain, jj = 0; node;
1244 node = node->next, jj++)
1246 vui[jj].lc = node;
1247 vui[jj].pos_dst = jj;
1249 /* Value larger than a sum of 2 valid positions. */
1250 vui[jj].pos_src = src_l + dst_l;
1253 /* Fill in the locations from SRC. */
1254 n = dst_l;
1255 for (node = src->var_part[i].loc_chain, ii = 0; node;
1256 node = node->next, ii++)
1258 /* Find location from NODE. */
1259 for (jj = 0; jj < dst_l; jj++)
1261 if ((REG_P (vui[jj].lc->loc)
1262 && REG_P (node->loc)
1263 && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
1264 || rtx_equal_p (vui[jj].lc->loc, node->loc))
1266 vui[jj].pos_src = ii;
1267 break;
1270 if (jj >= dst_l) /* The location has not been found. */
1272 location_chain new_node;
1274 /* Copy the location from SRC. */
1275 new_node = pool_alloc (loc_chain_pool);
1276 new_node->loc = node->loc;
1277 new_node->init = node->init;
1278 if (!node->set_src || MEM_P (node->set_src))
1279 new_node->set_src = NULL;
1280 else
1281 new_node->set_src = node->set_src;
1282 vui[n].lc = new_node;
1283 vui[n].pos_src = ii;
1284 vui[n].pos_dst = src_l + dst_l;
1285 n++;
1289 for (ii = 0; ii < src_l + dst_l; ii++)
1290 vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst;
1292 qsort (vui, n, sizeof (struct variable_union_info),
1293 variable_union_info_cmp_pos);
1295 /* Reconnect the nodes in sorted order. */
1296 for (ii = 1; ii < n; ii++)
1297 vui[ii - 1].lc->next = vui[ii].lc;
1298 vui[n - 1].lc->next = NULL;
1300 dst->var_part[k].loc_chain = vui[0].lc;
1301 dst->var_part[k].offset = dst->var_part[j].offset;
1303 free (vui);
1304 i--;
1305 j--;
1307 else if ((i >= 0 && j >= 0
1308 && src->var_part[i].offset < dst->var_part[j].offset)
1309 || i < 0)
1311 dst->var_part[k] = dst->var_part[j];
1312 j--;
1314 else if ((i >= 0 && j >= 0
1315 && src->var_part[i].offset > dst->var_part[j].offset)
1316 || j < 0)
1318 location_chain *nextp;
1320 /* Copy the chain from SRC. */
1321 nextp = &dst->var_part[k].loc_chain;
1322 for (node = src->var_part[i].loc_chain; node; node = node->next)
1324 location_chain new_lc;
1326 new_lc = pool_alloc (loc_chain_pool);
1327 new_lc->next = NULL;
1328 new_lc->init = node->init;
1329 if (!node->set_src || MEM_P (node->set_src))
1330 new_lc->set_src = NULL;
1331 else
1332 new_lc->set_src = node->set_src;
1333 new_lc->loc = node->loc;
1335 *nextp = new_lc;
1336 nextp = &new_lc->next;
1339 dst->var_part[k].offset = src->var_part[i].offset;
1340 i--;
1343 /* We are at the basic block boundary when computing union
1344 so set the CUR_LOC to be the first element of the chain. */
1345 if (dst->var_part[k].loc_chain)
1346 dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc;
1347 else
1348 dst->var_part[k].cur_loc = NULL;
1351 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
1353 location_chain node, node2;
1354 for (node = src->var_part[i].loc_chain; node; node = node->next)
1355 for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
1356 if (rtx_equal_p (node->loc, node2->loc))
1358 if (node->init > node2->init)
1359 node2->init = node->init;
1363 /* Continue traversing the hash table. */
1364 return 1;
1367 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1369 static void
1370 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
1372 int i;
1374 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1375 attrs_list_union (&dst->regs[i], src->regs[i]);
1377 htab_traverse (src->vars, variable_union, dst);
1380 /* Flag whether two dataflow sets being compared contain different data. */
1381 static bool
1382 dataflow_set_different_value;
1384 static bool
1385 variable_part_different_p (variable_part *vp1, variable_part *vp2)
1387 location_chain lc1, lc2;
1389 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
1391 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
1393 if (REG_P (lc1->loc) && REG_P (lc2->loc))
1395 if (REGNO (lc1->loc) == REGNO (lc2->loc))
1396 break;
1398 if (rtx_equal_p (lc1->loc, lc2->loc))
1399 break;
1401 if (!lc2)
1402 return true;
1404 return false;
1407 /* Return true if variables VAR1 and VAR2 are different.
1408 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1409 variable part. */
1411 static bool
1412 variable_different_p (variable var1, variable var2,
1413 bool compare_current_location)
1415 int i;
1417 if (var1 == var2)
1418 return false;
1420 if (var1->n_var_parts != var2->n_var_parts)
1421 return true;
1423 for (i = 0; i < var1->n_var_parts; i++)
1425 if (var1->var_part[i].offset != var2->var_part[i].offset)
1426 return true;
1427 if (compare_current_location)
1429 if (!((REG_P (var1->var_part[i].cur_loc)
1430 && REG_P (var2->var_part[i].cur_loc)
1431 && (REGNO (var1->var_part[i].cur_loc)
1432 == REGNO (var2->var_part[i].cur_loc)))
1433 || rtx_equal_p (var1->var_part[i].cur_loc,
1434 var2->var_part[i].cur_loc)))
1435 return true;
1437 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
1438 return true;
1439 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
1440 return true;
1442 return false;
1445 /* Compare variable *SLOT with the same variable in hash table DATA
1446 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1448 static int
1449 dataflow_set_different_1 (void **slot, void *data)
1451 htab_t htab = (htab_t) data;
1452 variable var1, var2;
1454 var1 = *(variable *) slot;
1455 var2 = htab_find_with_hash (htab, var1->decl,
1456 VARIABLE_HASH_VAL (var1->decl));
1457 if (!var2)
1459 dataflow_set_different_value = true;
1461 /* Stop traversing the hash table. */
1462 return 0;
1465 if (variable_different_p (var1, var2, false))
1467 dataflow_set_different_value = true;
1469 /* Stop traversing the hash table. */
1470 return 0;
1473 /* Continue traversing the hash table. */
1474 return 1;
1477 /* Compare variable *SLOT with the same variable in hash table DATA
1478 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1480 static int
1481 dataflow_set_different_2 (void **slot, void *data)
1483 htab_t htab = (htab_t) data;
1484 variable var1, var2;
1486 var1 = *(variable *) slot;
1487 var2 = htab_find_with_hash (htab, var1->decl,
1488 VARIABLE_HASH_VAL (var1->decl));
1489 if (!var2)
1491 dataflow_set_different_value = true;
1493 /* Stop traversing the hash table. */
1494 return 0;
1497 /* If both variables are defined they have been already checked for
1498 equivalence. */
1499 gcc_assert (!variable_different_p (var1, var2, false));
1501 /* Continue traversing the hash table. */
1502 return 1;
1505 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1507 static bool
1508 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
1510 dataflow_set_different_value = false;
1512 htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars);
1513 if (!dataflow_set_different_value)
1515 /* We have compared the variables which are in both hash tables
1516 so now only check whether there are some variables in NEW_SET->VARS
1517 which are not in OLD_SET->VARS. */
1518 htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars);
1520 return dataflow_set_different_value;
1523 /* Free the contents of dataflow set SET. */
1525 static void
1526 dataflow_set_destroy (dataflow_set *set)
1528 int i;
1530 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1531 attrs_list_clear (&set->regs[i]);
1533 htab_delete (set->vars);
1534 set->vars = NULL;
1537 /* Return true if RTL X contains a SYMBOL_REF. */
1539 static bool
1540 contains_symbol_ref (rtx x)
1542 const char *fmt;
1543 RTX_CODE code;
1544 int i;
1546 if (!x)
1547 return false;
1549 code = GET_CODE (x);
1550 if (code == SYMBOL_REF)
1551 return true;
1553 fmt = GET_RTX_FORMAT (code);
1554 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1556 if (fmt[i] == 'e')
1558 if (contains_symbol_ref (XEXP (x, i)))
1559 return true;
1561 else if (fmt[i] == 'E')
1563 int j;
1564 for (j = 0; j < XVECLEN (x, i); j++)
1565 if (contains_symbol_ref (XVECEXP (x, i, j)))
1566 return true;
1570 return false;
1573 /* Shall EXPR be tracked? */
1575 static bool
1576 track_expr_p (tree expr)
1578 rtx decl_rtl;
1579 tree realdecl;
1581 /* If EXPR is not a parameter or a variable do not track it. */
1582 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
1583 return 0;
1585 /* It also must have a name... */
1586 if (!DECL_NAME (expr))
1587 return 0;
1589 /* ... and a RTL assigned to it. */
1590 decl_rtl = DECL_RTL_IF_SET (expr);
1591 if (!decl_rtl)
1592 return 0;
1594 /* If this expression is really a debug alias of some other declaration, we
1595 don't need to track this expression if the ultimate declaration is
1596 ignored. */
1597 realdecl = expr;
1598 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
1600 realdecl = DECL_DEBUG_EXPR (realdecl);
1601 /* ??? We don't yet know how to emit DW_OP_piece for variable
1602 that has been SRA'ed. */
1603 if (!DECL_P (realdecl))
1604 return 0;
1607 /* Do not track EXPR if REALDECL it should be ignored for debugging
1608 purposes. */
1609 if (DECL_IGNORED_P (realdecl))
1610 return 0;
1612 /* Do not track global variables until we are able to emit correct location
1613 list for them. */
1614 if (TREE_STATIC (realdecl))
1615 return 0;
1617 /* When the EXPR is a DECL for alias of some variable (see example)
1618 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1619 DECL_RTL contains SYMBOL_REF.
1621 Example:
1622 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1623 char **_dl_argv;
1625 if (MEM_P (decl_rtl)
1626 && contains_symbol_ref (XEXP (decl_rtl, 0)))
1627 return 0;
1629 /* If RTX is a memory it should not be very large (because it would be
1630 an array or struct). */
1631 if (MEM_P (decl_rtl))
1633 /* Do not track structures and arrays. */
1634 if (GET_MODE (decl_rtl) == BLKmode
1635 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
1636 return 0;
1637 if (MEM_SIZE (decl_rtl)
1638 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
1639 return 0;
1642 return 1;
1645 /* Determine whether a given LOC refers to the same variable part as
1646 EXPR+OFFSET. */
1648 static bool
1649 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
1651 tree expr2;
1652 HOST_WIDE_INT offset2;
1654 if (! DECL_P (expr))
1655 return false;
1657 if (REG_P (loc))
1659 expr2 = REG_EXPR (loc);
1660 offset2 = REG_OFFSET (loc);
1662 else if (MEM_P (loc))
1664 expr2 = MEM_EXPR (loc);
1665 offset2 = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
1667 else
1668 return false;
1670 if (! expr2 || ! DECL_P (expr2))
1671 return false;
1673 expr = var_debug_decl (expr);
1674 expr2 = var_debug_decl (expr2);
1676 return (expr == expr2 && offset == offset2);
1679 /* REG is a register we want to track. If not all of REG contains useful
1680 information, return the mode of the lowpart that does contain useful
1681 information, otherwise return the mode of REG.
1683 If REG was a paradoxical subreg, its REG_ATTRS will describe the
1684 whole subreg, but only the old inner part is really relevant. */
1686 static enum machine_mode
1687 mode_for_reg_attrs (rtx reg)
1689 enum machine_mode mode;
1691 mode = GET_MODE (reg);
1692 if (!HARD_REGISTER_NUM_P (ORIGINAL_REGNO (reg)))
1694 enum machine_mode pseudo_mode;
1696 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (reg));
1697 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
1698 mode = pseudo_mode;
1700 return mode;
1703 /* Return the MODE lowpart of LOC, or null if LOC is not something we
1704 want to track. When returning nonnull, make sure that the attributes
1705 on the returned value are updated. */
1707 static rtx
1708 var_lowpart (enum machine_mode mode, rtx loc)
1710 unsigned int offset, regno;
1712 if (!REG_P (loc) && !MEM_P (loc))
1713 return NULL;
1715 if (GET_MODE (loc) == mode)
1716 return loc;
1718 offset = subreg_lowpart_offset (mode, GET_MODE (loc));
1720 if (MEM_P (loc))
1721 return adjust_address_nv (loc, mode, offset);
1723 regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
1724 offset, mode);
1725 return gen_rtx_REG_offset (loc, mode, regno, offset);
1728 /* Count uses (register and memory references) LOC which will be tracked.
1729 INSN is instruction which the LOC is part of. */
1731 static int
1732 count_uses (rtx *loc, void *insn)
1734 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1736 if (REG_P (*loc))
1738 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
1739 VTI (bb)->n_mos++;
1741 else if (MEM_P (*loc)
1742 && MEM_EXPR (*loc)
1743 && track_expr_p (MEM_EXPR (*loc)))
1745 VTI (bb)->n_mos++;
1748 return 0;
1751 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1753 static void
1754 count_uses_1 (rtx *x, void *insn)
1756 for_each_rtx (x, count_uses, insn);
1759 /* Count stores (register and memory references) LOC which will be tracked.
1760 INSN is instruction which the LOC is part of. */
1762 static void
1763 count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *insn)
1765 count_uses (&loc, insn);
1768 /* Add uses (register and memory references) LOC which will be tracked
1769 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
1771 static int
1772 add_uses (rtx *loc, void *insn)
1774 if (REG_P (*loc))
1776 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1777 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1779 if (REG_EXPR (*loc) && track_expr_p (REG_EXPR (*loc)))
1781 mo->type = MO_USE;
1782 mo->u.loc = var_lowpart (mode_for_reg_attrs (*loc), *loc);
1784 else
1786 mo->type = MO_USE_NO_VAR;
1787 mo->u.loc = *loc;
1789 mo->insn = (rtx) insn;
1791 else if (MEM_P (*loc)
1792 && MEM_EXPR (*loc)
1793 && track_expr_p (MEM_EXPR (*loc)))
1795 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1796 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1798 mo->type = MO_USE;
1799 mo->u.loc = *loc;
1800 mo->insn = (rtx) insn;
1803 return 0;
1806 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1808 static void
1809 add_uses_1 (rtx *x, void *insn)
1811 for_each_rtx (x, add_uses, insn);
1814 /* Add stores (register and memory references) LOC which will be tracked
1815 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
1816 INSN is instruction which the LOC is part of. */
1818 static void
1819 add_stores (rtx loc, const_rtx expr, void *insn)
1821 if (REG_P (loc))
1823 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1824 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1826 if (GET_CODE (expr) == CLOBBER
1827 || ! REG_EXPR (loc)
1828 || ! track_expr_p (REG_EXPR (loc)))
1830 mo->type = MO_CLOBBER;
1831 mo->u.loc = loc;
1833 else
1835 enum machine_mode mode = mode_for_reg_attrs (loc);
1836 rtx src = NULL;
1838 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1839 src = var_lowpart (mode, SET_SRC (expr));
1840 loc = var_lowpart (mode, loc);
1842 if (src == NULL)
1844 mo->type = MO_SET;
1845 mo->u.loc = loc;
1847 else
1849 if (SET_SRC (expr) != src)
1850 expr = gen_rtx_SET (VOIDmode, loc, src);
1851 if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
1852 mo->type = MO_COPY;
1853 else
1854 mo->type = MO_SET;
1855 mo->u.loc = CONST_CAST_RTX (expr);
1858 mo->insn = (rtx) insn;
1860 else if (MEM_P (loc)
1861 && MEM_EXPR (loc)
1862 && track_expr_p (MEM_EXPR (loc)))
1864 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1865 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1867 if (GET_CODE (expr) == CLOBBER)
1869 mo->type = MO_CLOBBER;
1870 mo->u.loc = loc;
1872 else
1874 rtx src = NULL;
1876 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1877 src = var_lowpart (GET_MODE (loc), SET_SRC (expr));
1879 if (src == NULL)
1881 mo->type = MO_SET;
1882 mo->u.loc = loc;
1884 else
1886 if (same_variable_part_p (SET_SRC (expr),
1887 MEM_EXPR (loc),
1888 MEM_OFFSET (loc)
1889 ? INTVAL (MEM_OFFSET (loc)) : 0))
1890 mo->type = MO_COPY;
1891 else
1892 mo->type = MO_SET;
1893 mo->u.loc = CONST_CAST_RTX (expr);
1896 mo->insn = (rtx) insn;
1900 static enum var_init_status
1901 find_src_status (dataflow_set *in, rtx src)
1903 tree decl = NULL_TREE;
1904 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
1906 if (! flag_var_tracking_uninit)
1907 status = VAR_INIT_STATUS_INITIALIZED;
1909 if (src && REG_P (src))
1910 decl = var_debug_decl (REG_EXPR (src));
1911 else if (src && MEM_P (src))
1912 decl = var_debug_decl (MEM_EXPR (src));
1914 if (src && decl)
1915 status = get_init_value (in, src, decl);
1917 return status;
1920 /* SRC is the source of an assignment. Use SET to try to find what
1921 was ultimately assigned to SRC. Return that value if known,
1922 otherwise return SRC itself. */
1924 static rtx
1925 find_src_set_src (dataflow_set *set, rtx src)
1927 tree decl = NULL_TREE; /* The variable being copied around. */
1928 rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
1929 void **slot;
1930 variable var;
1931 location_chain nextp;
1932 int i;
1933 bool found;
1935 if (src && REG_P (src))
1936 decl = var_debug_decl (REG_EXPR (src));
1937 else if (src && MEM_P (src))
1938 decl = var_debug_decl (MEM_EXPR (src));
1940 if (src && decl)
1942 slot = htab_find_slot_with_hash (set->vars, decl,
1943 VARIABLE_HASH_VAL (decl), NO_INSERT);
1945 if (slot)
1947 var = *(variable *) slot;
1948 found = false;
1949 for (i = 0; i < var->n_var_parts && !found; i++)
1950 for (nextp = var->var_part[i].loc_chain; nextp && !found;
1951 nextp = nextp->next)
1952 if (rtx_equal_p (nextp->loc, src))
1954 set_src = nextp->set_src;
1955 found = true;
1961 return set_src;
1964 /* Compute the changes of variable locations in the basic block BB. */
1966 static bool
1967 compute_bb_dataflow (basic_block bb)
1969 int i, n, r;
1970 bool changed;
1971 dataflow_set old_out;
1972 dataflow_set *in = &VTI (bb)->in;
1973 dataflow_set *out = &VTI (bb)->out;
1975 dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3);
1976 dataflow_set_copy (&old_out, out);
1977 dataflow_set_copy (out, in);
1979 n = VTI (bb)->n_mos;
1980 for (i = 0; i < n; i++)
1982 switch (VTI (bb)->mos[i].type)
1984 case MO_CALL:
1985 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
1986 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
1987 var_regno_delete (out, r);
1988 break;
1990 case MO_USE:
1992 rtx loc = VTI (bb)->mos[i].u.loc;
1993 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
1995 if (! flag_var_tracking_uninit)
1996 status = VAR_INIT_STATUS_INITIALIZED;
1998 if (GET_CODE (loc) == REG)
1999 var_reg_set (out, loc, status, NULL);
2000 else if (GET_CODE (loc) == MEM)
2001 var_mem_set (out, loc, status, NULL);
2003 break;
2005 case MO_SET:
2007 rtx loc = VTI (bb)->mos[i].u.loc;
2008 rtx set_src = NULL;
2010 if (GET_CODE (loc) == SET)
2012 set_src = SET_SRC (loc);
2013 loc = SET_DEST (loc);
2016 if (REG_P (loc))
2017 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2018 set_src);
2019 else if (MEM_P (loc))
2020 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
2021 set_src);
2023 break;
2025 case MO_COPY:
2027 rtx loc = VTI (bb)->mos[i].u.loc;
2028 enum var_init_status src_status;
2029 rtx set_src = NULL;
2031 if (GET_CODE (loc) == SET)
2033 set_src = SET_SRC (loc);
2034 loc = SET_DEST (loc);
2037 if (! flag_var_tracking_uninit)
2038 src_status = VAR_INIT_STATUS_INITIALIZED;
2039 else
2040 src_status = find_src_status (in, set_src);
2042 if (src_status == VAR_INIT_STATUS_UNKNOWN)
2043 src_status = find_src_status (out, set_src);
2045 set_src = find_src_set_src (in, set_src);
2047 if (REG_P (loc))
2048 var_reg_delete_and_set (out, loc, false, src_status, set_src);
2049 else if (MEM_P (loc))
2050 var_mem_delete_and_set (out, loc, false, src_status, set_src);
2052 break;
2054 case MO_USE_NO_VAR:
2056 rtx loc = VTI (bb)->mos[i].u.loc;
2058 if (REG_P (loc))
2059 var_reg_delete (out, loc, false);
2060 else if (MEM_P (loc))
2061 var_mem_delete (out, loc, false);
2063 break;
2065 case MO_CLOBBER:
2067 rtx loc = VTI (bb)->mos[i].u.loc;
2069 if (REG_P (loc))
2070 var_reg_delete (out, loc, true);
2071 else if (MEM_P (loc))
2072 var_mem_delete (out, loc, true);
2074 break;
2076 case MO_ADJUST:
2077 out->stack_adjust += VTI (bb)->mos[i].u.adjust;
2078 break;
2082 changed = dataflow_set_different (&old_out, out);
2083 dataflow_set_destroy (&old_out);
2084 return changed;
2087 /* Find the locations of variables in the whole function. */
2089 static void
2090 vt_find_locations (void)
2092 fibheap_t worklist, pending, fibheap_swap;
2093 sbitmap visited, in_worklist, in_pending, sbitmap_swap;
2094 basic_block bb;
2095 edge e;
2096 int *bb_order;
2097 int *rc_order;
2098 int i;
2100 /* Compute reverse completion order of depth first search of the CFG
2101 so that the data-flow runs faster. */
2102 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
2103 bb_order = XNEWVEC (int, last_basic_block);
2104 pre_and_rev_post_order_compute (NULL, rc_order, false);
2105 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
2106 bb_order[rc_order[i]] = i;
2107 free (rc_order);
2109 worklist = fibheap_new ();
2110 pending = fibheap_new ();
2111 visited = sbitmap_alloc (last_basic_block);
2112 in_worklist = sbitmap_alloc (last_basic_block);
2113 in_pending = sbitmap_alloc (last_basic_block);
2114 sbitmap_zero (in_worklist);
2116 FOR_EACH_BB (bb)
2117 fibheap_insert (pending, bb_order[bb->index], bb);
2118 sbitmap_ones (in_pending);
2120 while (!fibheap_empty (pending))
2122 fibheap_swap = pending;
2123 pending = worklist;
2124 worklist = fibheap_swap;
2125 sbitmap_swap = in_pending;
2126 in_pending = in_worklist;
2127 in_worklist = sbitmap_swap;
2129 sbitmap_zero (visited);
2131 while (!fibheap_empty (worklist))
2133 bb = fibheap_extract_min (worklist);
2134 RESET_BIT (in_worklist, bb->index);
2135 if (!TEST_BIT (visited, bb->index))
2137 bool changed;
2138 edge_iterator ei;
2140 SET_BIT (visited, bb->index);
2142 /* Calculate the IN set as union of predecessor OUT sets. */
2143 dataflow_set_clear (&VTI (bb)->in);
2144 FOR_EACH_EDGE (e, ei, bb->preds)
2146 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
2149 changed = compute_bb_dataflow (bb);
2150 if (changed)
2152 FOR_EACH_EDGE (e, ei, bb->succs)
2154 if (e->dest == EXIT_BLOCK_PTR)
2155 continue;
2157 if (e->dest == bb)
2158 continue;
2160 if (TEST_BIT (visited, e->dest->index))
2162 if (!TEST_BIT (in_pending, e->dest->index))
2164 /* Send E->DEST to next round. */
2165 SET_BIT (in_pending, e->dest->index);
2166 fibheap_insert (pending,
2167 bb_order[e->dest->index],
2168 e->dest);
2171 else if (!TEST_BIT (in_worklist, e->dest->index))
2173 /* Add E->DEST to current round. */
2174 SET_BIT (in_worklist, e->dest->index);
2175 fibheap_insert (worklist, bb_order[e->dest->index],
2176 e->dest);
2184 free (bb_order);
2185 fibheap_delete (worklist);
2186 fibheap_delete (pending);
2187 sbitmap_free (visited);
2188 sbitmap_free (in_worklist);
2189 sbitmap_free (in_pending);
2192 /* Print the content of the LIST to dump file. */
2194 static void
2195 dump_attrs_list (attrs list)
2197 for (; list; list = list->next)
2199 print_mem_expr (dump_file, list->decl);
2200 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
2202 fprintf (dump_file, "\n");
2205 /* Print the information about variable *SLOT to dump file. */
2207 static int
2208 dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
2210 variable var = *(variable *) slot;
2211 int i;
2212 location_chain node;
2214 fprintf (dump_file, " name: %s",
2215 IDENTIFIER_POINTER (DECL_NAME (var->decl)));
2216 if (dump_flags & TDF_UID)
2217 fprintf (dump_file, " D.%u\n", DECL_UID (var->decl));
2218 else
2219 fprintf (dump_file, "\n");
2221 for (i = 0; i < var->n_var_parts; i++)
2223 fprintf (dump_file, " offset %ld\n",
2224 (long) var->var_part[i].offset);
2225 for (node = var->var_part[i].loc_chain; node; node = node->next)
2227 fprintf (dump_file, " ");
2228 if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
2229 fprintf (dump_file, "[uninit]");
2230 print_rtl_single (dump_file, node->loc);
2234 /* Continue traversing the hash table. */
2235 return 1;
2238 /* Print the information about variables from hash table VARS to dump file. */
2240 static void
2241 dump_vars (htab_t vars)
2243 if (htab_elements (vars) > 0)
2245 fprintf (dump_file, "Variables:\n");
2246 htab_traverse (vars, dump_variable, NULL);
2250 /* Print the dataflow set SET to dump file. */
2252 static void
2253 dump_dataflow_set (dataflow_set *set)
2255 int i;
2257 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
2258 set->stack_adjust);
2259 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2261 if (set->regs[i])
2263 fprintf (dump_file, "Reg %d:", i);
2264 dump_attrs_list (set->regs[i]);
2267 dump_vars (set->vars);
2268 fprintf (dump_file, "\n");
2271 /* Print the IN and OUT sets for each basic block to dump file. */
2273 static void
2274 dump_dataflow_sets (void)
2276 basic_block bb;
2278 FOR_EACH_BB (bb)
2280 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
2281 fprintf (dump_file, "IN:\n");
2282 dump_dataflow_set (&VTI (bb)->in);
2283 fprintf (dump_file, "OUT:\n");
2284 dump_dataflow_set (&VTI (bb)->out);
2288 /* Add variable VAR to the hash table of changed variables and
2289 if it has no locations delete it from hash table HTAB. */
2291 static void
2292 variable_was_changed (variable var, htab_t htab)
2294 hashval_t hash = VARIABLE_HASH_VAL (var->decl);
2296 if (emit_notes)
2298 variable *slot;
2300 slot = (variable *) htab_find_slot_with_hash (changed_variables,
2301 var->decl, hash, INSERT);
2303 if (htab && var->n_var_parts == 0)
2305 variable empty_var;
2306 void **old;
2308 empty_var = pool_alloc (var_pool);
2309 empty_var->decl = var->decl;
2310 empty_var->refcount = 1;
2311 empty_var->n_var_parts = 0;
2312 *slot = empty_var;
2314 old = htab_find_slot_with_hash (htab, var->decl, hash,
2315 NO_INSERT);
2316 if (old)
2317 htab_clear_slot (htab, old);
2319 else
2321 *slot = var;
2324 else
2326 gcc_assert (htab);
2327 if (var->n_var_parts == 0)
2329 void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
2330 NO_INSERT);
2331 if (slot)
2332 htab_clear_slot (htab, slot);
2337 /* Look for the index in VAR->var_part corresponding to OFFSET.
2338 Return -1 if not found. If INSERTION_POINT is non-NULL, the
2339 referenced int will be set to the index that the part has or should
2340 have, if it should be inserted. */
2342 static inline int
2343 find_variable_location_part (variable var, HOST_WIDE_INT offset,
2344 int *insertion_point)
2346 int pos, low, high;
2348 /* Find the location part. */
2349 low = 0;
2350 high = var->n_var_parts;
2351 while (low != high)
2353 pos = (low + high) / 2;
2354 if (var->var_part[pos].offset < offset)
2355 low = pos + 1;
2356 else
2357 high = pos;
2359 pos = low;
2361 if (insertion_point)
2362 *insertion_point = pos;
2364 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
2365 return pos;
2367 return -1;
2370 /* Set the part of variable's location in the dataflow set SET. The variable
2371 part is specified by variable's declaration DECL and offset OFFSET and the
2372 part's location by LOC. */
2374 static void
2375 set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset,
2376 enum var_init_status initialized, rtx set_src)
2378 int pos;
2379 location_chain node, next;
2380 location_chain *nextp;
2381 variable var;
2382 void **slot;
2384 slot = htab_find_slot_with_hash (set->vars, decl,
2385 VARIABLE_HASH_VAL (decl), INSERT);
2386 if (!*slot)
2388 /* Create new variable information. */
2389 var = pool_alloc (var_pool);
2390 var->decl = decl;
2391 var->refcount = 1;
2392 var->n_var_parts = 1;
2393 var->var_part[0].offset = offset;
2394 var->var_part[0].loc_chain = NULL;
2395 var->var_part[0].cur_loc = NULL;
2396 *slot = var;
2397 pos = 0;
2399 else
2401 int inspos = 0;
2403 var = (variable) *slot;
2405 pos = find_variable_location_part (var, offset, &inspos);
2407 if (pos >= 0)
2409 node = var->var_part[pos].loc_chain;
2411 if (node
2412 && ((REG_P (node->loc) && REG_P (loc)
2413 && REGNO (node->loc) == REGNO (loc))
2414 || rtx_equal_p (node->loc, loc)))
2416 /* LOC is in the beginning of the chain so we have nothing
2417 to do. */
2418 if (node->init < initialized)
2419 node->init = initialized;
2420 if (set_src != NULL)
2421 node->set_src = set_src;
2423 *slot = var;
2424 return;
2426 else
2428 /* We have to make a copy of a shared variable. */
2429 if (var->refcount > 1)
2430 var = unshare_variable (set, var, initialized);
2433 else
2435 /* We have not found the location part, new one will be created. */
2437 /* We have to make a copy of the shared variable. */
2438 if (var->refcount > 1)
2439 var = unshare_variable (set, var, initialized);
2441 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2442 thus there are at most MAX_VAR_PARTS different offsets. */
2443 gcc_assert (var->n_var_parts < MAX_VAR_PARTS);
2445 /* We have to move the elements of array starting at index
2446 inspos to the next position. */
2447 for (pos = var->n_var_parts; pos > inspos; pos--)
2448 var->var_part[pos] = var->var_part[pos - 1];
2450 var->n_var_parts++;
2451 var->var_part[pos].offset = offset;
2452 var->var_part[pos].loc_chain = NULL;
2453 var->var_part[pos].cur_loc = NULL;
2457 /* Delete the location from the list. */
2458 nextp = &var->var_part[pos].loc_chain;
2459 for (node = var->var_part[pos].loc_chain; node; node = next)
2461 next = node->next;
2462 if ((REG_P (node->loc) && REG_P (loc)
2463 && REGNO (node->loc) == REGNO (loc))
2464 || rtx_equal_p (node->loc, loc))
2466 /* Save these values, to assign to the new node, before
2467 deleting this one. */
2468 if (node->init > initialized)
2469 initialized = node->init;
2470 if (node->set_src != NULL && set_src == NULL)
2471 set_src = node->set_src;
2472 pool_free (loc_chain_pool, node);
2473 *nextp = next;
2474 break;
2476 else
2477 nextp = &node->next;
2480 /* Add the location to the beginning. */
2481 node = pool_alloc (loc_chain_pool);
2482 node->loc = loc;
2483 node->init = initialized;
2484 node->set_src = set_src;
2485 node->next = var->var_part[pos].loc_chain;
2486 var->var_part[pos].loc_chain = node;
2488 /* If no location was emitted do so. */
2489 if (var->var_part[pos].cur_loc == NULL)
2491 var->var_part[pos].cur_loc = loc;
2492 variable_was_changed (var, set->vars);
2496 /* Remove all recorded register locations for the given variable part
2497 from dataflow set SET, except for those that are identical to loc.
2498 The variable part is specified by variable's declaration DECL and
2499 offset OFFSET. */
2501 static void
2502 clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
2503 HOST_WIDE_INT offset, rtx set_src)
2505 void **slot;
2507 if (! decl || ! DECL_P (decl))
2508 return;
2510 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2511 NO_INSERT);
2512 if (slot)
2514 variable var = (variable) *slot;
2515 int pos = find_variable_location_part (var, offset, NULL);
2517 if (pos >= 0)
2519 location_chain node, next;
2521 /* Remove the register locations from the dataflow set. */
2522 next = var->var_part[pos].loc_chain;
2523 for (node = next; node; node = next)
2525 next = node->next;
2526 if (node->loc != loc
2527 && (!flag_var_tracking_uninit
2528 || !set_src
2529 || MEM_P (set_src)
2530 || !rtx_equal_p (set_src, node->set_src)))
2532 if (REG_P (node->loc))
2534 attrs anode, anext;
2535 attrs *anextp;
2537 /* Remove the variable part from the register's
2538 list, but preserve any other variable parts
2539 that might be regarded as live in that same
2540 register. */
2541 anextp = &set->regs[REGNO (node->loc)];
2542 for (anode = *anextp; anode; anode = anext)
2544 anext = anode->next;
2545 if (anode->decl == decl
2546 && anode->offset == offset)
2548 pool_free (attrs_pool, anode);
2549 *anextp = anext;
2554 delete_variable_part (set, node->loc, decl, offset);
2561 /* Delete the part of variable's location from dataflow set SET. The variable
2562 part is specified by variable's declaration DECL and offset OFFSET and the
2563 part's location by LOC. */
2565 static void
2566 delete_variable_part (dataflow_set *set, rtx loc, tree decl,
2567 HOST_WIDE_INT offset)
2569 void **slot;
2571 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2572 NO_INSERT);
2573 if (slot)
2575 variable var = (variable) *slot;
2576 int pos = find_variable_location_part (var, offset, NULL);
2578 if (pos >= 0)
2580 location_chain node, next;
2581 location_chain *nextp;
2582 bool changed;
2584 if (var->refcount > 1)
2586 /* If the variable contains the location part we have to
2587 make a copy of the variable. */
2588 for (node = var->var_part[pos].loc_chain; node;
2589 node = node->next)
2591 if ((REG_P (node->loc) && REG_P (loc)
2592 && REGNO (node->loc) == REGNO (loc))
2593 || rtx_equal_p (node->loc, loc))
2595 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
2596 if (! flag_var_tracking_uninit)
2597 status = VAR_INIT_STATUS_INITIALIZED;
2598 var = unshare_variable (set, var, status);
2599 break;
2604 /* Delete the location part. */
2605 nextp = &var->var_part[pos].loc_chain;
2606 for (node = *nextp; node; node = next)
2608 next = node->next;
2609 if ((REG_P (node->loc) && REG_P (loc)
2610 && REGNO (node->loc) == REGNO (loc))
2611 || rtx_equal_p (node->loc, loc))
2613 pool_free (loc_chain_pool, node);
2614 *nextp = next;
2615 break;
2617 else
2618 nextp = &node->next;
2621 /* If we have deleted the location which was last emitted
2622 we have to emit new location so add the variable to set
2623 of changed variables. */
2624 if (var->var_part[pos].cur_loc
2625 && ((REG_P (loc)
2626 && REG_P (var->var_part[pos].cur_loc)
2627 && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
2628 || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
2630 changed = true;
2631 if (var->var_part[pos].loc_chain)
2632 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc;
2634 else
2635 changed = false;
2637 if (var->var_part[pos].loc_chain == NULL)
2639 var->n_var_parts--;
2640 while (pos < var->n_var_parts)
2642 var->var_part[pos] = var->var_part[pos + 1];
2643 pos++;
2646 if (changed)
2647 variable_was_changed (var, set->vars);
2652 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2653 additional parameters: WHERE specifies whether the note shall be emitted
2654 before of after instruction INSN. */
2656 static int
2657 emit_note_insn_var_location (void **varp, void *data)
2659 variable var = *(variable *) varp;
2660 rtx insn = ((emit_note_data *)data)->insn;
2661 enum emit_note_where where = ((emit_note_data *)data)->where;
2662 rtx note;
2663 int i, j, n_var_parts;
2664 bool complete;
2665 enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
2666 HOST_WIDE_INT last_limit;
2667 tree type_size_unit;
2668 HOST_WIDE_INT offsets[MAX_VAR_PARTS];
2669 rtx loc[MAX_VAR_PARTS];
2671 gcc_assert (var->decl);
2673 if (! flag_var_tracking_uninit)
2674 initialized = VAR_INIT_STATUS_INITIALIZED;
2676 complete = true;
2677 last_limit = 0;
2678 n_var_parts = 0;
2679 for (i = 0; i < var->n_var_parts; i++)
2681 enum machine_mode mode, wider_mode;
2683 if (last_limit < var->var_part[i].offset)
2685 complete = false;
2686 break;
2688 else if (last_limit > var->var_part[i].offset)
2689 continue;
2690 offsets[n_var_parts] = var->var_part[i].offset;
2691 loc[n_var_parts] = var->var_part[i].loc_chain->loc;
2692 mode = GET_MODE (loc[n_var_parts]);
2693 initialized = var->var_part[i].loc_chain->init;
2694 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
2696 /* Attempt to merge adjacent registers or memory. */
2697 wider_mode = GET_MODE_WIDER_MODE (mode);
2698 for (j = i + 1; j < var->n_var_parts; j++)
2699 if (last_limit <= var->var_part[j].offset)
2700 break;
2701 if (j < var->n_var_parts
2702 && wider_mode != VOIDmode
2703 && GET_CODE (loc[n_var_parts])
2704 == GET_CODE (var->var_part[j].loc_chain->loc)
2705 && mode == GET_MODE (var->var_part[j].loc_chain->loc)
2706 && last_limit == var->var_part[j].offset)
2708 rtx new_loc = NULL;
2709 rtx loc2 = var->var_part[j].loc_chain->loc;
2711 if (REG_P (loc[n_var_parts])
2712 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
2713 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
2714 && end_hard_regno (mode, REGNO (loc[n_var_parts]))
2715 == REGNO (loc2))
2717 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
2718 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
2719 mode, 0);
2720 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
2721 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
2722 if (new_loc)
2724 if (!REG_P (new_loc)
2725 || REGNO (new_loc) != REGNO (loc[n_var_parts]))
2726 new_loc = NULL;
2727 else
2728 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
2731 else if (MEM_P (loc[n_var_parts])
2732 && GET_CODE (XEXP (loc2, 0)) == PLUS
2733 && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG
2734 && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT)
2736 if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG
2737 && rtx_equal_p (XEXP (loc[n_var_parts], 0),
2738 XEXP (XEXP (loc2, 0), 0))
2739 && INTVAL (XEXP (XEXP (loc2, 0), 1))
2740 == GET_MODE_SIZE (mode))
2741 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
2742 && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1))
2743 == CONST_INT
2744 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
2745 XEXP (XEXP (loc2, 0), 0))
2746 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
2747 + GET_MODE_SIZE (mode)
2748 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
2749 new_loc = adjust_address_nv (loc[n_var_parts],
2750 wider_mode, 0);
2753 if (new_loc)
2755 loc[n_var_parts] = new_loc;
2756 mode = wider_mode;
2757 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
2758 i = j;
2761 ++n_var_parts;
2763 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
2764 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
2765 complete = false;
2767 if (where == EMIT_NOTE_AFTER_INSN)
2768 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
2769 else
2770 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
2772 if (! flag_var_tracking_uninit)
2773 initialized = VAR_INIT_STATUS_INITIALIZED;
2775 if (!complete)
2777 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2778 NULL_RTX, (int) initialized);
2780 else if (n_var_parts == 1)
2782 rtx expr_list
2783 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
2785 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2786 expr_list,
2787 (int) initialized);
2789 else if (n_var_parts)
2791 rtx parallel;
2793 for (i = 0; i < n_var_parts; i++)
2794 loc[i]
2795 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
2797 parallel = gen_rtx_PARALLEL (VOIDmode,
2798 gen_rtvec_v (n_var_parts, loc));
2799 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2800 parallel,
2801 (int) initialized);
2804 htab_clear_slot (changed_variables, varp);
2806 /* When there are no location parts the variable has been already
2807 removed from hash table and a new empty variable was created.
2808 Free the empty variable. */
2809 if (var->n_var_parts == 0)
2811 pool_free (var_pool, var);
2814 /* Continue traversing the hash table. */
2815 return 1;
2818 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
2819 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
2820 shall be emitted before of after instruction INSN. */
2822 static void
2823 emit_notes_for_changes (rtx insn, enum emit_note_where where)
2825 emit_note_data data;
2827 data.insn = insn;
2828 data.where = where;
2829 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
2832 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
2833 same variable in hash table DATA or is not there at all. */
2835 static int
2836 emit_notes_for_differences_1 (void **slot, void *data)
2838 htab_t new_vars = (htab_t) data;
2839 variable old_var, new_var;
2841 old_var = *(variable *) slot;
2842 new_var = htab_find_with_hash (new_vars, old_var->decl,
2843 VARIABLE_HASH_VAL (old_var->decl));
2845 if (!new_var)
2847 /* Variable has disappeared. */
2848 variable empty_var;
2850 empty_var = pool_alloc (var_pool);
2851 empty_var->decl = old_var->decl;
2852 empty_var->refcount = 1;
2853 empty_var->n_var_parts = 0;
2854 variable_was_changed (empty_var, NULL);
2856 else if (variable_different_p (old_var, new_var, true))
2858 variable_was_changed (new_var, NULL);
2861 /* Continue traversing the hash table. */
2862 return 1;
2865 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2866 table DATA. */
2868 static int
2869 emit_notes_for_differences_2 (void **slot, void *data)
2871 htab_t old_vars = (htab_t) data;
2872 variable old_var, new_var;
2874 new_var = *(variable *) slot;
2875 old_var = htab_find_with_hash (old_vars, new_var->decl,
2876 VARIABLE_HASH_VAL (new_var->decl));
2877 if (!old_var)
2879 /* Variable has appeared. */
2880 variable_was_changed (new_var, NULL);
2883 /* Continue traversing the hash table. */
2884 return 1;
2887 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2888 NEW_SET. */
2890 static void
2891 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
2892 dataflow_set *new_set)
2894 htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars);
2895 htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars);
2896 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
2899 /* Emit the notes for changes of location parts in the basic block BB. */
2901 static void
2902 emit_notes_in_bb (basic_block bb)
2904 int i;
2905 dataflow_set set;
2907 dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3);
2908 dataflow_set_copy (&set, &VTI (bb)->in);
2910 for (i = 0; i < VTI (bb)->n_mos; i++)
2912 rtx insn = VTI (bb)->mos[i].insn;
2914 switch (VTI (bb)->mos[i].type)
2916 case MO_CALL:
2918 int r;
2920 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
2921 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
2923 var_regno_delete (&set, r);
2925 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
2927 break;
2929 case MO_USE:
2931 rtx loc = VTI (bb)->mos[i].u.loc;
2933 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
2934 if (! flag_var_tracking_uninit)
2935 status = VAR_INIT_STATUS_INITIALIZED;
2936 if (GET_CODE (loc) == REG)
2937 var_reg_set (&set, loc, status, NULL);
2938 else
2939 var_mem_set (&set, loc, status, NULL);
2941 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
2943 break;
2945 case MO_SET:
2947 rtx loc = VTI (bb)->mos[i].u.loc;
2948 rtx set_src = NULL;
2950 if (GET_CODE (loc) == SET)
2952 set_src = SET_SRC (loc);
2953 loc = SET_DEST (loc);
2956 if (REG_P (loc))
2957 var_reg_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
2958 set_src);
2959 else
2960 var_mem_delete_and_set (&set, loc, true, VAR_INIT_STATUS_INITIALIZED,
2961 set_src);
2963 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
2965 break;
2967 case MO_COPY:
2969 rtx loc = VTI (bb)->mos[i].u.loc;
2970 enum var_init_status src_status;
2971 rtx set_src = NULL;
2973 if (GET_CODE (loc) == SET)
2975 set_src = SET_SRC (loc);
2976 loc = SET_DEST (loc);
2979 src_status = find_src_status (&set, set_src);
2980 set_src = find_src_set_src (&set, set_src);
2982 if (REG_P (loc))
2983 var_reg_delete_and_set (&set, loc, false, src_status, set_src);
2984 else
2985 var_mem_delete_and_set (&set, loc, false, src_status, set_src);
2987 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
2989 break;
2991 case MO_USE_NO_VAR:
2993 rtx loc = VTI (bb)->mos[i].u.loc;
2995 if (REG_P (loc))
2996 var_reg_delete (&set, loc, false);
2997 else
2998 var_mem_delete (&set, loc, false);
3000 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3002 break;
3004 case MO_CLOBBER:
3006 rtx loc = VTI (bb)->mos[i].u.loc;
3008 if (REG_P (loc))
3009 var_reg_delete (&set, loc, true);
3010 else
3011 var_mem_delete (&set, loc, true);
3013 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3015 break;
3017 case MO_ADJUST:
3018 set.stack_adjust += VTI (bb)->mos[i].u.adjust;
3019 break;
3022 dataflow_set_destroy (&set);
3025 /* Emit notes for the whole function. */
3027 static void
3028 vt_emit_notes (void)
3030 basic_block bb;
3031 dataflow_set *last_out;
3032 dataflow_set empty;
3034 gcc_assert (!htab_elements (changed_variables));
3036 /* Enable emitting notes by functions (mainly by set_variable_part and
3037 delete_variable_part). */
3038 emit_notes = true;
3040 dataflow_set_init (&empty, 7);
3041 last_out = &empty;
3043 FOR_EACH_BB (bb)
3045 /* Emit the notes for changes of variable locations between two
3046 subsequent basic blocks. */
3047 emit_notes_for_differences (BB_HEAD (bb), last_out, &VTI (bb)->in);
3049 /* Emit the notes for the changes in the basic block itself. */
3050 emit_notes_in_bb (bb);
3052 last_out = &VTI (bb)->out;
3054 dataflow_set_destroy (&empty);
3055 emit_notes = false;
3058 /* If there is a declaration and offset associated with register/memory RTL
3059 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
3061 static bool
3062 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
3064 if (REG_P (rtl))
3066 if (REG_ATTRS (rtl))
3068 *declp = REG_EXPR (rtl);
3069 *offsetp = REG_OFFSET (rtl);
3070 return true;
3073 else if (MEM_P (rtl))
3075 if (MEM_ATTRS (rtl))
3077 *declp = MEM_EXPR (rtl);
3078 *offsetp = MEM_OFFSET (rtl) ? INTVAL (MEM_OFFSET (rtl)) : 0;
3079 return true;
3082 return false;
3085 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3087 static void
3088 vt_add_function_parameters (void)
3090 tree parm;
3092 for (parm = DECL_ARGUMENTS (current_function_decl);
3093 parm; parm = TREE_CHAIN (parm))
3095 rtx decl_rtl = DECL_RTL_IF_SET (parm);
3096 rtx incoming = DECL_INCOMING_RTL (parm);
3097 tree decl;
3098 HOST_WIDE_INT offset;
3099 dataflow_set *out;
3101 if (TREE_CODE (parm) != PARM_DECL)
3102 continue;
3104 if (!DECL_NAME (parm))
3105 continue;
3107 if (!decl_rtl || !incoming)
3108 continue;
3110 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
3111 continue;
3113 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
3114 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
3115 continue;
3117 if (!decl)
3118 continue;
3120 gcc_assert (parm == decl);
3122 out = &VTI (ENTRY_BLOCK_PTR)->out;
3124 if (REG_P (incoming))
3126 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
3127 attrs_list_insert (&out->regs[REGNO (incoming)],
3128 parm, offset, incoming);
3129 set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
3130 NULL);
3132 else if (MEM_P (incoming))
3133 set_variable_part (out, incoming, parm, offset, VAR_INIT_STATUS_INITIALIZED,
3134 NULL);
3138 /* Allocate and initialize the data structures for variable tracking
3139 and parse the RTL to get the micro operations. */
3141 static void
3142 vt_initialize (void)
3144 basic_block bb;
3146 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
3148 FOR_EACH_BB (bb)
3150 rtx insn;
3151 HOST_WIDE_INT pre, post = 0;
3153 /* Count the number of micro operations. */
3154 VTI (bb)->n_mos = 0;
3155 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3156 insn = NEXT_INSN (insn))
3158 if (INSN_P (insn))
3160 if (!frame_pointer_needed)
3162 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3163 if (pre)
3164 VTI (bb)->n_mos++;
3165 if (post)
3166 VTI (bb)->n_mos++;
3168 note_uses (&PATTERN (insn), count_uses_1, insn);
3169 note_stores (PATTERN (insn), count_stores, insn);
3170 if (CALL_P (insn))
3171 VTI (bb)->n_mos++;
3175 /* Add the micro-operations to the array. */
3176 VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos);
3177 VTI (bb)->n_mos = 0;
3178 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
3179 insn = NEXT_INSN (insn))
3181 if (INSN_P (insn))
3183 int n1, n2;
3185 if (!frame_pointer_needed)
3187 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3188 if (pre)
3190 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3192 mo->type = MO_ADJUST;
3193 mo->u.adjust = pre;
3194 mo->insn = insn;
3198 n1 = VTI (bb)->n_mos;
3199 note_uses (&PATTERN (insn), add_uses_1, insn);
3200 n2 = VTI (bb)->n_mos - 1;
3202 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
3203 while (n1 < n2)
3205 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
3206 n1++;
3207 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR)
3208 n2--;
3209 if (n1 < n2)
3211 micro_operation sw;
3213 sw = VTI (bb)->mos[n1];
3214 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3215 VTI (bb)->mos[n2] = sw;
3219 if (CALL_P (insn))
3221 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3223 mo->type = MO_CALL;
3224 mo->insn = insn;
3227 n1 = VTI (bb)->n_mos;
3228 /* This will record NEXT_INSN (insn), such that we can
3229 insert notes before it without worrying about any
3230 notes that MO_USEs might emit after the insn. */
3231 note_stores (PATTERN (insn), add_stores, insn);
3232 n2 = VTI (bb)->n_mos - 1;
3234 /* Order the MO_CLOBBERs to be before MO_SETs. */
3235 while (n1 < n2)
3237 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
3238 n1++;
3239 while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET
3240 || VTI (bb)->mos[n2].type == MO_COPY))
3241 n2--;
3242 if (n1 < n2)
3244 micro_operation sw;
3246 sw = VTI (bb)->mos[n1];
3247 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3248 VTI (bb)->mos[n2] = sw;
3252 if (!frame_pointer_needed && post)
3254 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3256 mo->type = MO_ADJUST;
3257 mo->u.adjust = post;
3258 mo->insn = insn;
3264 /* Init the IN and OUT sets. */
3265 FOR_ALL_BB (bb)
3267 VTI (bb)->visited = false;
3268 dataflow_set_init (&VTI (bb)->in, 7);
3269 dataflow_set_init (&VTI (bb)->out, 7);
3272 attrs_pool = create_alloc_pool ("attrs_def pool",
3273 sizeof (struct attrs_def), 1024);
3274 var_pool = create_alloc_pool ("variable_def pool",
3275 sizeof (struct variable_def), 64);
3276 loc_chain_pool = create_alloc_pool ("location_chain_def pool",
3277 sizeof (struct location_chain_def),
3278 1024);
3279 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
3280 NULL);
3281 vt_add_function_parameters ();
3284 /* Free the data structures needed for variable tracking. */
3286 static void
3287 vt_finalize (void)
3289 basic_block bb;
3291 FOR_EACH_BB (bb)
3293 free (VTI (bb)->mos);
3296 FOR_ALL_BB (bb)
3298 dataflow_set_destroy (&VTI (bb)->in);
3299 dataflow_set_destroy (&VTI (bb)->out);
3301 free_aux_for_blocks ();
3302 free_alloc_pool (attrs_pool);
3303 free_alloc_pool (var_pool);
3304 free_alloc_pool (loc_chain_pool);
3305 htab_delete (changed_variables);
3308 /* The entry point to variable tracking pass. */
3310 unsigned int
3311 variable_tracking_main (void)
3313 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
3314 return 0;
3316 mark_dfs_back_edges ();
3317 vt_initialize ();
3318 if (!frame_pointer_needed)
3320 if (!vt_stack_adjustments ())
3322 vt_finalize ();
3323 return 0;
3327 vt_find_locations ();
3328 vt_emit_notes ();
3330 if (dump_file && (dump_flags & TDF_DETAILS))
3332 dump_dataflow_sets ();
3333 dump_flow_info (dump_file, dump_flags);
3336 vt_finalize ();
3337 return 0;
3340 static bool
3341 gate_handle_var_tracking (void)
3343 return (flag_var_tracking);
3348 struct tree_opt_pass pass_variable_tracking =
3350 "vartrack", /* name */
3351 gate_handle_var_tracking, /* gate */
3352 variable_tracking_main, /* execute */
3353 NULL, /* sub */
3354 NULL, /* next */
3355 0, /* static_pass_number */
3356 TV_VAR_TRACKING, /* tv_id */
3357 0, /* properties_required */
3358 0, /* properties_provided */
3359 0, /* properties_destroyed */
3360 0, /* todo_flags_start */
3361 TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
3362 'V' /* letter */