Merged revisions 143552,143554,143557,143560,143562,143564-143567,143570-143573,14357...
[official-gcc.git] / gcc / var-tracking.c
blobb9ff8c57b2549f63ed308385cc7a94ca1e99eaf5
1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
3 Free Software Foundation, Inc.
5 This file is part of GCC.
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.
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.
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/>. */
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.
29 How does the variable tracking pass work?
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
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.
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.
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:
62 if (cond)
63 set A;
64 else
65 set B;
66 CODE;
67 if (cond)
68 use A;
69 else
70 use B;
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).
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).
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"
110 /* Type of micro operation. */
111 enum micro_operation_type
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. */
124 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
125 enum emit_note_where
127 EMIT_NOTE_BEFORE_INSN,
128 EMIT_NOTE_AFTER_INSN
131 /* Structure holding information about micro operation. */
132 typedef struct micro_operation_def
134 /* Type of micro operation. */
135 enum micro_operation_type type;
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;
143 /* Stack adjustment. */
144 HOST_WIDE_INT adjust;
145 } u;
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;
155 /* Structure for passing some other parameters to function
156 emit_note_insn_var_location. */
157 typedef struct emit_note_data_def
159 /* The instruction which the note will be emitted before/after. */
160 rtx insn;
162 /* Where the note will be emitted (before/after insn)? */
163 enum emit_note_where where;
164 } emit_note_data;
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
172 /* Pointer to next member of the list. */
173 struct attrs_def *next;
175 /* The rtx of register. */
176 rtx loc;
178 /* The declaration corresponding to LOC. */
179 tree decl;
181 /* Offset from start of DECL. */
182 HOST_WIDE_INT offset;
183 } *attrs;
185 /* Structure holding the IN or OUT set for a basic block. */
186 typedef struct dataflow_set_def
188 /* Adjustment of stack offset. */
189 HOST_WIDE_INT stack_adjust;
191 /* Attributes for registers (lists of attrs). */
192 attrs regs[FIRST_PSEUDO_REGISTER];
194 /* Variable locations. */
195 htab_t vars;
196 } dataflow_set;
198 /* The structure (one for each basic block) containing the information
199 needed for variable tracking. */
200 typedef struct variable_tracking_info_def
202 /* Number of micro operations stored in the MOS array. */
203 int n_mos;
205 /* The array of micro operations. */
206 micro_operation *mos;
208 /* The IN and OUT set for dataflow analysis. */
209 dataflow_set in;
210 dataflow_set out;
212 /* Has the block been visited in DFS? */
213 bool visited;
214 } *variable_tracking_info;
216 /* Structure for chaining the locations. */
217 typedef struct location_chain_def
219 /* Next element in the chain. */
220 struct location_chain_def *next;
222 /* The location (REG or MEM). */
223 rtx loc;
225 /* The "value" stored in this location. */
226 rtx set_src;
228 /* Initialized? */
229 enum var_init_status init;
230 } *location_chain;
232 /* Structure describing one part of variable. */
233 typedef struct variable_part_def
235 /* Chain of locations of the part. */
236 location_chain loc_chain;
238 /* Location which was last emitted to location list. */
239 rtx cur_loc;
241 /* The offset in the variable. */
242 HOST_WIDE_INT offset;
243 } variable_part;
245 /* Maximum number of location parts. */
246 #define MAX_VAR_PARTS 16
248 /* Structure describing where the variable is located. */
249 typedef struct variable_def
251 /* The declaration of the variable. */
252 tree decl;
254 /* Reference count. */
255 int refcount;
257 /* Number of variable parts. */
258 int n_var_parts;
260 /* The variable parts. */
261 variable_part var_part[MAX_VAR_PARTS];
262 } *variable;
263 typedef const struct variable_def *const_variable;
265 /* Hash function for DECL for VARIABLE_HTAB. */
266 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
268 /* Pointer to the BB's information specific to variable tracking pass. */
269 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
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)
274 /* Alloc pool for struct attrs_def. */
275 static alloc_pool attrs_pool;
277 /* Alloc pool for struct variable_def. */
278 static alloc_pool var_pool;
280 /* Alloc pool for struct location_chain_def. */
281 static alloc_pool loc_chain_pool;
283 /* Changed variables, notes will be emitted for them. */
284 static htab_t changed_variables;
286 /* Shall notes be emitted? */
287 static bool emit_notes;
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 *);
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);
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);
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 *);
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);
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);
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);
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);
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. */
378 static void
379 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
380 HOST_WIDE_INT *post)
382 rtx src = SET_SRC (pattern);
383 rtx dest = SET_DEST (pattern);
384 enum rtx_code code;
386 if (dest == stack_pointer_rtx)
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;
395 if (code == MINUS)
396 *post += INTVAL (XEXP (src, 1));
397 else
398 *post -= INTVAL (XEXP (src, 1));
400 else if (MEM_P (dest))
402 /* (set (mem (pre_dec (reg sp))) (foo)) */
403 src = XEXP (dest, 0);
404 code = GET_CODE (src);
406 switch (code)
408 case PRE_MODIFY:
409 case POST_MODIFY:
410 if (XEXP (src, 0) == stack_pointer_rtx)
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);
417 if (code == PRE_MODIFY)
418 *pre -= INTVAL (val);
419 else
420 *post -= INTVAL (val);
421 break;
423 return;
425 case PRE_DEC:
426 if (XEXP (src, 0) == stack_pointer_rtx)
428 *pre += GET_MODE_SIZE (GET_MODE (dest));
429 break;
431 return;
433 case POST_DEC:
434 if (XEXP (src, 0) == stack_pointer_rtx)
436 *post += GET_MODE_SIZE (GET_MODE (dest));
437 break;
439 return;
441 case PRE_INC:
442 if (XEXP (src, 0) == stack_pointer_rtx)
444 *pre -= GET_MODE_SIZE (GET_MODE (dest));
445 break;
447 return;
449 case POST_INC:
450 if (XEXP (src, 0) == stack_pointer_rtx)
452 *post -= GET_MODE_SIZE (GET_MODE (dest));
453 break;
455 return;
457 default:
458 return;
463 /* Given an INSN, calculate the amount of stack adjustment it contains
464 PRE- and POST-modifying stack pointer. */
466 static void
467 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
468 HOST_WIDE_INT *post)
470 rtx pattern;
472 *pre = 0;
473 *post = 0;
475 pattern = PATTERN (insn);
476 if (RTX_FRAME_RELATED_P (insn))
478 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
479 if (expr)
480 pattern = XEXP (expr, 0);
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)
488 int i;
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);
498 /* Compute stack adjustment in basic block BB. */
500 static void
501 bb_stack_adjust_offset (basic_block bb)
503 HOST_WIDE_INT offset;
504 int i;
506 offset = VTI (bb)->in.stack_adjust;
507 for (i = 0; i < VTI (bb)->n_mos; i++)
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)
513 if (MEM_P (VTI (bb)->mos[i].u.loc))
515 VTI (bb)->mos[i].u.loc
516 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
520 VTI (bb)->out.stack_adjust = offset;
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. */
527 static bool
528 vt_stack_adjustments (void)
530 edge_iterator *stack;
531 int sp;
533 /* Initialize entry block. */
534 VTI (ENTRY_BLOCK_PTR)->visited = true;
535 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
537 /* Allocate stack for back-tracking up CFG. */
538 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
539 sp = 0;
541 /* Push the first edge on to the stack. */
542 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
544 while (sp)
546 edge_iterator ei;
547 basic_block src;
548 basic_block dest;
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;
555 /* Check if the edge destination has been visited yet. */
556 if (!VTI (dest)->visited)
558 VTI (dest)->visited = true;
559 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
560 bb_stack_adjust_offset (dest);
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);
567 else
569 /* Check whether the adjustments on the edges are the same. */
570 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
572 free (stack);
573 return false;
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--;
585 free (stack);
586 return true;
589 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
590 to the argument pointer. Return the new rtx. */
592 static rtx
593 adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
595 rtx addr, cfa, tmp;
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
605 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
606 tmp = simplify_rtx (addr);
607 if (tmp)
608 addr = tmp;
610 return replace_equiv_address_nv (mem, addr);
613 /* The hash function for variable_htab, computes the hash value
614 from the declaration of variable X. */
616 static hashval_t
617 variable_htab_hash (const void *x)
619 const_variable const v = (const_variable) x;
621 return (VARIABLE_HASH_VAL (v->decl));
624 /* Compare the declaration of variable X with declaration Y. */
626 static int
627 variable_htab_eq (const void *x, const void *y)
629 const_variable const v = (const_variable) x;
630 const_tree const decl = (const_tree) y;
632 return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
635 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
637 static void
638 variable_htab_free (void *elem)
640 int i;
641 variable var = (variable) elem;
642 location_chain node, next;
644 gcc_assert (var->refcount > 0);
646 var->refcount--;
647 if (var->refcount > 0)
648 return;
650 for (i = 0; i < var->n_var_parts; i++)
652 for (node = var->var_part[i].loc_chain; node; node = next)
654 next = node->next;
655 pool_free (loc_chain_pool, node);
657 var->var_part[i].loc_chain = NULL;
659 pool_free (var_pool, var);
662 /* Initialize the set (array) SET of attrs to empty lists. */
664 static void
665 init_attrs_list_set (attrs *set)
667 int i;
669 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
670 set[i] = NULL;
673 /* Make the list *LISTP empty. */
675 static void
676 attrs_list_clear (attrs *listp)
678 attrs list, next;
680 for (list = *listp; list; list = next)
682 next = list->next;
683 pool_free (attrs_pool, list);
685 *listp = NULL;
688 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
690 static attrs
691 attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset)
693 for (; list; list = list->next)
694 if (list->decl == decl && list->offset == offset)
695 return list;
696 return NULL;
699 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
701 static void
702 attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc)
704 attrs list;
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;
714 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
716 static void
717 attrs_list_copy (attrs *dstp, attrs src)
719 attrs n;
721 attrs_list_clear (dstp);
722 for (; src; src = src->next)
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;
733 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
735 static void
736 attrs_list_union (attrs *dstp, attrs src)
738 for (; src; src = src->next)
740 if (!attrs_list_member (*dstp, src->decl, src->offset))
741 attrs_list_insert (dstp, src->decl, src->offset, src->loc);
745 /* Delete all variables from hash table VARS. */
747 static void
748 vars_clear (htab_t vars)
750 htab_empty (vars);
753 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
755 static variable
756 unshare_variable (dataflow_set *set, variable var,
757 enum var_init_status initialized)
759 void **slot;
760 variable new_var;
761 int i;
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;
769 for (i = 0; i < var->n_var_parts; i++)
771 location_chain node;
772 location_chain *nextp;
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)
778 location_chain new_lc;
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;
792 *nextp = new_lc;
793 nextp = &new_lc->next;
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;
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;
811 /* Add a variable from *SLOT to hash table DATA and increase its reference
812 count. */
814 static int
815 vars_copy_1 (void **slot, void *data)
817 htab_t dst = (htab_t) data;
818 variable src, *dstp;
820 src = *(variable *) slot;
821 src->refcount++;
823 dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
824 VARIABLE_HASH_VAL (src->decl),
825 INSERT);
826 *dstp = src;
828 /* Continue traversing the hash table. */
829 return 1;
832 /* Copy all variables from hash table SRC to hash table DST. */
834 static void
835 vars_copy (htab_t dst, htab_t src)
837 vars_clear (dst);
838 htab_traverse (src, vars_copy_1, dst);
841 /* Map a decl to its main debug decl. */
843 static inline tree
844 var_debug_decl (tree decl)
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);
851 return decl;
854 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
856 static void
857 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
858 rtx set_src)
860 tree decl = REG_EXPR (loc);
861 HOST_WIDE_INT offset = REG_OFFSET (loc);
862 attrs node;
864 decl = var_debug_decl (decl);
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);
874 static int
875 get_init_value (dataflow_set *set, rtx loc, tree decl)
877 void **slot;
878 variable var;
879 int i;
880 int ret_val = VAR_INIT_STATUS_UNKNOWN;
882 if (! flag_var_tracking_uninit)
883 return VAR_INIT_STATUS_INITIALIZED;
885 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
886 NO_INSERT);
887 if (slot)
889 var = * (variable *) slot;
890 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
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))
896 ret_val = nextp->init;
897 break;
902 return ret_val;
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. */
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)
916 tree decl = REG_EXPR (loc);
917 HOST_WIDE_INT offset = REG_OFFSET (loc);
918 attrs node, next;
919 attrs *nextp;
921 decl = var_debug_decl (decl);
923 if (initialized == VAR_INIT_STATUS_UNKNOWN)
924 initialized = get_init_value (set, loc, decl);
926 nextp = &set->regs[REGNO (loc)];
927 for (node = *nextp; node; node = next)
929 next = node->next;
930 if (node->decl != decl || node->offset != offset)
932 delete_variable_part (set, node->loc, node->decl, node->offset);
933 pool_free (attrs_pool, node);
934 *nextp = next;
936 else
938 node->loc = loc;
939 nextp = &node->next;
942 if (modify)
943 clobber_variable_part (set, loc, decl, offset, set_src);
944 var_reg_set (set, loc, initialized, set_src);
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. */
951 static void
952 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
954 attrs *reg = &set->regs[REGNO (loc)];
955 attrs node, next;
957 if (clobber)
959 tree decl = REG_EXPR (loc);
960 HOST_WIDE_INT offset = REG_OFFSET (loc);
962 decl = var_debug_decl (decl);
964 clobber_variable_part (set, NULL, decl, offset, NULL);
967 for (node = *reg; node; node = next)
969 next = node->next;
970 delete_variable_part (set, node->loc, node->decl, node->offset);
971 pool_free (attrs_pool, node);
973 *reg = NULL;
976 /* Delete content of register with number REGNO in dataflow set SET. */
978 static void
979 var_regno_delete (dataflow_set *set, int regno)
981 attrs *reg = &set->regs[regno];
982 attrs node, next;
984 for (node = *reg; node; node = next)
986 next = node->next;
987 delete_variable_part (set, node->loc, node->decl, node->offset);
988 pool_free (attrs_pool, node);
990 *reg = NULL;
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. */
997 static void
998 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
999 rtx set_src)
1001 tree decl = MEM_EXPR (loc);
1002 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1004 decl = var_debug_decl (decl);
1006 set_variable_part (set, loc, decl, offset, initialized, set_src);
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. */
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)
1020 tree decl = MEM_EXPR (loc);
1021 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1023 decl = var_debug_decl (decl);
1025 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1026 initialized = get_init_value (set, loc, decl);
1028 if (modify)
1029 clobber_variable_part (set, NULL, decl, offset, set_src);
1030 var_mem_set (set, loc, initialized, set_src);
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. */
1037 static void
1038 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1040 tree decl = MEM_EXPR (loc);
1041 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
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);
1049 /* Initialize dataflow set SET to be empty.
1050 VARS_SIZE is the initial size of hash table VARS. */
1052 static void
1053 dataflow_set_init (dataflow_set *set, int vars_size)
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;
1061 /* Delete the contents of dataflow set SET. */
1063 static void
1064 dataflow_set_clear (dataflow_set *set)
1066 int i;
1068 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1069 attrs_list_clear (&set->regs[i]);
1071 vars_clear (set->vars);
1074 /* Copy the contents of dataflow set SRC to DST. */
1076 static void
1077 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
1079 int i;
1081 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1082 attrs_list_copy (&dst->regs[i], src->regs[i]);
1084 vars_copy (dst->vars, src->vars);
1085 dst->stack_adjust = src->stack_adjust;
1088 /* Information for merging lists of locations for a given offset of variable.
1090 struct variable_union_info
1092 /* Node of the location chain. */
1093 location_chain lc;
1095 /* The sum of positions in the input chains. */
1096 int pos;
1098 /* The position in the chains of SRC and DST dataflow sets. */
1099 int pos_src;
1100 int pos_dst;
1103 /* Compare function for qsort, order the structures by POS element. */
1105 static int
1106 variable_union_info_cmp_pos (const void *n1, const void *n2)
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;
1113 if (i1->pos != i2->pos)
1114 return i1->pos - i2->pos;
1116 return (i1->pos_dst - i2->pos_dst);
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. */
1129 static int
1130 variable_union (void **slot, void *data)
1132 variable src, dst, *dstp;
1133 dataflow_set *set = (dataflow_set *) data;
1134 int i, j, k;
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)
1142 src->refcount++;
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++)
1149 gcc_assert (!src->var_part[k].loc_chain
1150 == !src->var_part[k].cur_loc);
1151 if (src->var_part[k].loc_chain)
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;
1158 if (k < src->n_var_parts)
1160 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1162 if (! flag_var_tracking_uninit)
1163 status = VAR_INIT_STATUS_INITIALIZED;
1165 unshare_variable (set, src, status);
1167 else
1168 *dstp = src;
1170 /* Continue traversing the hash table. */
1171 return 1;
1173 else
1174 dst = *dstp;
1176 gcc_assert (src->n_var_parts);
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++)
1182 if (src->var_part[i].offset == dst->var_part[j].offset)
1184 i++;
1185 j++;
1187 else if (src->var_part[i].offset < dst->var_part[j].offset)
1188 i++;
1189 else
1190 j++;
1192 k += src->n_var_parts - i;
1193 k += dst->n_var_parts - j;
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);
1199 if (dst->refcount > 1 && dst->n_var_parts != k)
1201 enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
1203 if (! flag_var_tracking_uninit)
1204 status = VAR_INIT_STATUS_INITIALIZED;
1205 dst = unshare_variable (set, dst, status);
1208 i = src->n_var_parts - 1;
1209 j = dst->n_var_parts - 1;
1210 dst->n_var_parts = k;
1212 for (k--; k >= 0; k--)
1214 location_chain node, node2;
1216 if (i >= 0 && j >= 0
1217 && src->var_part[i].offset == dst->var_part[j].offset)
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;
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)
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)
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)))
1240 if (node2->init < node->init)
1241 node2->init = node->init;
1242 break;
1245 if (node || node2)
1246 dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
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);
1257 /* Fill in the locations from DST. */
1258 for (node = dst->var_part[j].loc_chain, jj = 0; node;
1259 node = node->next, jj++)
1261 vui[jj].lc = node;
1262 vui[jj].pos_dst = jj;
1264 /* Value larger than a sum of 2 valid positions. */
1265 vui[jj].pos_src = src_l + dst_l;
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++)
1273 /* Find location from NODE. */
1274 for (jj = 0; jj < dst_l; jj++)
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))
1281 vui[jj].pos_src = ii;
1282 break;
1285 if (jj >= dst_l) /* The location has not been found. */
1287 location_chain new_node;
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++;
1304 for (ii = 0; ii < src_l + dst_l; ii++)
1305 vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst;
1307 qsort (vui, n, sizeof (struct variable_union_info),
1308 variable_union_info_cmp_pos);
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;
1315 dst->var_part[k].loc_chain = vui[0].lc;
1316 dst->var_part[k].offset = dst->var_part[j].offset;
1318 free (vui);
1319 i--;
1320 j--;
1322 else if ((i >= 0 && j >= 0
1323 && src->var_part[i].offset < dst->var_part[j].offset)
1324 || i < 0)
1326 dst->var_part[k] = dst->var_part[j];
1327 j--;
1329 else if ((i >= 0 && j >= 0
1330 && src->var_part[i].offset > dst->var_part[j].offset)
1331 || j < 0)
1333 location_chain *nextp;
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)
1339 location_chain new_lc;
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;
1350 *nextp = new_lc;
1351 nextp = &new_lc->next;
1354 dst->var_part[k].offset = src->var_part[i].offset;
1355 i--;
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;
1366 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
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))
1373 if (node->init > node2->init)
1374 node2->init = node->init;
1378 /* Continue traversing the hash table. */
1379 return 1;
1382 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1384 static void
1385 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
1387 int i;
1389 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1390 attrs_list_union (&dst->regs[i], src->regs[i]);
1392 htab_traverse (src->vars, variable_union, dst);
1395 /* Flag whether two dataflow sets being compared contain different data. */
1396 static bool
1397 dataflow_set_different_value;
1399 static bool
1400 variable_part_different_p (variable_part *vp1, variable_part *vp2)
1402 location_chain lc1, lc2;
1404 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
1406 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
1408 if (REG_P (lc1->loc) && REG_P (lc2->loc))
1410 if (REGNO (lc1->loc) == REGNO (lc2->loc))
1411 break;
1413 if (rtx_equal_p (lc1->loc, lc2->loc))
1414 break;
1416 if (!lc2)
1417 return true;
1419 return false;
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. */
1426 static bool
1427 variable_different_p (variable var1, variable var2,
1428 bool compare_current_location)
1430 int i;
1432 if (var1 == var2)
1433 return false;
1435 if (var1->n_var_parts != var2->n_var_parts)
1436 return true;
1438 for (i = 0; i < var1->n_var_parts; i++)
1440 if (var1->var_part[i].offset != var2->var_part[i].offset)
1441 return true;
1442 if (compare_current_location)
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;
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;
1457 return false;
1460 /* Compare variable *SLOT with the same variable in hash table DATA
1461 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1463 static int
1464 dataflow_set_different_1 (void **slot, void *data)
1466 htab_t htab = (htab_t) data;
1467 variable var1, var2;
1469 var1 = *(variable *) slot;
1470 var2 = (variable) htab_find_with_hash (htab, var1->decl,
1471 VARIABLE_HASH_VAL (var1->decl));
1472 if (!var2)
1474 dataflow_set_different_value = true;
1476 /* Stop traversing the hash table. */
1477 return 0;
1480 if (variable_different_p (var1, var2, false))
1482 dataflow_set_different_value = true;
1484 /* Stop traversing the hash table. */
1485 return 0;
1488 /* Continue traversing the hash table. */
1489 return 1;
1492 /* Compare variable *SLOT with the same variable in hash table DATA
1493 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1495 static int
1496 dataflow_set_different_2 (void **slot, void *data)
1498 htab_t htab = (htab_t) data;
1499 variable var1, var2;
1501 var1 = *(variable *) slot;
1502 var2 = (variable) htab_find_with_hash (htab, var1->decl,
1503 VARIABLE_HASH_VAL (var1->decl));
1504 if (!var2)
1506 dataflow_set_different_value = true;
1508 /* Stop traversing the hash table. */
1509 return 0;
1512 /* If both variables are defined they have been already checked for
1513 equivalence. */
1514 gcc_assert (!variable_different_p (var1, var2, false));
1516 /* Continue traversing the hash table. */
1517 return 1;
1520 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1522 static bool
1523 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
1525 dataflow_set_different_value = false;
1527 htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars);
1528 if (!dataflow_set_different_value)
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);
1535 return dataflow_set_different_value;
1538 /* Free the contents of dataflow set SET. */
1540 static void
1541 dataflow_set_destroy (dataflow_set *set)
1543 int i;
1545 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1546 attrs_list_clear (&set->regs[i]);
1548 htab_delete (set->vars);
1549 set->vars = NULL;
1552 /* Return true if RTL X contains a SYMBOL_REF. */
1554 static bool
1555 contains_symbol_ref (rtx x)
1557 const char *fmt;
1558 RTX_CODE code;
1559 int i;
1561 if (!x)
1562 return false;
1564 code = GET_CODE (x);
1565 if (code == SYMBOL_REF)
1566 return true;
1568 fmt = GET_RTX_FORMAT (code);
1569 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1571 if (fmt[i] == 'e')
1573 if (contains_symbol_ref (XEXP (x, i)))
1574 return true;
1576 else if (fmt[i] == 'E')
1578 int j;
1579 for (j = 0; j < XVECLEN (x, i); j++)
1580 if (contains_symbol_ref (XVECEXP (x, i, j)))
1581 return true;
1585 return false;
1588 /* Shall EXPR be tracked? */
1590 static bool
1591 track_expr_p (tree expr)
1593 rtx decl_rtl;
1594 tree realdecl;
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;
1600 /* It also must have a name... */
1601 if (!DECL_NAME (expr))
1602 return 0;
1604 /* ... and a RTL assigned to it. */
1605 decl_rtl = DECL_RTL_IF_SET (expr);
1606 if (!decl_rtl)
1607 return 0;
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))
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;
1622 /* Do not track EXPR if REALDECL it should be ignored for debugging
1623 purposes. */
1624 if (DECL_IGNORED_P (realdecl))
1625 return 0;
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;
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.
1636 Example:
1637 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1638 char **_dl_argv;
1640 if (MEM_P (decl_rtl)
1641 && contains_symbol_ref (XEXP (decl_rtl, 0)))
1642 return 0;
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))
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;
1657 return 1;
1660 /* Determine whether a given LOC refers to the same variable part as
1661 EXPR+OFFSET. */
1663 static bool
1664 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
1666 tree expr2;
1667 HOST_WIDE_INT offset2;
1669 if (! DECL_P (expr))
1670 return false;
1672 if (REG_P (loc))
1674 expr2 = REG_EXPR (loc);
1675 offset2 = REG_OFFSET (loc);
1677 else if (MEM_P (loc))
1679 expr2 = MEM_EXPR (loc);
1680 offset2 = INT_MEM_OFFSET (loc);
1682 else
1683 return false;
1685 if (! expr2 || ! DECL_P (expr2))
1686 return false;
1688 expr = var_debug_decl (expr);
1689 expr2 = var_debug_decl (expr2);
1691 return (expr == expr2 && offset == offset2);
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.
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). */
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)
1708 enum machine_mode mode;
1710 if (expr == NULL || !track_expr_p (expr))
1711 return false;
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)))
1718 enum machine_mode pseudo_mode;
1720 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
1721 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
1723 offset += byte_lowpart_offset (pseudo_mode, mode);
1724 mode = pseudo_mode;
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)
1741 mode = DECL_MODE (expr);
1742 offset = 0;
1745 if (offset < 0 || offset >= MAX_VAR_PARTS)
1746 return false;
1748 if (mode_out)
1749 *mode_out = mode;
1750 if (offset_out)
1751 *offset_out = offset;
1752 return true;
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. */
1759 static rtx
1760 var_lowpart (enum machine_mode mode, rtx loc)
1762 unsigned int offset, reg_offset, regno;
1764 if (!REG_P (loc) && !MEM_P (loc))
1765 return NULL;
1767 if (GET_MODE (loc) == mode)
1768 return loc;
1770 offset = byte_lowpart_offset (mode, GET_MODE (loc));
1772 if (MEM_P (loc))
1773 return adjust_address_nv (loc, mode, offset);
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);
1781 /* Count uses (register and memory references) LOC which will be tracked.
1782 INSN is instruction which the LOC is part of. */
1784 static int
1785 count_uses (rtx *loc, void *insn)
1787 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1789 if (REG_P (*loc))
1791 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
1792 VTI (bb)->n_mos++;
1794 else if (MEM_P (*loc)
1795 && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
1796 false, NULL, NULL))
1798 VTI (bb)->n_mos++;
1801 return 0;
1804 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1806 static void
1807 count_uses_1 (rtx *x, void *insn)
1809 for_each_rtx (x, count_uses, insn);
1812 /* Count stores (register and memory references) LOC which will be tracked.
1813 INSN is instruction which the LOC is part of. */
1815 static void
1816 count_stores (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *insn)
1818 count_uses (&loc, insn);
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. */
1824 static int
1825 add_uses (rtx *loc, void *insn)
1827 enum machine_mode mode;
1829 if (REG_P (*loc))
1831 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1832 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1834 if (track_loc_p (*loc, REG_EXPR (*loc), REG_OFFSET (*loc),
1835 false, &mode, NULL))
1837 mo->type = MO_USE;
1838 mo->u.loc = var_lowpart (mode, *loc);
1840 else
1842 mo->type = MO_USE_NO_VAR;
1843 mo->u.loc = *loc;
1845 mo->insn = (rtx) insn;
1847 else if (MEM_P (*loc)
1848 && track_loc_p (*loc, MEM_EXPR (*loc), INT_MEM_OFFSET (*loc),
1849 false, &mode, NULL))
1851 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1852 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1854 mo->type = MO_USE;
1855 mo->u.loc = var_lowpart (mode, *loc);
1856 mo->insn = (rtx) insn;
1859 return 0;
1862 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1864 static void
1865 add_uses_1 (rtx *x, void *insn)
1867 for_each_rtx (x, add_uses, insn);
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. */
1874 static void
1875 add_stores (rtx loc, const_rtx expr, void *insn)
1877 enum machine_mode mode;
1879 if (REG_P (loc))
1881 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1882 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1884 if (GET_CODE (expr) == CLOBBER
1885 || !track_loc_p (loc, REG_EXPR (loc), REG_OFFSET (loc),
1886 true, &mode, NULL))
1888 mo->type = MO_CLOBBER;
1889 mo->u.loc = loc;
1891 else
1893 rtx src = NULL;
1895 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1896 src = var_lowpart (mode, SET_SRC (expr));
1897 loc = var_lowpart (mode, loc);
1899 if (src == NULL)
1901 mo->type = MO_SET;
1902 mo->u.loc = loc;
1904 else
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);
1915 mo->insn = (rtx) insn;
1917 else if (MEM_P (loc)
1918 && track_loc_p (loc, MEM_EXPR (loc), INT_MEM_OFFSET (loc),
1919 false, &mode, NULL))
1921 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
1922 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
1924 if (GET_CODE (expr) == CLOBBER)
1926 mo->type = MO_CLOBBER;
1927 mo->u.loc = var_lowpart (mode, loc);
1929 else
1931 rtx src = NULL;
1933 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
1934 src = var_lowpart (mode, SET_SRC (expr));
1935 loc = var_lowpart (mode, loc);
1937 if (src == NULL)
1939 mo->type = MO_SET;
1940 mo->u.loc = loc;
1942 else
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);
1955 mo->insn = (rtx) insn;
1959 static enum var_init_status
1960 find_src_status (dataflow_set *in, rtx src)
1962 tree decl = NULL_TREE;
1963 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
1965 if (! flag_var_tracking_uninit)
1966 status = VAR_INIT_STATUS_INITIALIZED;
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));
1973 if (src && decl)
1974 status = get_init_value (in, src, decl);
1976 return status;
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. */
1983 static rtx
1984 find_src_set_src (dataflow_set *set, rtx src)
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;
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));
1999 if (src && decl)
2001 slot = htab_find_slot_with_hash (set->vars, decl,
2002 VARIABLE_HASH_VAL (decl), NO_INSERT);
2004 if (slot)
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))
2013 set_src = nextp->set_src;
2014 found = true;
2020 return set_src;
2023 /* Compute the changes of variable locations in the basic block BB. */
2025 static bool
2026 compute_bb_dataflow (basic_block bb)
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;
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);
2038 n = VTI (bb)->n_mos;
2039 for (i = 0; i < n; i++)
2041 switch (VTI (bb)->mos[i].type)
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;
2049 case MO_USE:
2051 rtx loc = VTI (bb)->mos[i].u.loc;
2052 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
2054 if (! flag_var_tracking_uninit)
2055 status = VAR_INIT_STATUS_INITIALIZED;
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);
2062 break;
2064 case MO_SET:
2066 rtx loc = VTI (bb)->mos[i].u.loc;
2067 rtx set_src = NULL;
2069 if (GET_CODE (loc) == SET)
2071 set_src = SET_SRC (loc);
2072 loc = SET_DEST (loc);
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);
2082 break;
2084 case MO_COPY:
2086 rtx loc = VTI (bb)->mos[i].u.loc;
2087 enum var_init_status src_status;
2088 rtx set_src = NULL;
2090 if (GET_CODE (loc) == SET)
2092 set_src = SET_SRC (loc);
2093 loc = SET_DEST (loc);
2096 if (! flag_var_tracking_uninit)
2097 src_status = VAR_INIT_STATUS_INITIALIZED;
2098 else
2099 src_status = find_src_status (in, set_src);
2101 if (src_status == VAR_INIT_STATUS_UNKNOWN)
2102 src_status = find_src_status (out, set_src);
2104 set_src = find_src_set_src (in, set_src);
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);
2111 break;
2113 case MO_USE_NO_VAR:
2115 rtx loc = VTI (bb)->mos[i].u.loc;
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);
2122 break;
2124 case MO_CLOBBER:
2126 rtx loc = VTI (bb)->mos[i].u.loc;
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);
2133 break;
2135 case MO_ADJUST:
2136 out->stack_adjust += VTI (bb)->mos[i].u.adjust;
2137 break;
2141 changed = dataflow_set_different (&old_out, out);
2142 dataflow_set_destroy (&old_out);
2143 return changed;
2146 /* Find the locations of variables in the whole function. */
2148 static void
2149 vt_find_locations (void)
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;
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);
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);
2175 FOR_EACH_BB (bb)
2176 fibheap_insert (pending, bb_order[bb->index], bb);
2177 sbitmap_ones (in_pending);
2179 while (!fibheap_empty (pending))
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;
2188 sbitmap_zero (visited);
2190 while (!fibheap_empty (worklist))
2192 bb = (basic_block) fibheap_extract_min (worklist);
2193 RESET_BIT (in_worklist, bb->index);
2194 if (!TEST_BIT (visited, bb->index))
2196 bool changed;
2197 edge_iterator ei;
2199 SET_BIT (visited, bb->index);
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)
2205 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
2208 changed = compute_bb_dataflow (bb);
2209 if (changed)
2211 FOR_EACH_EDGE (e, ei, bb->succs)
2213 if (e->dest == EXIT_BLOCK_PTR)
2214 continue;
2216 if (e->dest == bb)
2217 continue;
2219 if (TEST_BIT (visited, e->dest->index))
2221 if (!TEST_BIT (in_pending, e->dest->index))
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);
2230 else if (!TEST_BIT (in_worklist, e->dest->index))
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);
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);
2251 /* Print the content of the LIST to dump file. */
2253 static void
2254 dump_attrs_list (attrs list)
2256 for (; list; list = list->next)
2258 print_mem_expr (dump_file, list->decl);
2259 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
2261 fprintf (dump_file, "\n");
2264 /* Print the information about variable *SLOT to dump file. */
2266 static int
2267 dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
2269 variable var = *(variable *) slot;
2270 int i;
2271 location_chain node;
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");
2280 for (i = 0; i < var->n_var_parts; i++)
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)
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);
2293 /* Continue traversing the hash table. */
2294 return 1;
2297 /* Print the information about variables from hash table VARS to dump file. */
2299 static void
2300 dump_vars (htab_t vars)
2302 if (htab_elements (vars) > 0)
2304 fprintf (dump_file, "Variables:\n");
2305 htab_traverse (vars, dump_variable, NULL);
2309 /* Print the dataflow set SET to dump file. */
2311 static void
2312 dump_dataflow_set (dataflow_set *set)
2314 int i;
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++)
2320 if (set->regs[i])
2322 fprintf (dump_file, "Reg %d:", i);
2323 dump_attrs_list (set->regs[i]);
2326 dump_vars (set->vars);
2327 fprintf (dump_file, "\n");
2330 /* Print the IN and OUT sets for each basic block to dump file. */
2332 static void
2333 dump_dataflow_sets (void)
2335 basic_block bb;
2337 FOR_EACH_BB (bb)
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);
2347 /* Add variable VAR to the hash table of changed variables and
2348 if it has no locations delete it from hash table HTAB. */
2350 static void
2351 variable_was_changed (variable var, htab_t htab)
2353 hashval_t hash = VARIABLE_HASH_VAL (var->decl);
2355 if (emit_notes)
2357 variable *slot;
2359 slot = (variable *) htab_find_slot_with_hash (changed_variables,
2360 var->decl, hash, INSERT);
2362 if (htab && var->n_var_parts == 0)
2364 variable empty_var;
2365 void **old;
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;
2373 old = htab_find_slot_with_hash (htab, var->decl, hash,
2374 NO_INSERT);
2375 if (old)
2376 htab_clear_slot (htab, old);
2378 else
2380 *slot = var;
2383 else
2385 gcc_assert (htab);
2386 if (var->n_var_parts == 0)
2388 void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
2389 NO_INSERT);
2390 if (slot)
2391 htab_clear_slot (htab, slot);
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. */
2401 static inline int
2402 find_variable_location_part (variable var, HOST_WIDE_INT offset,
2403 int *insertion_point)
2405 int pos, low, high;
2407 /* Find the location part. */
2408 low = 0;
2409 high = var->n_var_parts;
2410 while (low != high)
2412 pos = (low + high) / 2;
2413 if (var->var_part[pos].offset < offset)
2414 low = pos + 1;
2415 else
2416 high = pos;
2418 pos = low;
2420 if (insertion_point)
2421 *insertion_point = pos;
2423 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
2424 return pos;
2426 return -1;
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. */
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)
2437 int pos;
2438 location_chain node, next;
2439 location_chain *nextp;
2440 variable var;
2441 void **slot;
2443 slot = htab_find_slot_with_hash (set->vars, decl,
2444 VARIABLE_HASH_VAL (decl), INSERT);
2445 if (!*slot)
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;
2458 else
2460 int inspos = 0;
2462 var = (variable) *slot;
2464 pos = find_variable_location_part (var, offset, &inspos);
2466 if (pos >= 0)
2468 node = var->var_part[pos].loc_chain;
2470 if (node
2471 && ((REG_P (node->loc) && REG_P (loc)
2472 && REGNO (node->loc) == REGNO (loc))
2473 || rtx_equal_p (node->loc, loc)))
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;
2482 *slot = var;
2483 return;
2485 else
2487 /* We have to make a copy of a shared variable. */
2488 if (var->refcount > 1)
2489 var = unshare_variable (set, var, initialized);
2492 else
2494 /* We have not found the location part, new one will be created. */
2496 /* We have to make a copy of the shared variable. */
2497 if (var->refcount > 1)
2498 var = unshare_variable (set, var, initialized);
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);
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];
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;
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)
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))
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;
2535 else
2536 nextp = &node->next;
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;
2547 /* If no location was emitted do so. */
2548 if (var->var_part[pos].cur_loc == NULL)
2550 var->var_part[pos].cur_loc = loc;
2551 variable_was_changed (var, set->vars);
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. */
2560 static void
2561 clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
2562 HOST_WIDE_INT offset, rtx set_src)
2564 void **slot;
2566 if (! decl || ! DECL_P (decl))
2567 return;
2569 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2570 NO_INSERT);
2571 if (slot)
2573 variable var = (variable) *slot;
2574 int pos = find_variable_location_part (var, offset, NULL);
2576 if (pos >= 0)
2578 location_chain node, next;
2580 /* Remove the register locations from the dataflow set. */
2581 next = var->var_part[pos].loc_chain;
2582 for (node = next; node; node = next)
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)))
2591 if (REG_P (node->loc))
2593 attrs anode, anext;
2594 attrs *anextp;
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)
2603 anext = anode->next;
2604 if (anode->decl == decl
2605 && anode->offset == offset)
2607 pool_free (attrs_pool, anode);
2608 *anextp = anext;
2610 else
2611 anextp = &anode->next;
2615 delete_variable_part (set, node->loc, decl, offset);
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. */
2626 static void
2627 delete_variable_part (dataflow_set *set, rtx loc, tree decl,
2628 HOST_WIDE_INT offset)
2630 void **slot;
2632 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
2633 NO_INSERT);
2634 if (slot)
2636 variable var = (variable) *slot;
2637 int pos = find_variable_location_part (var, offset, NULL);
2639 if (pos >= 0)
2641 location_chain node, next;
2642 location_chain *nextp;
2643 bool changed;
2645 if (var->refcount > 1)
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)
2652 if ((REG_P (node->loc) && REG_P (loc)
2653 && REGNO (node->loc) == REGNO (loc))
2654 || rtx_equal_p (node->loc, loc))
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;
2665 /* Delete the location part. */
2666 nextp = &var->var_part[pos].loc_chain;
2667 for (node = *nextp; node; node = next)
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))
2674 pool_free (loc_chain_pool, node);
2675 *nextp = next;
2676 break;
2678 else
2679 nextp = &node->next;
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)))
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;
2695 else
2696 changed = false;
2698 if (var->var_part[pos].loc_chain == NULL)
2700 var->n_var_parts--;
2701 while (pos < var->n_var_parts)
2703 var->var_part[pos] = var->var_part[pos + 1];
2704 pos++;
2707 if (changed)
2708 variable_was_changed (var, set->vars);
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. */
2717 static int
2718 emit_note_insn_var_location (void **varp, void *data)
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];
2732 gcc_assert (var->decl);
2734 if (! flag_var_tracking_uninit)
2735 initialized = VAR_INIT_STATUS_INITIALIZED;
2737 complete = true;
2738 last_limit = 0;
2739 n_var_parts = 0;
2740 for (i = 0; i < var->n_var_parts; i++)
2742 enum machine_mode mode, wider_mode;
2744 if (last_limit < var->var_part[i].offset)
2746 complete = false;
2747 break;
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);
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)
2769 rtx new_loc = NULL;
2770 rtx loc2 = var->var_part[j].loc_chain->loc;
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))
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)
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]);
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)
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);
2814 if (new_loc)
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;
2822 ++n_var_parts;
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;
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);
2833 if (! flag_var_tracking_uninit)
2834 initialized = VAR_INIT_STATUS_INITIALIZED;
2836 if (!complete)
2838 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2839 NULL_RTX, (int) initialized);
2841 else if (n_var_parts == 1)
2843 rtx expr_list
2844 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
2846 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
2847 expr_list,
2848 (int) initialized);
2850 else if (n_var_parts)
2852 rtx parallel;
2854 for (i = 0; i < n_var_parts; i++)
2855 loc[i]
2856 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
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);
2865 htab_clear_slot (changed_variables, varp);
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)
2872 pool_free (var_pool, var);
2875 /* Continue traversing the hash table. */
2876 return 1;
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. */
2883 static void
2884 emit_notes_for_changes (rtx insn, enum emit_note_where where)
2886 emit_note_data data;
2888 data.insn = insn;
2889 data.where = where;
2890 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
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. */
2896 static int
2897 emit_notes_for_differences_1 (void **slot, void *data)
2899 htab_t new_vars = (htab_t) data;
2900 variable old_var, new_var;
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));
2906 if (!new_var)
2908 /* Variable has disappeared. */
2909 variable empty_var;
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);
2917 else if (variable_different_p (old_var, new_var, true))
2919 variable_was_changed (new_var, NULL);
2922 /* Continue traversing the hash table. */
2923 return 1;
2926 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2927 table DATA. */
2929 static int
2930 emit_notes_for_differences_2 (void **slot, void *data)
2932 htab_t old_vars = (htab_t) data;
2933 variable old_var, new_var;
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)
2940 /* Variable has appeared. */
2941 variable_was_changed (new_var, NULL);
2944 /* Continue traversing the hash table. */
2945 return 1;
2948 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2949 NEW_SET. */
2951 static void
2952 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
2953 dataflow_set *new_set)
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);
2960 /* Emit the notes for changes of location parts in the basic block BB. */
2962 static void
2963 emit_notes_in_bb (basic_block bb)
2965 int i;
2966 dataflow_set set;
2968 dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3);
2969 dataflow_set_copy (&set, &VTI (bb)->in);
2971 for (i = 0; i < VTI (bb)->n_mos; i++)
2973 rtx insn = VTI (bb)->mos[i].insn;
2975 switch (VTI (bb)->mos[i].type)
2977 case MO_CALL:
2979 int r;
2981 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
2982 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
2984 var_regno_delete (&set, r);
2986 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
2988 break;
2990 case MO_USE:
2992 rtx loc = VTI (bb)->mos[i].u.loc;
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);
3002 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3004 break;
3006 case MO_SET:
3008 rtx loc = VTI (bb)->mos[i].u.loc;
3009 rtx set_src = NULL;
3011 if (GET_CODE (loc) == SET)
3013 set_src = SET_SRC (loc);
3014 loc = SET_DEST (loc);
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);
3024 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3026 break;
3028 case MO_COPY:
3030 rtx loc = VTI (bb)->mos[i].u.loc;
3031 enum var_init_status src_status;
3032 rtx set_src = NULL;
3034 if (GET_CODE (loc) == SET)
3036 set_src = SET_SRC (loc);
3037 loc = SET_DEST (loc);
3040 src_status = find_src_status (&set, set_src);
3041 set_src = find_src_set_src (&set, set_src);
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);
3048 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3050 break;
3052 case MO_USE_NO_VAR:
3054 rtx loc = VTI (bb)->mos[i].u.loc;
3056 if (REG_P (loc))
3057 var_reg_delete (&set, loc, false);
3058 else
3059 var_mem_delete (&set, loc, false);
3061 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
3063 break;
3065 case MO_CLOBBER:
3067 rtx loc = VTI (bb)->mos[i].u.loc;
3069 if (REG_P (loc))
3070 var_reg_delete (&set, loc, true);
3071 else
3072 var_mem_delete (&set, loc, true);
3074 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN);
3076 break;
3078 case MO_ADJUST:
3079 set.stack_adjust += VTI (bb)->mos[i].u.adjust;
3080 break;
3083 dataflow_set_destroy (&set);
3086 /* Emit notes for the whole function. */
3088 static void
3089 vt_emit_notes (void)
3091 basic_block bb;
3092 dataflow_set *last_out;
3093 dataflow_set empty;
3095 gcc_assert (!htab_elements (changed_variables));
3097 /* Enable emitting notes by functions (mainly by set_variable_part and
3098 delete_variable_part). */
3099 emit_notes = true;
3101 dataflow_set_init (&empty, 7);
3102 last_out = &empty;
3104 FOR_EACH_BB (bb)
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);
3110 /* Emit the notes for the changes in the basic block itself. */
3111 emit_notes_in_bb (bb);
3113 last_out = &VTI (bb)->out;
3115 dataflow_set_destroy (&empty);
3116 emit_notes = false;
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. */
3122 static bool
3123 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
3125 if (REG_P (rtl))
3127 if (REG_ATTRS (rtl))
3129 *declp = REG_EXPR (rtl);
3130 *offsetp = REG_OFFSET (rtl);
3131 return true;
3134 else if (MEM_P (rtl))
3136 if (MEM_ATTRS (rtl))
3138 *declp = MEM_EXPR (rtl);
3139 *offsetp = INT_MEM_OFFSET (rtl);
3140 return true;
3143 return false;
3146 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3148 static void
3149 vt_add_function_parameters (void)
3151 tree parm;
3153 for (parm = DECL_ARGUMENTS (current_function_decl);
3154 parm; parm = TREE_CHAIN (parm))
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;
3163 if (TREE_CODE (parm) != PARM_DECL)
3164 continue;
3166 if (!DECL_NAME (parm))
3167 continue;
3169 if (!decl_rtl || !incoming)
3170 continue;
3172 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
3173 continue;
3175 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
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));
3183 if (!decl)
3184 continue;
3186 if (parm != decl)
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;
3197 if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
3198 continue;
3200 out = &VTI (ENTRY_BLOCK_PTR)->out;
3202 if (REG_P (incoming))
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);
3211 else if (MEM_P (incoming))
3213 incoming = var_lowpart (mode, incoming);
3214 set_variable_part (out, incoming, parm, offset,
3215 VAR_INIT_STATUS_INITIALIZED, NULL);
3220 /* Allocate and initialize the data structures for variable tracking
3221 and parse the RTL to get the micro operations. */
3223 static void
3224 vt_initialize (void)
3226 basic_block bb;
3228 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
3230 FOR_EACH_BB (bb)
3232 rtx insn;
3233 HOST_WIDE_INT pre, post = 0;
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))
3240 if (INSN_P (insn))
3242 if (!frame_pointer_needed)
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++;
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++;
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))
3263 if (INSN_P (insn))
3265 int n1, n2;
3267 if (!frame_pointer_needed)
3269 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
3270 if (pre)
3272 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3274 mo->type = MO_ADJUST;
3275 mo->u.adjust = pre;
3276 mo->insn = insn;
3280 n1 = VTI (bb)->n_mos;
3281 note_uses (&PATTERN (insn), add_uses_1, insn);
3282 n2 = VTI (bb)->n_mos - 1;
3284 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
3285 while (n1 < n2)
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)
3293 micro_operation sw;
3295 sw = VTI (bb)->mos[n1];
3296 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3297 VTI (bb)->mos[n2] = sw;
3301 if (CALL_P (insn))
3303 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3305 mo->type = MO_CALL;
3306 mo->insn = insn;
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;
3316 /* Order the MO_CLOBBERs to be before MO_SETs. */
3317 while (n1 < n2)
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)
3326 micro_operation sw;
3328 sw = VTI (bb)->mos[n1];
3329 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
3330 VTI (bb)->mos[n2] = sw;
3334 if (!frame_pointer_needed && post)
3336 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
3338 mo->type = MO_ADJUST;
3339 mo->u.adjust = post;
3340 mo->insn = insn;
3346 /* Init the IN and OUT sets. */
3347 FOR_ALL_BB (bb)
3349 VTI (bb)->visited = false;
3350 dataflow_set_init (&VTI (bb)->in, 7);
3351 dataflow_set_init (&VTI (bb)->out, 7);
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 ();
3366 /* Free the data structures needed for variable tracking. */
3368 static void
3369 vt_finalize (void)
3371 basic_block bb;
3373 FOR_EACH_BB (bb)
3375 free (VTI (bb)->mos);
3378 FOR_ALL_BB (bb)
3380 dataflow_set_destroy (&VTI (bb)->in);
3381 dataflow_set_destroy (&VTI (bb)->out);
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);
3390 /* The entry point to variable tracking pass. */
3392 unsigned int
3393 variable_tracking_main (void)
3395 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
3396 return 0;
3398 mark_dfs_back_edges ();
3399 vt_initialize ();
3400 if (!frame_pointer_needed)
3402 if (!vt_stack_adjustments ())
3404 vt_finalize ();
3405 return 0;
3409 vt_find_locations ();
3410 vt_emit_notes ();
3412 if (dump_file && (dump_flags & TDF_DETAILS))
3414 dump_dataflow_sets ();
3415 dump_flow_info (dump_file, dump_flags);
3418 vt_finalize ();
3419 return 0;
3422 static bool
3423 gate_handle_var_tracking (void)
3425 return (flag_var_tracking);
3430 struct rtl_opt_pass pass_variable_tracking =
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 */