1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
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)
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
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
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
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
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).
91 #include "coretypes.h"
95 #include "hard-reg-set.h"
96 #include "basic-block.h"
99 #include "insn-config.h"
102 #include "alloc-pool.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. */
127 EMIT_NOTE_BEFORE_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
;
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
143 /* Stack adjustment. */
144 HOST_WIDE_INT adjust
;
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
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. */
162 /* Where the note will be emitted (before/after insn)? */
163 enum emit_note_where where
;
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. */
178 /* The declaration corresponding to LOC. */
181 /* Offset from start of DECL. */
182 HOST_WIDE_INT offset
;
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. */
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. */
205 /* The array of micro operations. */
206 micro_operation
*mos
;
208 /* The IN and OUT set for dataflow analysis. */
212 /* Has the block been visited in DFS? */
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). */
225 /* The "value" stored in this location. */
229 enum var_init_status init
;
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. */
241 /* The offset in the variable. */
242 HOST_WIDE_INT offset
;
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. */
254 /* Reference count. */
257 /* Number of variable parts. */
260 /* The variable parts. */
261 variable_part var_part
[MAX_VAR_PARTS
];
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
*,
292 static void insn_stack_adjust_offset_pre_post (rtx
, 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
,
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. */
379 stack_adjust_offset_pre_post (rtx pattern
, HOST_WIDE_INT
*pre
,
382 rtx src
= SET_SRC (pattern
);
383 rtx dest
= SET_DEST (pattern
);
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
)
396 *post
+= INTVAL (XEXP (src
, 1));
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
);
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
);
420 *post
-= INTVAL (val
);
426 if (XEXP (src
, 0) == stack_pointer_rtx
)
428 *pre
+= GET_MODE_SIZE (GET_MODE (dest
));
434 if (XEXP (src
, 0) == stack_pointer_rtx
)
436 *post
+= GET_MODE_SIZE (GET_MODE (dest
));
442 if (XEXP (src
, 0) == stack_pointer_rtx
)
444 *pre
-= GET_MODE_SIZE (GET_MODE (dest
));
450 if (XEXP (src
, 0) == stack_pointer_rtx
)
452 *post
-= GET_MODE_SIZE (GET_MODE (dest
));
463 /* Given an INSN, calculate the amount of stack adjustment it contains
464 PRE- and POST-modifying stack pointer. */
467 insn_stack_adjust_offset_pre_post (rtx insn
, HOST_WIDE_INT
*pre
,
475 pattern
= PATTERN (insn
);
476 if (RTX_FRAME_RELATED_P (insn
))
478 rtx expr
= find_reg_note (insn
, REG_FRAME_RELATED_EXPR
, NULL_RTX
);
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
)
490 /* There may be stack adjustments inside compound insns. Search
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. */
501 bb_stack_adjust_offset (basic_block bb
)
503 HOST_WIDE_INT offset
;
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. */
528 vt_stack_adjustments (void)
530 edge_iterator
*stack
;
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);
541 /* Push the first edge on to the stack. */
542 stack
[sp
++] = ei_start (ENTRY_BLOCK_PTR
->succs
);
550 /* Look at the edge on the top of the stack. */
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
);
569 /* Check whether the adjustments on the edges are the same. */
570 if (VTI (dest
)->in
.stack_adjust
!= VTI (src
)->out
.stack_adjust
)
576 if (! ei_one_before_end_p (ei
))
577 /* Go to the next edge. */
578 ei_next (&stack
[sp
- 1]);
580 /* Return to previous level if there are no more edges. */
589 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
590 to the argument pointer. Return the new rtx. */
593 adjust_stack_reference (rtx mem
, HOST_WIDE_INT adjustment
)
597 #ifdef FRAME_POINTER_CFA_OFFSET
598 adjustment
-= FRAME_POINTER_CFA_OFFSET (current_function_decl
);
599 cfa
= plus_constant (frame_pointer_rtx
, adjustment
);
601 adjustment
-= ARG_POINTER_CFA_OFFSET (current_function_decl
);
602 cfa
= plus_constant (arg_pointer_rtx
, adjustment
);
605 addr
= replace_rtx (copy_rtx (XEXP (mem
, 0)), stack_pointer_rtx
, cfa
);
606 tmp
= simplify_rtx (addr
);
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. */
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. */
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). */
638 variable_htab_free (void *elem
)
641 variable var
= (variable
) elem
;
642 location_chain node
, next
;
644 gcc_assert (var
->refcount
> 0);
647 if (var
->refcount
> 0)
650 for (i
= 0; i
< var
->n_var_parts
; i
++)
652 for (node
= var
->var_part
[i
].loc_chain
; node
; 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. */
665 init_attrs_list_set (attrs
*set
)
669 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
673 /* Make the list *LISTP empty. */
676 attrs_list_clear (attrs
*listp
)
680 for (list
= *listp
; list
; list
= next
)
683 pool_free (attrs_pool
, list
);
688 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
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
)
699 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
702 attrs_list_insert (attrs
*listp
, tree decl
, HOST_WIDE_INT offset
, rtx loc
)
706 list
= (attrs
) pool_alloc (attrs_pool
);
709 list
->offset
= offset
;
714 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
717 attrs_list_copy (attrs
*dstp
, attrs src
)
721 attrs_list_clear (dstp
);
722 for (; src
; src
= src
->next
)
724 n
= (attrs
) pool_alloc (attrs_pool
);
727 n
->offset
= src
->offset
;
733 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
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. */
748 vars_clear (htab_t vars
)
753 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
756 unshare_variable (dataflow_set
*set
, variable var
,
757 enum var_init_status initialized
)
763 new_var
= (variable
) pool_alloc (var_pool
);
764 new_var
->decl
= var
->decl
;
765 new_var
->refcount
= 1;
767 new_var
->n_var_parts
= var
->n_var_parts
;
769 for (i
= 0; i
< var
->n_var_parts
; i
++)
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
);
782 if (node
->init
> initialized
)
783 new_lc
->init
= node
->init
;
785 new_lc
->init
= initialized
;
786 if (node
->set_src
&& !(MEM_P (node
->set_src
)))
787 new_lc
->set_src
= node
->set_src
;
789 new_lc
->set_src
= NULL
;
790 new_lc
->loc
= node
->loc
;
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
;
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
),
811 /* Add a variable from *SLOT to hash table DATA and increase its reference
815 vars_copy_1 (void **slot
, void *data
)
817 htab_t dst
= (htab_t
) data
;
820 src
= *(variable
*) slot
;
823 dstp
= (variable
*) htab_find_slot_with_hash (dst
, src
->decl
,
824 VARIABLE_HASH_VAL (src
->decl
),
828 /* Continue traversing the hash table. */
832 /* Copy all variables from hash table SRC to hash table DST. */
835 vars_copy (htab_t dst
, htab_t src
)
838 htab_traverse (src
, vars_copy_1
, dst
);
841 /* Map a decl to its main debug decl. */
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
);
854 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
857 var_reg_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
860 tree decl
= REG_EXPR (loc
);
861 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
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
)
870 attrs_list_insert (&set
->regs
[REGNO (loc
)], decl
, offset
, loc
);
871 set_variable_part (set
, loc
, decl
, offset
, initialized
, set_src
);
874 static enum var_init_status
875 get_init_value (dataflow_set
*set
, rtx loc
, tree decl
)
880 enum var_init_status 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
),
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
;
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
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
);
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
)
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
);
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
952 var_reg_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
954 attrs
*reg
= &set
->regs
[REGNO (loc
)];
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
)
970 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
971 pool_free (attrs_pool
, node
);
976 /* Delete content of register with number REGNO in dataflow set SET. */
979 var_regno_delete (dataflow_set
*set
, int regno
)
981 attrs
*reg
= &set
->regs
[regno
];
984 for (node
= *reg
; node
; node
= next
)
987 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
988 pool_free (attrs_pool
, node
);
993 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
995 Adjust the address first if it is stack pointer based. */
998 var_mem_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
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. */
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
);
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. */
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
);
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. */
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. */
1064 dataflow_set_clear (dataflow_set
*set
)
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. */
1077 dataflow_set_copy (dataflow_set
*dst
, dataflow_set
*src
)
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. */
1095 /* The sum of positions in the input chains. */
1098 /* The position in the chains of SRC and DST dataflow sets. */
1103 /* Compare function for qsort, order the structures by POS element. */
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. */
1130 variable_union (void **slot
, void *data
)
1132 variable src
, dst
, *dstp
;
1133 dataflow_set
*set
= (dataflow_set
*) data
;
1136 src
= *(variable
*) slot
;
1137 dstp
= (variable
*) htab_find_slot_with_hash (set
->vars
, src
->decl
,
1138 VARIABLE_HASH_VAL (src
->decl
),
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
)
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
);
1170 /* Continue traversing the hash table. */
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
)
1187 else if (src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
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. */
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
;
1246 dst
= unshare_variable (set
, dst
, VAR_INIT_STATUS_UNKNOWN
);
1250 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1253 for (node
= dst
->var_part
[j
].loc_chain
; node
; node
= node
->next
)
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
++)
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. */
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
;
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
;
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
;
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
;
1322 else if ((i
>= 0 && j
>= 0
1323 && src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1326 dst
->var_part
[k
] = dst
->var_part
[j
];
1329 else if ((i
>= 0 && j
>= 0
1330 && src
->var_part
[i
].offset
> dst
->var_part
[j
].offset
)
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
;
1347 new_lc
->set_src
= node
->set_src
;
1348 new_lc
->loc
= node
->loc
;
1351 nextp
= &new_lc
->next
;
1354 dst
->var_part
[k
].offset
= src
->var_part
[i
].offset
;
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
;
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. */
1382 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1385 dataflow_set_union (dataflow_set
*dst
, dataflow_set
*src
)
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. */
1397 dataflow_set_different_value
;
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
))
1413 if (rtx_equal_p (lc1
->loc
, lc2
->loc
))
1422 /* Return true if variables VAR1 and VAR2 are different.
1423 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1427 variable_different_p (variable var1
, variable var2
,
1428 bool compare_current_location
)
1435 if (var1
->n_var_parts
!= var2
->n_var_parts
)
1438 for (i
= 0; i
< var1
->n_var_parts
; i
++)
1440 if (var1
->var_part
[i
].offset
!= var2
->var_part
[i
].offset
)
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
)))
1452 if (variable_part_different_p (&var1
->var_part
[i
], &var2
->var_part
[i
]))
1454 if (variable_part_different_p (&var2
->var_part
[i
], &var1
->var_part
[i
]))
1460 /* Compare variable *SLOT with the same variable in hash table DATA
1461 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
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
));
1474 dataflow_set_different_value
= true;
1476 /* Stop traversing the hash table. */
1480 if (variable_different_p (var1
, var2
, false))
1482 dataflow_set_different_value
= true;
1484 /* Stop traversing the hash table. */
1488 /* Continue traversing the hash table. */
1492 /* Compare variable *SLOT with the same variable in hash table DATA
1493 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
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
));
1506 dataflow_set_different_value
= true;
1508 /* Stop traversing the hash table. */
1512 /* If both variables are defined they have been already checked for
1514 gcc_assert (!variable_different_p (var1
, var2
, false));
1516 /* Continue traversing the hash table. */
1520 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
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. */
1541 dataflow_set_destroy (dataflow_set
*set
)
1545 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1546 attrs_list_clear (&set
->regs
[i
]);
1548 htab_delete (set
->vars
);
1552 /* Return true if RTL X contains a SYMBOL_REF. */
1555 contains_symbol_ref (rtx x
)
1564 code
= GET_CODE (x
);
1565 if (code
== SYMBOL_REF
)
1568 fmt
= GET_RTX_FORMAT (code
);
1569 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1573 if (contains_symbol_ref (XEXP (x
, i
)))
1576 else if (fmt
[i
] == 'E')
1579 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1580 if (contains_symbol_ref (XVECEXP (x
, i
, j
)))
1588 /* Shall EXPR be tracked? */
1591 track_expr_p (tree expr
)
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
)
1600 /* It also must have a name... */
1601 if (!DECL_NAME (expr
))
1604 /* ... and a RTL assigned to it. */
1605 decl_rtl
= DECL_RTL_IF_SET (expr
);
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
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
))
1622 /* Do not track EXPR if REALDECL it should be ignored for debugging
1624 if (DECL_IGNORED_P (realdecl
))
1627 /* Do not track global variables until we are able to emit correct location
1629 if (TREE_STATIC (realdecl
))
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.
1637 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1640 if (MEM_P (decl_rtl
)
1641 && contains_symbol_ref (XEXP (decl_rtl
, 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
)))
1652 if (MEM_SIZE (decl_rtl
)
1653 && INTVAL (MEM_SIZE (decl_rtl
)) > MAX_VAR_PARTS
)
1660 /* Determine whether a given LOC refers to the same variable part as
1664 same_variable_part_p (rtx loc
, tree expr
, HOST_WIDE_INT offset
)
1667 HOST_WIDE_INT offset2
;
1669 if (! DECL_P (expr
))
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
);
1685 if (! expr2
|| ! DECL_P (expr2
))
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). */
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
))
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
);
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
1735 if ((GET_MODE_SIZE (mode
) > GET_MODE_SIZE (DECL_MODE (expr
))
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
);
1745 if (offset
< 0 || offset
>= MAX_VAR_PARTS
)
1751 *offset_out
= offset
;
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. */
1760 var_lowpart (enum machine_mode mode
, rtx loc
)
1762 unsigned int offset
, reg_offset
, regno
;
1764 if (!REG_P (loc
) && !MEM_P (loc
))
1767 if (GET_MODE (loc
) == mode
)
1770 offset
= byte_lowpart_offset (mode
, GET_MODE (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
),
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. */
1785 count_uses (rtx
*loc
, void *insn
)
1787 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1791 gcc_assert (REGNO (*loc
) < FIRST_PSEUDO_REGISTER
);
1794 else if (MEM_P (*loc
)
1795 && track_loc_p (*loc
, MEM_EXPR (*loc
), INT_MEM_OFFSET (*loc
),
1804 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
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. */
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. */
1825 add_uses (rtx
*loc
, void *insn
)
1827 enum machine_mode mode
;
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
))
1838 mo
->u
.loc
= var_lowpart (mode
, *loc
);
1842 mo
->type
= MO_USE_NO_VAR
;
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
++;
1855 mo
->u
.loc
= var_lowpart (mode
, *loc
);
1856 mo
->insn
= (rtx
) insn
;
1862 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
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. */
1875 add_stores (rtx loc
, const_rtx expr
, void *insn
)
1877 enum machine_mode mode
;
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
),
1888 mo
->type
= MO_CLOBBER
;
1895 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
1896 src
= var_lowpart (mode
, SET_SRC (expr
));
1897 loc
= var_lowpart (mode
, loc
);
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
)))
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
);
1933 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
1934 src
= var_lowpart (mode
, SET_SRC (expr
));
1935 loc
= var_lowpart (mode
, loc
);
1944 if (SET_SRC (expr
) != src
)
1945 expr
= gen_rtx_SET (VOIDmode
, loc
, src
);
1946 if (same_variable_part_p (SET_SRC (expr
),
1948 INT_MEM_OFFSET (loc
)))
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
));
1974 status
= get_init_value (in
, src
, decl
);
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. */
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". */
1990 location_chain nextp
;
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
));
2001 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
2002 VARIABLE_HASH_VAL (decl
), NO_INSERT
);
2006 var
= *(variable
*) slot
;
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
;
2023 /* Compute the changes of variable locations in the basic block BB. */
2026 compute_bb_dataflow (basic_block bb
)
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
)
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
);
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
);
2066 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2069 if (GET_CODE (loc
) == SET
)
2071 set_src
= SET_SRC (loc
);
2072 loc
= SET_DEST (loc
);
2076 var_reg_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2078 else if (MEM_P (loc
))
2079 var_mem_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2086 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2087 enum var_init_status src_status
;
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
;
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
);
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
);
2115 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2118 var_reg_delete (out
, loc
, false);
2119 else if (MEM_P (loc
))
2120 var_mem_delete (out
, loc
, false);
2126 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2129 var_reg_delete (out
, loc
, true);
2130 else if (MEM_P (loc
))
2131 var_mem_delete (out
, loc
, true);
2136 out
->stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
2141 changed
= dataflow_set_different (&old_out
, out
);
2142 dataflow_set_destroy (&old_out
);
2146 /* Find the locations of variables in the whole function. */
2149 vt_find_locations (void)
2151 fibheap_t worklist
, pending
, fibheap_swap
;
2152 sbitmap visited
, in_worklist
, in_pending
, sbitmap_swap
;
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
;
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
);
2176 fibheap_insert (pending
, bb_order
[bb
->index
], bb
);
2177 sbitmap_ones (in_pending
);
2179 while (!fibheap_empty (pending
))
2181 fibheap_swap
= pending
;
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
))
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
);
2211 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
2213 if (e
->dest
== EXIT_BLOCK_PTR
)
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
],
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
],
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. */
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. */
2267 dump_variable (void **slot
, void *data ATTRIBUTE_UNUSED
)
2269 variable var
= *(variable
*) slot
;
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
));
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. */
2297 /* Print the information about variables from hash table VARS to dump file. */
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. */
2312 dump_dataflow_set (dataflow_set
*set
)
2316 fprintf (dump_file
, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC
"\n",
2318 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; 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. */
2333 dump_dataflow_sets (void)
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. */
2351 variable_was_changed (variable var
, htab_t htab
)
2353 hashval_t hash
= VARIABLE_HASH_VAL (var
->decl
);
2359 slot
= (variable
*) htab_find_slot_with_hash (changed_variables
,
2360 var
->decl
, hash
, INSERT
);
2362 if (htab
&& var
->n_var_parts
== 0)
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;
2373 old
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
2376 htab_clear_slot (htab
, old
);
2386 if (var
->n_var_parts
== 0)
2388 void **slot
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
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. */
2402 find_variable_location_part (variable var
, HOST_WIDE_INT offset
,
2403 int *insertion_point
)
2407 /* Find the location part. */
2409 high
= var
->n_var_parts
;
2412 pos
= (low
+ high
) / 2;
2413 if (var
->var_part
[pos
].offset
< offset
)
2420 if (insertion_point
)
2421 *insertion_point
= pos
;
2423 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
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. */
2434 set_variable_part (dataflow_set
*set
, rtx loc
, tree decl
, HOST_WIDE_INT offset
,
2435 enum var_init_status initialized
, rtx set_src
)
2438 location_chain node
, next
;
2439 location_chain
*nextp
;
2443 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
2444 VARIABLE_HASH_VAL (decl
), INSERT
);
2447 /* Create new variable information. */
2448 var
= (variable
) pool_alloc (var_pool
);
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
;
2462 var
= (variable
) *slot
;
2464 pos
= find_variable_location_part (var
, offset
, &inspos
);
2468 node
= var
->var_part
[pos
].loc_chain
;
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
2477 if (node
->init
< initialized
)
2478 node
->init
= initialized
;
2479 if (set_src
!= NULL
)
2480 node
->set_src
= set_src
;
2487 /* We have to make a copy of a shared variable. */
2488 if (var
->refcount
> 1)
2489 var
= unshare_variable (set
, var
, initialized
);
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];
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
)
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
);
2536 nextp
= &node
->next
;
2539 /* Add the location to the beginning. */
2540 node
= (location_chain
) pool_alloc (loc_chain_pool
);
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
2561 clobber_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2562 HOST_WIDE_INT offset
, rtx set_src
)
2566 if (! decl
|| ! DECL_P (decl
))
2569 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2573 variable var
= (variable
) *slot
;
2574 int pos
= find_variable_location_part (var
, offset
, NULL
);
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
)
2585 if (node
->loc
!= loc
2586 && (!flag_var_tracking_uninit
2589 || !rtx_equal_p (set_src
, node
->set_src
)))
2591 if (REG_P (node
->loc
))
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
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
);
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. */
2627 delete_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2628 HOST_WIDE_INT offset
)
2632 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2636 variable var
= (variable
) *slot
;
2637 int pos
= find_variable_location_part (var
, offset
, NULL
);
2641 location_chain node
, next
;
2642 location_chain
*nextp
;
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
;
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
);
2665 /* Delete the location part. */
2666 nextp
= &var
->var_part
[pos
].loc_chain
;
2667 for (node
= *nextp
; node
; 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
);
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
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
)))
2692 if (var
->var_part
[pos
].loc_chain
)
2693 var
->var_part
[pos
].cur_loc
= var
->var_part
[pos
].loc_chain
->loc
;
2698 if (var
->var_part
[pos
].loc_chain
== NULL
)
2701 while (pos
< var
->n_var_parts
)
2703 var
->var_part
[pos
] = var
->var_part
[pos
+ 1];
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. */
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
;
2724 int i
, j
, n_var_parts
;
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
;
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
)
2749 else if (last_limit
> var
->var_part
[i
].offset
)
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
)
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
)
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
]))
2778 if (! WORDS_BIG_ENDIAN
&& ! BYTES_BIG_ENDIAN
)
2779 new_loc
= simplify_subreg (wider_mode
, loc
[n_var_parts
],
2781 else if (WORDS_BIG_ENDIAN
&& BYTES_BIG_ENDIAN
)
2782 new_loc
= simplify_subreg (wider_mode
, loc2
, mode
, 0);
2785 if (!REG_P (new_loc
)
2786 || REGNO (new_loc
) != REGNO (loc
[n_var_parts
]))
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))
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
],
2816 loc
[n_var_parts
] = new_loc
;
2818 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
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
))
2828 if (where
== EMIT_NOTE_AFTER_INSN
)
2829 note
= emit_note_after (NOTE_INSN_VAR_LOCATION
, insn
);
2831 note
= emit_note_before (NOTE_INSN_VAR_LOCATION
, insn
);
2833 if (! flag_var_tracking_uninit
)
2834 initialized
= VAR_INIT_STATUS_INITIALIZED
;
2838 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2839 NULL_RTX
, (int) initialized
);
2841 else if (n_var_parts
== 1)
2844 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[0], GEN_INT (offsets
[0]));
2846 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2850 else if (n_var_parts
)
2854 for (i
= 0; i
< n_var_parts
; 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
,
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. */
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. */
2884 emit_notes_for_changes (rtx insn
, enum emit_note_where where
)
2886 emit_note_data data
;
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. */
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
));
2908 /* Variable has disappeared. */
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. */
2926 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
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
));
2940 /* Variable has appeared. */
2941 variable_was_changed (new_var
, NULL
);
2944 /* Continue traversing the hash table. */
2948 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
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. */
2963 emit_notes_in_bb (basic_block bb
)
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
)
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
);
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
);
3000 var_mem_set (&set
, loc
, status
, NULL
);
3002 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3008 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3011 if (GET_CODE (loc
) == SET
)
3013 set_src
= SET_SRC (loc
);
3014 loc
= SET_DEST (loc
);
3018 var_reg_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
3021 var_mem_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
3024 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3030 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3031 enum var_init_status src_status
;
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
);
3044 var_reg_delete_and_set (&set
, loc
, false, src_status
, set_src
);
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
);
3054 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3057 var_reg_delete (&set
, loc
, false);
3059 var_mem_delete (&set
, loc
, false);
3061 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3067 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3070 var_reg_delete (&set
, loc
, true);
3072 var_mem_delete (&set
, loc
, true);
3074 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3079 set
.stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
3083 dataflow_set_destroy (&set
);
3086 /* Emit notes for the whole function. */
3089 vt_emit_notes (void)
3092 dataflow_set
*last_out
;
3095 gcc_assert (!htab_elements (changed_variables
));
3097 /* Enable emitting notes by functions (mainly by set_variable_part and
3098 delete_variable_part). */
3101 dataflow_set_init (&empty
, 7);
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
);
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. */
3123 vt_get_decl_and_offset (rtx rtl
, tree
*declp
, HOST_WIDE_INT
*offsetp
)
3127 if (REG_ATTRS (rtl
))
3129 *declp
= REG_EXPR (rtl
);
3130 *offsetp
= REG_OFFSET (rtl
);
3134 else if (MEM_P (rtl
))
3136 if (MEM_ATTRS (rtl
))
3138 *declp
= MEM_EXPR (rtl
);
3139 *offsetp
= INT_MEM_OFFSET (rtl
);
3146 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3149 vt_add_function_parameters (void)
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
);
3159 enum machine_mode mode
;
3160 HOST_WIDE_INT offset
;
3163 if (TREE_CODE (parm
) != PARM_DECL
)
3166 if (!DECL_NAME (parm
))
3169 if (!decl_rtl
|| !incoming
)
3172 if (GET_MODE (decl_rtl
) == BLKmode
|| GET_MODE (incoming
) == BLKmode
)
3175 if (!vt_get_decl_and_offset (incoming
, &decl
, &offset
))
3177 if (!vt_get_decl_and_offset (decl_rtl
, &decl
, &offset
))
3179 offset
+= byte_lowpart_offset (GET_MODE (incoming
),
3180 GET_MODE (decl_rtl
));
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));
3197 if (!track_loc_p (incoming
, parm
, offset
, false, &mode
, &offset
))
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
,
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. */
3224 vt_initialize (void)
3228 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def
));
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
))
3242 if (!frame_pointer_needed
)
3244 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3250 note_uses (&PATTERN (insn
), count_uses_1
, insn
);
3251 note_stores (PATTERN (insn
), count_stores
, insn
);
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
))
3267 if (!frame_pointer_needed
)
3269 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3272 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3274 mo
->type
= MO_ADJUST
;
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. */
3287 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_USE
)
3289 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_USE_NO_VAR
)
3295 sw
= VTI (bb
)->mos
[n1
];
3296 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
3297 VTI (bb
)->mos
[n2
] = sw
;
3303 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
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. */
3319 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_CLOBBER
)
3321 while (n1
< n2
&& (VTI (bb
)->mos
[n2
].type
== MO_SET
3322 || VTI (bb
)->mos
[n2
].type
== MO_COPY
))
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
;
3346 /* Init the IN and OUT sets. */
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
),
3361 changed_variables
= htab_create (10, variable_htab_hash
, variable_htab_eq
,
3363 vt_add_function_parameters ();
3366 /* Free the data structures needed for variable tracking. */
3375 free (VTI (bb
)->mos
);
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. */
3393 variable_tracking_main (void)
3395 if (n_basic_blocks
> 500 && n_edges
/ n_basic_blocks
>= 20)
3398 mark_dfs_back_edges ();
3400 if (!frame_pointer_needed
)
3402 if (!vt_stack_adjustments ())
3409 vt_find_locations ();
3412 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3414 dump_dataflow_sets ();
3415 dump_flow_info (dump_file
, dump_flags
);
3423 gate_handle_var_tracking (void)
3425 return (flag_var_tracking
);
3430 struct rtl_opt_pass pass_variable_tracking
=
3434 "vartrack", /* name */
3435 gate_handle_var_tracking
, /* gate */
3436 variable_tracking_main
, /* execute */
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 */