1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This file contains the variable tracking pass. It computes where
21 variables are located (which registers or where in memory) at each position
22 in instruction stream and emits notes describing the locations.
23 Debug information (DWARF2 location lists) is finally generated from
25 With this debug information, it is possible to show variables
26 even when debugging optimized code.
28 How does the variable tracking pass work?
30 First, it scans RTL code for uses, stores and clobbers (register/memory
31 references in instructions), for call insns and for stack adjustments
32 separately for each basic block and saves them to an array of micro
34 The micro operations of one instruction are ordered so that
35 pre-modifying stack adjustment < use < use with no var < call insn <
36 < set < clobber < post-modifying stack adjustment
38 Then, a forward dataflow analysis is performed to find out how locations
39 of variables change through code and to propagate the variable locations
40 along control flow graph.
41 The IN set for basic block BB is computed as a union of OUT sets of BB's
42 predecessors, the OUT set for BB is copied from the IN set for BB and
43 is changed according to micro operations in BB.
45 The IN and OUT sets for basic blocks consist of a current stack adjustment
46 (used for adjusting offset of variables addressed using stack pointer),
47 the table of structures describing the locations of parts of a variable
48 and for each physical register a linked list for each physical register.
49 The linked list is a list of variable parts stored in the register,
50 i.e. it is a list of triplets (reg, decl, offset) where decl is
51 REG_EXPR (reg) and offset is REG_OFFSET (reg). The linked list is used for
52 effective deleting appropriate variable parts when we set or clobber the
55 There may be more than one variable part in a register. The linked lists
56 should be pretty short so it is a good data structure here.
57 For example in the following code, register allocator may assign same
58 register to variables A and B, and both of them are stored in the same
71 Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
72 are emitted to appropriate positions in RTL code. Each such a note describes
73 the location of one variable at the point in instruction stream where the
74 note is. There is no need to emit a note for each variable before each
75 instruction, we only emit these notes where the location of variable changes
76 (this means that we also emit notes for changes between the OUT set of the
77 previous block and the IN set of the current block).
79 The notes consist of two parts:
80 1. the declaration (from REG_EXPR or MEM_EXPR)
81 2. the location of a variable - it is either a simple register/memory
82 reference (for simple variables, for example int),
83 or a parallel of register/memory references (for a large variables
84 which consist of several parts, for example long long).
90 #include "coretypes.h"
94 #include "hard-reg-set.h"
95 #include "basic-block.h"
98 #include "insn-config.h"
101 #include "alloc-pool.h"
107 #include "tree-pass.h"
109 /* Type of micro operation. */
110 enum micro_operation_type
112 MO_USE
, /* Use location (REG or MEM). */
113 MO_USE_NO_VAR
,/* Use location which is not associated with a variable
114 or the variable is not trackable. */
115 MO_SET
, /* Set location. */
116 MO_COPY
, /* Copy the same portion of a variable from one
117 location to another. */
118 MO_CLOBBER
, /* Clobber location. */
119 MO_CALL
, /* Call insn. */
120 MO_ADJUST
/* Adjust stack pointer. */
123 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
126 EMIT_NOTE_BEFORE_INSN
,
130 /* Structure holding information about micro operation. */
131 typedef struct micro_operation_def
133 /* Type of micro operation. */
134 enum micro_operation_type type
;
137 /* Location. For MO_SET and MO_COPY, this is the SET that performs
138 the assignment, if known, otherwise it is the target of the
142 /* Stack adjustment. */
143 HOST_WIDE_INT adjust
;
146 /* The instruction which the micro operation is in, for MO_USE,
147 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
148 instruction or note in the original flow (before any var-tracking
149 notes are inserted, to simplify emission of notes), for MO_SET
154 /* Structure for passing some other parameters to function
155 emit_note_insn_var_location. */
156 typedef struct emit_note_data_def
158 /* The instruction which the note will be emitted before/after. */
161 /* Where the note will be emitted (before/after insn)? */
162 enum emit_note_where where
;
165 /* Description of location of a part of a variable. The content of a physical
166 register is described by a chain of these structures.
167 The chains are pretty short (usually 1 or 2 elements) and thus
168 chain is the best data structure. */
169 typedef struct attrs_def
171 /* Pointer to next member of the list. */
172 struct attrs_def
*next
;
174 /* The rtx of register. */
177 /* The declaration corresponding to LOC. */
180 /* Offset from start of DECL. */
181 HOST_WIDE_INT offset
;
184 /* Structure holding the IN or OUT set for a basic block. */
185 typedef struct dataflow_set_def
187 /* Adjustment of stack offset. */
188 HOST_WIDE_INT stack_adjust
;
190 /* Attributes for registers (lists of attrs). */
191 attrs regs
[FIRST_PSEUDO_REGISTER
];
193 /* Variable locations. */
197 /* The structure (one for each basic block) containing the information
198 needed for variable tracking. */
199 typedef struct variable_tracking_info_def
201 /* Number of micro operations stored in the MOS array. */
204 /* The array of micro operations. */
205 micro_operation
*mos
;
207 /* The IN and OUT set for dataflow analysis. */
211 /* Has the block been visited in DFS? */
213 } *variable_tracking_info
;
215 /* Structure for chaining the locations. */
216 typedef struct location_chain_def
218 /* Next element in the chain. */
219 struct location_chain_def
*next
;
221 /* The location (REG or MEM). */
224 /* The "value" stored in this location. */
228 enum var_init_status init
;
231 /* Structure describing one part of variable. */
232 typedef struct variable_part_def
234 /* Chain of locations of the part. */
235 location_chain loc_chain
;
237 /* Location which was last emitted to location list. */
240 /* The offset in the variable. */
241 HOST_WIDE_INT offset
;
244 /* Maximum number of location parts. */
245 #define MAX_VAR_PARTS 16
247 /* Structure describing where the variable is located. */
248 typedef struct variable_def
250 /* The declaration of the variable. */
253 /* Reference count. */
256 /* Number of variable parts. */
259 /* The variable parts. */
260 variable_part var_part
[MAX_VAR_PARTS
];
262 typedef const struct variable_def
*const_variable
;
264 /* Hash function for DECL for VARIABLE_HTAB. */
265 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
267 /* Pointer to the BB's information specific to variable tracking pass. */
268 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
270 /* Alloc pool for struct attrs_def. */
271 static alloc_pool attrs_pool
;
273 /* Alloc pool for struct variable_def. */
274 static alloc_pool var_pool
;
276 /* Alloc pool for struct location_chain_def. */
277 static alloc_pool loc_chain_pool
;
279 /* Changed variables, notes will be emitted for them. */
280 static htab_t changed_variables
;
282 /* Shall notes be emitted? */
283 static bool emit_notes
;
285 /* Local function prototypes. */
286 static void stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
288 static void insn_stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
290 static void bb_stack_adjust_offset (basic_block
);
291 static bool vt_stack_adjustments (void);
292 static rtx
adjust_stack_reference (rtx
, HOST_WIDE_INT
);
293 static hashval_t
variable_htab_hash (const void *);
294 static int variable_htab_eq (const void *, const void *);
295 static void variable_htab_free (void *);
297 static void init_attrs_list_set (attrs
*);
298 static void attrs_list_clear (attrs
*);
299 static attrs
attrs_list_member (attrs
, tree
, HOST_WIDE_INT
);
300 static void attrs_list_insert (attrs
*, tree
, HOST_WIDE_INT
, rtx
);
301 static void attrs_list_copy (attrs
*, attrs
);
302 static void attrs_list_union (attrs
*, attrs
);
304 static void vars_clear (htab_t
);
305 static variable
unshare_variable (dataflow_set
*set
, variable var
,
306 enum var_init_status
);
307 static int vars_copy_1 (void **, void *);
308 static void vars_copy (htab_t
, htab_t
);
309 static tree
var_debug_decl (tree
);
310 static void var_reg_set (dataflow_set
*, rtx
, enum var_init_status
, rtx
);
311 static void var_reg_delete_and_set (dataflow_set
*, rtx
, bool,
312 enum var_init_status
, rtx
);
313 static void var_reg_delete (dataflow_set
*, rtx
, bool);
314 static void var_regno_delete (dataflow_set
*, int);
315 static void var_mem_set (dataflow_set
*, rtx
, enum var_init_status
, rtx
);
316 static void var_mem_delete_and_set (dataflow_set
*, rtx
, bool,
317 enum var_init_status
, rtx
);
318 static void var_mem_delete (dataflow_set
*, rtx
, bool);
320 static void dataflow_set_init (dataflow_set
*, int);
321 static void dataflow_set_clear (dataflow_set
*);
322 static void dataflow_set_copy (dataflow_set
*, dataflow_set
*);
323 static int variable_union_info_cmp_pos (const void *, const void *);
324 static int variable_union (void **, void *);
325 static void dataflow_set_union (dataflow_set
*, dataflow_set
*);
326 static bool variable_part_different_p (variable_part
*, variable_part
*);
327 static bool variable_different_p (variable
, variable
, bool);
328 static int dataflow_set_different_1 (void **, void *);
329 static int dataflow_set_different_2 (void **, void *);
330 static bool dataflow_set_different (dataflow_set
*, dataflow_set
*);
331 static void dataflow_set_destroy (dataflow_set
*);
333 static bool contains_symbol_ref (rtx
);
334 static bool track_expr_p (tree
);
335 static bool same_variable_part_p (rtx
, tree
, HOST_WIDE_INT
);
336 static int count_uses (rtx
*, void *);
337 static void count_uses_1 (rtx
*, void *);
338 static void count_stores (rtx
, const_rtx
, void *);
339 static int add_uses (rtx
*, void *);
340 static void add_uses_1 (rtx
*, void *);
341 static void add_stores (rtx
, const_rtx
, void *);
342 static bool compute_bb_dataflow (basic_block
);
343 static void vt_find_locations (void);
345 static void dump_attrs_list (attrs
);
346 static int dump_variable (void **, void *);
347 static void dump_vars (htab_t
);
348 static void dump_dataflow_set (dataflow_set
*);
349 static void dump_dataflow_sets (void);
351 static void variable_was_changed (variable
, htab_t
);
352 static void set_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
,
353 enum var_init_status
, rtx
);
354 static void clobber_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
,
356 static void delete_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
357 static int emit_note_insn_var_location (void **, void *);
358 static void emit_notes_for_changes (rtx
, enum emit_note_where
);
359 static int emit_notes_for_differences_1 (void **, void *);
360 static int emit_notes_for_differences_2 (void **, void *);
361 static void emit_notes_for_differences (rtx
, dataflow_set
*, dataflow_set
*);
362 static void emit_notes_in_bb (basic_block
);
363 static void vt_emit_notes (void);
365 static bool vt_get_decl_and_offset (rtx
, tree
*, HOST_WIDE_INT
*);
366 static void vt_add_function_parameters (void);
367 static void vt_initialize (void);
368 static void vt_finalize (void);
370 /* Given a SET, calculate the amount of stack adjustment it contains
371 PRE- and POST-modifying stack pointer.
372 This function is similar to stack_adjust_offset. */
375 stack_adjust_offset_pre_post (rtx pattern
, HOST_WIDE_INT
*pre
,
378 rtx src
= SET_SRC (pattern
);
379 rtx dest
= SET_DEST (pattern
);
382 if (dest
== stack_pointer_rtx
)
384 /* (set (reg sp) (plus (reg sp) (const_int))) */
385 code
= GET_CODE (src
);
386 if (! (code
== PLUS
|| code
== MINUS
)
387 || XEXP (src
, 0) != stack_pointer_rtx
388 || GET_CODE (XEXP (src
, 1)) != CONST_INT
)
392 *post
+= INTVAL (XEXP (src
, 1));
394 *post
-= INTVAL (XEXP (src
, 1));
396 else if (MEM_P (dest
))
398 /* (set (mem (pre_dec (reg sp))) (foo)) */
399 src
= XEXP (dest
, 0);
400 code
= GET_CODE (src
);
406 if (XEXP (src
, 0) == stack_pointer_rtx
)
408 rtx val
= XEXP (XEXP (src
, 1), 1);
409 /* We handle only adjustments by constant amount. */
410 gcc_assert (GET_CODE (XEXP (src
, 1)) == PLUS
&&
411 GET_CODE (val
) == CONST_INT
);
413 if (code
== PRE_MODIFY
)
414 *pre
-= INTVAL (val
);
416 *post
-= INTVAL (val
);
422 if (XEXP (src
, 0) == stack_pointer_rtx
)
424 *pre
+= GET_MODE_SIZE (GET_MODE (dest
));
430 if (XEXP (src
, 0) == stack_pointer_rtx
)
432 *post
+= GET_MODE_SIZE (GET_MODE (dest
));
438 if (XEXP (src
, 0) == stack_pointer_rtx
)
440 *pre
-= GET_MODE_SIZE (GET_MODE (dest
));
446 if (XEXP (src
, 0) == stack_pointer_rtx
)
448 *post
-= GET_MODE_SIZE (GET_MODE (dest
));
459 /* Given an INSN, calculate the amount of stack adjustment it contains
460 PRE- and POST-modifying stack pointer. */
463 insn_stack_adjust_offset_pre_post (rtx insn
, HOST_WIDE_INT
*pre
,
469 if (GET_CODE (PATTERN (insn
)) == SET
)
470 stack_adjust_offset_pre_post (PATTERN (insn
), pre
, post
);
471 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
472 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
476 /* There may be stack adjustments inside compound insns. Search
478 for ( i
= XVECLEN (PATTERN (insn
), 0) - 1; i
>= 0; i
--)
479 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
480 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn
), 0, i
),
485 /* Compute stack adjustment in basic block BB. */
488 bb_stack_adjust_offset (basic_block bb
)
490 HOST_WIDE_INT offset
;
493 offset
= VTI (bb
)->in
.stack_adjust
;
494 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
496 if (VTI (bb
)->mos
[i
].type
== MO_ADJUST
)
497 offset
+= VTI (bb
)->mos
[i
].u
.adjust
;
498 else if (VTI (bb
)->mos
[i
].type
!= MO_CALL
)
500 if (MEM_P (VTI (bb
)->mos
[i
].u
.loc
))
502 VTI (bb
)->mos
[i
].u
.loc
503 = adjust_stack_reference (VTI (bb
)->mos
[i
].u
.loc
, -offset
);
507 VTI (bb
)->out
.stack_adjust
= offset
;
510 /* Compute stack adjustments for all blocks by traversing DFS tree.
511 Return true when the adjustments on all incoming edges are consistent.
512 Heavily borrowed from pre_and_rev_post_order_compute. */
515 vt_stack_adjustments (void)
517 edge_iterator
*stack
;
520 /* Initialize entry block. */
521 VTI (ENTRY_BLOCK_PTR
)->visited
= true;
522 VTI (ENTRY_BLOCK_PTR
)->out
.stack_adjust
= INCOMING_FRAME_SP_OFFSET
;
524 /* Allocate stack for back-tracking up CFG. */
525 stack
= XNEWVEC (edge_iterator
, n_basic_blocks
+ 1);
528 /* Push the first edge on to the stack. */
529 stack
[sp
++] = ei_start (ENTRY_BLOCK_PTR
->succs
);
537 /* Look at the edge on the top of the stack. */
539 src
= ei_edge (ei
)->src
;
540 dest
= ei_edge (ei
)->dest
;
542 /* Check if the edge destination has been visited yet. */
543 if (!VTI (dest
)->visited
)
545 VTI (dest
)->visited
= true;
546 VTI (dest
)->in
.stack_adjust
= VTI (src
)->out
.stack_adjust
;
547 bb_stack_adjust_offset (dest
);
549 if (EDGE_COUNT (dest
->succs
) > 0)
550 /* Since the DEST node has been visited for the first
551 time, check its successors. */
552 stack
[sp
++] = ei_start (dest
->succs
);
556 /* Check whether the adjustments on the edges are the same. */
557 if (VTI (dest
)->in
.stack_adjust
!= VTI (src
)->out
.stack_adjust
)
563 if (! ei_one_before_end_p (ei
))
564 /* Go to the next edge. */
565 ei_next (&stack
[sp
- 1]);
567 /* Return to previous level if there are no more edges. */
576 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
577 to the argument pointer. Return the new rtx. */
580 adjust_stack_reference (rtx mem
, HOST_WIDE_INT adjustment
)
584 #ifdef FRAME_POINTER_CFA_OFFSET
585 adjustment
-= FRAME_POINTER_CFA_OFFSET (current_function_decl
);
586 cfa
= plus_constant (frame_pointer_rtx
, adjustment
);
588 adjustment
-= ARG_POINTER_CFA_OFFSET (current_function_decl
);
589 cfa
= plus_constant (arg_pointer_rtx
, adjustment
);
592 addr
= replace_rtx (copy_rtx (XEXP (mem
, 0)), stack_pointer_rtx
, cfa
);
593 tmp
= simplify_rtx (addr
);
597 return replace_equiv_address_nv (mem
, addr
);
600 /* The hash function for variable_htab, computes the hash value
601 from the declaration of variable X. */
604 variable_htab_hash (const void *x
)
606 const_variable
const v
= (const_variable
) x
;
608 return (VARIABLE_HASH_VAL (v
->decl
));
611 /* Compare the declaration of variable X with declaration Y. */
614 variable_htab_eq (const void *x
, const void *y
)
616 const_variable
const v
= (const_variable
) x
;
617 const_tree
const decl
= (const_tree
) y
;
619 return (VARIABLE_HASH_VAL (v
->decl
) == VARIABLE_HASH_VAL (decl
));
622 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
625 variable_htab_free (void *elem
)
628 variable var
= (variable
) elem
;
629 location_chain node
, next
;
631 gcc_assert (var
->refcount
> 0);
634 if (var
->refcount
> 0)
637 for (i
= 0; i
< var
->n_var_parts
; i
++)
639 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= next
)
642 pool_free (loc_chain_pool
, node
);
644 var
->var_part
[i
].loc_chain
= NULL
;
646 pool_free (var_pool
, var
);
649 /* Initialize the set (array) SET of attrs to empty lists. */
652 init_attrs_list_set (attrs
*set
)
656 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
660 /* Make the list *LISTP empty. */
663 attrs_list_clear (attrs
*listp
)
667 for (list
= *listp
; list
; list
= next
)
670 pool_free (attrs_pool
, list
);
675 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
678 attrs_list_member (attrs list
, tree decl
, HOST_WIDE_INT offset
)
680 for (; list
; list
= list
->next
)
681 if (list
->decl
== decl
&& list
->offset
== offset
)
686 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
689 attrs_list_insert (attrs
*listp
, tree decl
, HOST_WIDE_INT offset
, rtx loc
)
693 list
= pool_alloc (attrs_pool
);
696 list
->offset
= offset
;
701 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
704 attrs_list_copy (attrs
*dstp
, attrs src
)
708 attrs_list_clear (dstp
);
709 for (; src
; src
= src
->next
)
711 n
= pool_alloc (attrs_pool
);
714 n
->offset
= src
->offset
;
720 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
723 attrs_list_union (attrs
*dstp
, attrs src
)
725 for (; src
; src
= src
->next
)
727 if (!attrs_list_member (*dstp
, src
->decl
, src
->offset
))
728 attrs_list_insert (dstp
, src
->decl
, src
->offset
, src
->loc
);
732 /* Delete all variables from hash table VARS. */
735 vars_clear (htab_t vars
)
740 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
743 unshare_variable (dataflow_set
*set
, variable var
,
744 enum var_init_status initialized
)
750 new_var
= pool_alloc (var_pool
);
751 new_var
->decl
= var
->decl
;
752 new_var
->refcount
= 1;
754 new_var
->n_var_parts
= var
->n_var_parts
;
756 for (i
= 0; i
< var
->n_var_parts
; i
++)
759 location_chain
*nextp
;
761 new_var
->var_part
[i
].offset
= var
->var_part
[i
].offset
;
762 nextp
= &new_var
->var_part
[i
].loc_chain
;
763 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
765 location_chain new_lc
;
767 new_lc
= pool_alloc (loc_chain_pool
);
769 if (node
->init
> initialized
)
770 new_lc
->init
= node
->init
;
772 new_lc
->init
= initialized
;
773 if (node
->set_src
&& !(MEM_P (node
->set_src
)))
774 new_lc
->set_src
= node
->set_src
;
776 new_lc
->set_src
= NULL
;
777 new_lc
->loc
= node
->loc
;
780 nextp
= &new_lc
->next
;
783 /* We are at the basic block boundary when copying variable description
784 so set the CUR_LOC to be the first element of the chain. */
785 if (new_var
->var_part
[i
].loc_chain
)
786 new_var
->var_part
[i
].cur_loc
= new_var
->var_part
[i
].loc_chain
->loc
;
788 new_var
->var_part
[i
].cur_loc
= NULL
;
791 slot
= htab_find_slot_with_hash (set
->vars
, new_var
->decl
,
792 VARIABLE_HASH_VAL (new_var
->decl
),
798 /* Add a variable from *SLOT to hash table DATA and increase its reference
802 vars_copy_1 (void **slot
, void *data
)
804 htab_t dst
= (htab_t
) data
;
807 src
= *(variable
*) slot
;
810 dstp
= (variable
*) htab_find_slot_with_hash (dst
, src
->decl
,
811 VARIABLE_HASH_VAL (src
->decl
),
815 /* Continue traversing the hash table. */
819 /* Copy all variables from hash table SRC to hash table DST. */
822 vars_copy (htab_t dst
, htab_t src
)
825 htab_traverse (src
, vars_copy_1
, dst
);
828 /* Map a decl to its main debug decl. */
831 var_debug_decl (tree decl
)
833 if (decl
&& DECL_P (decl
)
834 && DECL_DEBUG_EXPR_IS_FROM (decl
) && DECL_DEBUG_EXPR (decl
)
835 && DECL_P (DECL_DEBUG_EXPR (decl
)))
836 decl
= DECL_DEBUG_EXPR (decl
);
841 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
844 var_reg_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
847 tree decl
= REG_EXPR (loc
);
848 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
851 decl
= var_debug_decl (decl
);
853 for (node
= set
->regs
[REGNO (loc
)]; node
; node
= node
->next
)
854 if (node
->decl
== decl
&& node
->offset
== offset
)
857 attrs_list_insert (&set
->regs
[REGNO (loc
)], decl
, offset
, loc
);
858 set_variable_part (set
, loc
, decl
, offset
, initialized
, set_src
);
862 get_init_value (dataflow_set
*set
, rtx loc
, tree decl
)
867 int ret_val
= VAR_INIT_STATUS_UNKNOWN
;
869 if (! flag_var_tracking_uninit
)
870 return VAR_INIT_STATUS_INITIALIZED
;
872 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
876 var
= * (variable
*) slot
;
877 for (i
= 0; i
< var
->n_var_parts
&& ret_val
== VAR_INIT_STATUS_UNKNOWN
; i
++)
879 location_chain nextp
;
880 for (nextp
= var
->var_part
[i
].loc_chain
; nextp
; nextp
= nextp
->next
)
881 if (rtx_equal_p (nextp
->loc
, loc
))
883 ret_val
= nextp
->init
;
892 /* Delete current content of register LOC in dataflow set SET and set
893 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
894 MODIFY is true, any other live copies of the same variable part are
895 also deleted from the dataflow set, otherwise the variable part is
896 assumed to be copied from another location holding the same
900 var_reg_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
,
901 enum var_init_status initialized
, rtx set_src
)
903 tree decl
= REG_EXPR (loc
);
904 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
908 decl
= var_debug_decl (decl
);
910 if (initialized
== VAR_INIT_STATUS_UNKNOWN
)
911 initialized
= get_init_value (set
, loc
, decl
);
913 nextp
= &set
->regs
[REGNO (loc
)];
914 for (node
= *nextp
; node
; node
= next
)
917 if (node
->decl
!= decl
|| node
->offset
!= offset
)
919 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
920 pool_free (attrs_pool
, node
);
930 clobber_variable_part (set
, loc
, decl
, offset
, set_src
);
931 var_reg_set (set
, loc
, initialized
, set_src
);
934 /* Delete current content of register LOC in dataflow set SET. If
935 CLOBBER is true, also delete any other live copies of the same
939 var_reg_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
941 attrs
*reg
= &set
->regs
[REGNO (loc
)];
946 tree decl
= REG_EXPR (loc
);
947 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
949 decl
= var_debug_decl (decl
);
951 clobber_variable_part (set
, NULL
, decl
, offset
, NULL
);
954 for (node
= *reg
; node
; node
= next
)
957 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
958 pool_free (attrs_pool
, node
);
963 /* Delete content of register with number REGNO in dataflow set SET. */
966 var_regno_delete (dataflow_set
*set
, int regno
)
968 attrs
*reg
= &set
->regs
[regno
];
971 for (node
= *reg
; node
; node
= next
)
974 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
975 pool_free (attrs_pool
, node
);
980 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
982 Adjust the address first if it is stack pointer based. */
985 var_mem_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
988 tree decl
= MEM_EXPR (loc
);
989 HOST_WIDE_INT offset
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
991 decl
= var_debug_decl (decl
);
993 set_variable_part (set
, loc
, decl
, offset
, initialized
, set_src
);
996 /* Delete and set the location part of variable MEM_EXPR (LOC) in
997 dataflow set SET to LOC. If MODIFY is true, any other live copies
998 of the same variable part are also deleted from the dataflow set,
999 otherwise the variable part is assumed to be copied from another
1000 location holding the same part.
1001 Adjust the address first if it is stack pointer based. */
1004 var_mem_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
,
1005 enum var_init_status initialized
, rtx set_src
)
1007 tree decl
= MEM_EXPR (loc
);
1008 HOST_WIDE_INT offset
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
1010 decl
= var_debug_decl (decl
);
1012 if (initialized
== VAR_INIT_STATUS_UNKNOWN
)
1013 initialized
= get_init_value (set
, loc
, decl
);
1016 clobber_variable_part (set
, NULL
, decl
, offset
, set_src
);
1017 var_mem_set (set
, loc
, initialized
, set_src
);
1020 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
1021 true, also delete any other live copies of the same variable part.
1022 Adjust the address first if it is stack pointer based. */
1025 var_mem_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
1027 tree decl
= MEM_EXPR (loc
);
1028 HOST_WIDE_INT offset
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
1030 decl
= var_debug_decl (decl
);
1032 clobber_variable_part (set
, NULL
, decl
, offset
, NULL
);
1033 delete_variable_part (set
, loc
, decl
, offset
);
1036 /* Initialize dataflow set SET to be empty.
1037 VARS_SIZE is the initial size of hash table VARS. */
1040 dataflow_set_init (dataflow_set
*set
, int vars_size
)
1042 init_attrs_list_set (set
->regs
);
1043 set
->vars
= htab_create (vars_size
, variable_htab_hash
, variable_htab_eq
,
1044 variable_htab_free
);
1045 set
->stack_adjust
= 0;
1048 /* Delete the contents of dataflow set SET. */
1051 dataflow_set_clear (dataflow_set
*set
)
1055 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1056 attrs_list_clear (&set
->regs
[i
]);
1058 vars_clear (set
->vars
);
1061 /* Copy the contents of dataflow set SRC to DST. */
1064 dataflow_set_copy (dataflow_set
*dst
, dataflow_set
*src
)
1068 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1069 attrs_list_copy (&dst
->regs
[i
], src
->regs
[i
]);
1071 vars_copy (dst
->vars
, src
->vars
);
1072 dst
->stack_adjust
= src
->stack_adjust
;
1075 /* Information for merging lists of locations for a given offset of variable.
1077 struct variable_union_info
1079 /* Node of the location chain. */
1082 /* The sum of positions in the input chains. */
1085 /* The position in the chains of SRC and DST dataflow sets. */
1090 /* Compare function for qsort, order the structures by POS element. */
1093 variable_union_info_cmp_pos (const void *n1
, const void *n2
)
1095 const struct variable_union_info
*i1
= n1
;
1096 const struct variable_union_info
*i2
= n2
;
1098 if (i1
->pos
!= i2
->pos
)
1099 return i1
->pos
- i2
->pos
;
1101 return (i1
->pos_dst
- i2
->pos_dst
);
1104 /* Compute union of location parts of variable *SLOT and the same variable
1105 from hash table DATA. Compute "sorted" union of the location chains
1106 for common offsets, i.e. the locations of a variable part are sorted by
1107 a priority where the priority is the sum of the positions in the 2 chains
1108 (if a location is only in one list the position in the second list is
1109 defined to be larger than the length of the chains).
1110 When we are updating the location parts the newest location is in the
1111 beginning of the chain, so when we do the described "sorted" union
1112 we keep the newest locations in the beginning. */
1115 variable_union (void **slot
, void *data
)
1117 variable src
, dst
, *dstp
;
1118 dataflow_set
*set
= (dataflow_set
*) data
;
1121 src
= *(variable
*) slot
;
1122 dstp
= (variable
*) htab_find_slot_with_hash (set
->vars
, src
->decl
,
1123 VARIABLE_HASH_VAL (src
->decl
),
1129 /* If CUR_LOC of some variable part is not the first element of
1130 the location chain we are going to change it so we have to make
1131 a copy of the variable. */
1132 for (k
= 0; k
< src
->n_var_parts
; k
++)
1134 gcc_assert (!src
->var_part
[k
].loc_chain
1135 == !src
->var_part
[k
].cur_loc
);
1136 if (src
->var_part
[k
].loc_chain
)
1138 gcc_assert (src
->var_part
[k
].cur_loc
);
1139 if (src
->var_part
[k
].cur_loc
!= src
->var_part
[k
].loc_chain
->loc
)
1143 if (k
< src
->n_var_parts
)
1145 enum var_init_status status
= VAR_INIT_STATUS_UNKNOWN
;
1147 if (! flag_var_tracking_uninit
)
1148 status
= VAR_INIT_STATUS_INITIALIZED
;
1150 unshare_variable (set
, src
, status
);
1155 /* Continue traversing the hash table. */
1161 gcc_assert (src
->n_var_parts
);
1163 /* Count the number of location parts, result is K. */
1164 for (i
= 0, j
= 0, k
= 0;
1165 i
< src
->n_var_parts
&& j
< dst
->n_var_parts
; k
++)
1167 if (src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1172 else if (src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1177 k
+= src
->n_var_parts
- i
;
1178 k
+= dst
->n_var_parts
- j
;
1180 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1181 thus there are at most MAX_VAR_PARTS different offsets. */
1182 gcc_assert (k
<= MAX_VAR_PARTS
);
1184 if (dst
->refcount
> 1 && dst
->n_var_parts
!= k
)
1186 enum var_init_status status
= VAR_INIT_STATUS_UNKNOWN
;
1188 if (! flag_var_tracking_uninit
)
1189 status
= VAR_INIT_STATUS_INITIALIZED
;
1190 dst
= unshare_variable (set
, dst
, status
);
1193 i
= src
->n_var_parts
- 1;
1194 j
= dst
->n_var_parts
- 1;
1195 dst
->n_var_parts
= k
;
1197 for (k
--; k
>= 0; k
--)
1199 location_chain node
, node2
;
1201 if (i
>= 0 && j
>= 0
1202 && src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1204 /* Compute the "sorted" union of the chains, i.e. the locations which
1205 are in both chains go first, they are sorted by the sum of
1206 positions in the chains. */
1209 struct variable_union_info
*vui
;
1211 /* If DST is shared compare the location chains.
1212 If they are different we will modify the chain in DST with
1213 high probability so make a copy of DST. */
1214 if (dst
->refcount
> 1)
1216 for (node
= src
->var_part
[i
].loc_chain
,
1217 node2
= dst
->var_part
[j
].loc_chain
; node
&& node2
;
1218 node
= node
->next
, node2
= node2
->next
)
1220 if (!((REG_P (node2
->loc
)
1221 && REG_P (node
->loc
)
1222 && REGNO (node2
->loc
) == REGNO (node
->loc
))
1223 || rtx_equal_p (node2
->loc
, node
->loc
)))
1225 if (node2
->init
< node
->init
)
1226 node2
->init
= node
->init
;
1231 dst
= unshare_variable (set
, dst
, VAR_INIT_STATUS_UNKNOWN
);
1235 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1238 for (node
= dst
->var_part
[j
].loc_chain
; node
; node
= node
->next
)
1240 vui
= XCNEWVEC (struct variable_union_info
, src_l
+ dst_l
);
1242 /* Fill in the locations from DST. */
1243 for (node
= dst
->var_part
[j
].loc_chain
, jj
= 0; node
;
1244 node
= node
->next
, jj
++)
1247 vui
[jj
].pos_dst
= jj
;
1249 /* Value larger than a sum of 2 valid positions. */
1250 vui
[jj
].pos_src
= src_l
+ dst_l
;
1253 /* Fill in the locations from SRC. */
1255 for (node
= src
->var_part
[i
].loc_chain
, ii
= 0; node
;
1256 node
= node
->next
, ii
++)
1258 /* Find location from NODE. */
1259 for (jj
= 0; jj
< dst_l
; jj
++)
1261 if ((REG_P (vui
[jj
].lc
->loc
)
1262 && REG_P (node
->loc
)
1263 && REGNO (vui
[jj
].lc
->loc
) == REGNO (node
->loc
))
1264 || rtx_equal_p (vui
[jj
].lc
->loc
, node
->loc
))
1266 vui
[jj
].pos_src
= ii
;
1270 if (jj
>= dst_l
) /* The location has not been found. */
1272 location_chain new_node
;
1274 /* Copy the location from SRC. */
1275 new_node
= pool_alloc (loc_chain_pool
);
1276 new_node
->loc
= node
->loc
;
1277 new_node
->init
= node
->init
;
1278 if (!node
->set_src
|| MEM_P (node
->set_src
))
1279 new_node
->set_src
= NULL
;
1281 new_node
->set_src
= node
->set_src
;
1282 vui
[n
].lc
= new_node
;
1283 vui
[n
].pos_src
= ii
;
1284 vui
[n
].pos_dst
= src_l
+ dst_l
;
1289 for (ii
= 0; ii
< src_l
+ dst_l
; ii
++)
1290 vui
[ii
].pos
= vui
[ii
].pos_src
+ vui
[ii
].pos_dst
;
1292 qsort (vui
, n
, sizeof (struct variable_union_info
),
1293 variable_union_info_cmp_pos
);
1295 /* Reconnect the nodes in sorted order. */
1296 for (ii
= 1; ii
< n
; ii
++)
1297 vui
[ii
- 1].lc
->next
= vui
[ii
].lc
;
1298 vui
[n
- 1].lc
->next
= NULL
;
1300 dst
->var_part
[k
].loc_chain
= vui
[0].lc
;
1301 dst
->var_part
[k
].offset
= dst
->var_part
[j
].offset
;
1307 else if ((i
>= 0 && j
>= 0
1308 && src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1311 dst
->var_part
[k
] = dst
->var_part
[j
];
1314 else if ((i
>= 0 && j
>= 0
1315 && src
->var_part
[i
].offset
> dst
->var_part
[j
].offset
)
1318 location_chain
*nextp
;
1320 /* Copy the chain from SRC. */
1321 nextp
= &dst
->var_part
[k
].loc_chain
;
1322 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1324 location_chain new_lc
;
1326 new_lc
= pool_alloc (loc_chain_pool
);
1327 new_lc
->next
= NULL
;
1328 new_lc
->init
= node
->init
;
1329 if (!node
->set_src
|| MEM_P (node
->set_src
))
1330 new_lc
->set_src
= NULL
;
1332 new_lc
->set_src
= node
->set_src
;
1333 new_lc
->loc
= node
->loc
;
1336 nextp
= &new_lc
->next
;
1339 dst
->var_part
[k
].offset
= src
->var_part
[i
].offset
;
1343 /* We are at the basic block boundary when computing union
1344 so set the CUR_LOC to be the first element of the chain. */
1345 if (dst
->var_part
[k
].loc_chain
)
1346 dst
->var_part
[k
].cur_loc
= dst
->var_part
[k
].loc_chain
->loc
;
1348 dst
->var_part
[k
].cur_loc
= NULL
;
1351 for (i
= 0; i
< src
->n_var_parts
&& i
< dst
->n_var_parts
; i
++)
1353 location_chain node
, node2
;
1354 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1355 for (node2
= dst
->var_part
[i
].loc_chain
; node2
; node2
= node2
->next
)
1356 if (rtx_equal_p (node
->loc
, node2
->loc
))
1358 if (node
->init
> node2
->init
)
1359 node2
->init
= node
->init
;
1363 /* Continue traversing the hash table. */
1367 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1370 dataflow_set_union (dataflow_set
*dst
, dataflow_set
*src
)
1374 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1375 attrs_list_union (&dst
->regs
[i
], src
->regs
[i
]);
1377 htab_traverse (src
->vars
, variable_union
, dst
);
1380 /* Flag whether two dataflow sets being compared contain different data. */
1382 dataflow_set_different_value
;
1385 variable_part_different_p (variable_part
*vp1
, variable_part
*vp2
)
1387 location_chain lc1
, lc2
;
1389 for (lc1
= vp1
->loc_chain
; lc1
; lc1
= lc1
->next
)
1391 for (lc2
= vp2
->loc_chain
; lc2
; lc2
= lc2
->next
)
1393 if (REG_P (lc1
->loc
) && REG_P (lc2
->loc
))
1395 if (REGNO (lc1
->loc
) == REGNO (lc2
->loc
))
1398 if (rtx_equal_p (lc1
->loc
, lc2
->loc
))
1407 /* Return true if variables VAR1 and VAR2 are different.
1408 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1412 variable_different_p (variable var1
, variable var2
,
1413 bool compare_current_location
)
1420 if (var1
->n_var_parts
!= var2
->n_var_parts
)
1423 for (i
= 0; i
< var1
->n_var_parts
; i
++)
1425 if (var1
->var_part
[i
].offset
!= var2
->var_part
[i
].offset
)
1427 if (compare_current_location
)
1429 if (!((REG_P (var1
->var_part
[i
].cur_loc
)
1430 && REG_P (var2
->var_part
[i
].cur_loc
)
1431 && (REGNO (var1
->var_part
[i
].cur_loc
)
1432 == REGNO (var2
->var_part
[i
].cur_loc
)))
1433 || rtx_equal_p (var1
->var_part
[i
].cur_loc
,
1434 var2
->var_part
[i
].cur_loc
)))
1437 if (variable_part_different_p (&var1
->var_part
[i
], &var2
->var_part
[i
]))
1439 if (variable_part_different_p (&var2
->var_part
[i
], &var1
->var_part
[i
]))
1445 /* Compare variable *SLOT with the same variable in hash table DATA
1446 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1449 dataflow_set_different_1 (void **slot
, void *data
)
1451 htab_t htab
= (htab_t
) data
;
1452 variable var1
, var2
;
1454 var1
= *(variable
*) slot
;
1455 var2
= htab_find_with_hash (htab
, var1
->decl
,
1456 VARIABLE_HASH_VAL (var1
->decl
));
1459 dataflow_set_different_value
= true;
1461 /* Stop traversing the hash table. */
1465 if (variable_different_p (var1
, var2
, false))
1467 dataflow_set_different_value
= true;
1469 /* Stop traversing the hash table. */
1473 /* Continue traversing the hash table. */
1477 /* Compare variable *SLOT with the same variable in hash table DATA
1478 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1481 dataflow_set_different_2 (void **slot
, void *data
)
1483 htab_t htab
= (htab_t
) data
;
1484 variable var1
, var2
;
1486 var1
= *(variable
*) slot
;
1487 var2
= htab_find_with_hash (htab
, var1
->decl
,
1488 VARIABLE_HASH_VAL (var1
->decl
));
1491 dataflow_set_different_value
= true;
1493 /* Stop traversing the hash table. */
1497 /* If both variables are defined they have been already checked for
1499 gcc_assert (!variable_different_p (var1
, var2
, false));
1501 /* Continue traversing the hash table. */
1505 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1508 dataflow_set_different (dataflow_set
*old_set
, dataflow_set
*new_set
)
1510 dataflow_set_different_value
= false;
1512 htab_traverse (old_set
->vars
, dataflow_set_different_1
, new_set
->vars
);
1513 if (!dataflow_set_different_value
)
1515 /* We have compared the variables which are in both hash tables
1516 so now only check whether there are some variables in NEW_SET->VARS
1517 which are not in OLD_SET->VARS. */
1518 htab_traverse (new_set
->vars
, dataflow_set_different_2
, old_set
->vars
);
1520 return dataflow_set_different_value
;
1523 /* Free the contents of dataflow set SET. */
1526 dataflow_set_destroy (dataflow_set
*set
)
1530 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1531 attrs_list_clear (&set
->regs
[i
]);
1533 htab_delete (set
->vars
);
1537 /* Return true if RTL X contains a SYMBOL_REF. */
1540 contains_symbol_ref (rtx x
)
1549 code
= GET_CODE (x
);
1550 if (code
== SYMBOL_REF
)
1553 fmt
= GET_RTX_FORMAT (code
);
1554 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1558 if (contains_symbol_ref (XEXP (x
, i
)))
1561 else if (fmt
[i
] == 'E')
1564 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1565 if (contains_symbol_ref (XVECEXP (x
, i
, j
)))
1573 /* Shall EXPR be tracked? */
1576 track_expr_p (tree expr
)
1581 /* If EXPR is not a parameter or a variable do not track it. */
1582 if (TREE_CODE (expr
) != VAR_DECL
&& TREE_CODE (expr
) != PARM_DECL
)
1585 /* It also must have a name... */
1586 if (!DECL_NAME (expr
))
1589 /* ... and a RTL assigned to it. */
1590 decl_rtl
= DECL_RTL_IF_SET (expr
);
1594 /* If this expression is really a debug alias of some other declaration, we
1595 don't need to track this expression if the ultimate declaration is
1598 if (DECL_DEBUG_EXPR_IS_FROM (realdecl
) && DECL_DEBUG_EXPR (realdecl
))
1600 realdecl
= DECL_DEBUG_EXPR (realdecl
);
1601 /* ??? We don't yet know how to emit DW_OP_piece for variable
1602 that has been SRA'ed. */
1603 if (!DECL_P (realdecl
))
1607 /* Do not track EXPR if REALDECL it should be ignored for debugging
1609 if (DECL_IGNORED_P (realdecl
))
1612 /* Do not track global variables until we are able to emit correct location
1614 if (TREE_STATIC (realdecl
))
1617 /* When the EXPR is a DECL for alias of some variable (see example)
1618 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1619 DECL_RTL contains SYMBOL_REF.
1622 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1625 if (MEM_P (decl_rtl
)
1626 && contains_symbol_ref (XEXP (decl_rtl
, 0)))
1629 /* If RTX is a memory it should not be very large (because it would be
1630 an array or struct). */
1631 if (MEM_P (decl_rtl
))
1633 /* Do not track structures and arrays. */
1634 if (GET_MODE (decl_rtl
) == BLKmode
1635 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl
)))
1637 if (MEM_SIZE (decl_rtl
)
1638 && INTVAL (MEM_SIZE (decl_rtl
)) > MAX_VAR_PARTS
)
1645 /* Determine whether a given LOC refers to the same variable part as
1649 same_variable_part_p (rtx loc
, tree expr
, HOST_WIDE_INT offset
)
1652 HOST_WIDE_INT offset2
;
1654 if (! DECL_P (expr
))
1659 expr2
= REG_EXPR (loc
);
1660 offset2
= REG_OFFSET (loc
);
1662 else if (MEM_P (loc
))
1664 expr2
= MEM_EXPR (loc
);
1665 offset2
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
1670 if (! expr2
|| ! DECL_P (expr2
))
1673 expr
= var_debug_decl (expr
);
1674 expr2
= var_debug_decl (expr2
);
1676 return (expr
== expr2
&& offset
== offset2
);
1679 /* REG is a register we want to track. If not all of REG contains useful
1680 information, return the mode of the lowpart that does contain useful
1681 information, otherwise return the mode of REG.
1683 If REG was a paradoxical subreg, its REG_ATTRS will describe the
1684 whole subreg, but only the old inner part is really relevant. */
1686 static enum machine_mode
1687 mode_for_reg_attrs (rtx reg
)
1689 enum machine_mode mode
;
1691 mode
= GET_MODE (reg
);
1692 if (!HARD_REGISTER_NUM_P (ORIGINAL_REGNO (reg
)))
1694 enum machine_mode pseudo_mode
;
1696 pseudo_mode
= PSEUDO_REGNO_MODE (ORIGINAL_REGNO (reg
));
1697 if (GET_MODE_SIZE (mode
) > GET_MODE_SIZE (pseudo_mode
))
1703 /* Return the MODE lowpart of LOC, or null if LOC is not something we
1704 want to track. When returning nonnull, make sure that the attributes
1705 on the returned value are updated. */
1708 var_lowpart (enum machine_mode mode
, rtx loc
)
1710 unsigned int offset
, regno
;
1712 if (!REG_P (loc
) && !MEM_P (loc
))
1715 if (GET_MODE (loc
) == mode
)
1718 offset
= subreg_lowpart_offset (mode
, GET_MODE (loc
));
1721 return adjust_address_nv (loc
, mode
, offset
);
1723 regno
= REGNO (loc
) + subreg_regno_offset (REGNO (loc
), GET_MODE (loc
),
1725 return gen_rtx_REG_offset (loc
, mode
, regno
, offset
);
1728 /* Count uses (register and memory references) LOC which will be tracked.
1729 INSN is instruction which the LOC is part of. */
1732 count_uses (rtx
*loc
, void *insn
)
1734 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1738 gcc_assert (REGNO (*loc
) < FIRST_PSEUDO_REGISTER
);
1741 else if (MEM_P (*loc
)
1743 && track_expr_p (MEM_EXPR (*loc
)))
1751 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1754 count_uses_1 (rtx
*x
, void *insn
)
1756 for_each_rtx (x
, count_uses
, insn
);
1759 /* Count stores (register and memory references) LOC which will be tracked.
1760 INSN is instruction which the LOC is part of. */
1763 count_stores (rtx loc
, const_rtx expr ATTRIBUTE_UNUSED
, void *insn
)
1765 count_uses (&loc
, insn
);
1768 /* Add uses (register and memory references) LOC which will be tracked
1769 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
1772 add_uses (rtx
*loc
, void *insn
)
1776 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1777 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1779 if (REG_EXPR (*loc
) && track_expr_p (REG_EXPR (*loc
)))
1782 mo
->u
.loc
= var_lowpart (mode_for_reg_attrs (*loc
), *loc
);
1786 mo
->type
= MO_USE_NO_VAR
;
1789 mo
->insn
= (rtx
) insn
;
1791 else if (MEM_P (*loc
)
1793 && track_expr_p (MEM_EXPR (*loc
)))
1795 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1796 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1800 mo
->insn
= (rtx
) insn
;
1806 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1809 add_uses_1 (rtx
*x
, void *insn
)
1811 for_each_rtx (x
, add_uses
, insn
);
1814 /* Add stores (register and memory references) LOC which will be tracked
1815 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
1816 INSN is instruction which the LOC is part of. */
1819 add_stores (rtx loc
, const_rtx expr
, void *insn
)
1823 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1824 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1826 if (GET_CODE (expr
) == CLOBBER
1828 || ! track_expr_p (REG_EXPR (loc
)))
1830 mo
->type
= MO_CLOBBER
;
1835 enum machine_mode mode
= mode_for_reg_attrs (loc
);
1838 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
1839 src
= var_lowpart (mode
, SET_SRC (expr
));
1840 loc
= var_lowpart (mode
, loc
);
1849 if (SET_SRC (expr
) != src
)
1850 expr
= gen_rtx_SET (VOIDmode
, loc
, src
);
1851 if (same_variable_part_p (src
, REG_EXPR (loc
), REG_OFFSET (loc
)))
1855 mo
->u
.loc
= CONST_CAST_RTX (expr
);
1858 mo
->insn
= (rtx
) insn
;
1860 else if (MEM_P (loc
)
1862 && track_expr_p (MEM_EXPR (loc
)))
1864 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1865 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1867 if (GET_CODE (expr
) == CLOBBER
)
1869 mo
->type
= MO_CLOBBER
;
1876 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
1877 src
= var_lowpart (GET_MODE (loc
), SET_SRC (expr
));
1886 if (same_variable_part_p (SET_SRC (expr
),
1889 ? INTVAL (MEM_OFFSET (loc
)) : 0))
1893 mo
->u
.loc
= CONST_CAST_RTX (expr
);
1896 mo
->insn
= (rtx
) insn
;
1900 static enum var_init_status
1901 find_src_status (dataflow_set
*in
, rtx src
)
1903 tree decl
= NULL_TREE
;
1904 enum var_init_status status
= VAR_INIT_STATUS_UNINITIALIZED
;
1906 if (! flag_var_tracking_uninit
)
1907 status
= VAR_INIT_STATUS_INITIALIZED
;
1909 if (src
&& REG_P (src
))
1910 decl
= var_debug_decl (REG_EXPR (src
));
1911 else if (src
&& MEM_P (src
))
1912 decl
= var_debug_decl (MEM_EXPR (src
));
1915 status
= get_init_value (in
, src
, decl
);
1920 /* SRC is the source of an assignment. Use SET to try to find what
1921 was ultimately assigned to SRC. Return that value if known,
1922 otherwise return SRC itself. */
1925 find_src_set_src (dataflow_set
*set
, rtx src
)
1927 tree decl
= NULL_TREE
; /* The variable being copied around. */
1928 rtx set_src
= NULL_RTX
; /* The value for "decl" stored in "src". */
1931 location_chain nextp
;
1935 if (src
&& REG_P (src
))
1936 decl
= var_debug_decl (REG_EXPR (src
));
1937 else if (src
&& MEM_P (src
))
1938 decl
= var_debug_decl (MEM_EXPR (src
));
1942 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
1943 VARIABLE_HASH_VAL (decl
), NO_INSERT
);
1947 var
= *(variable
*) slot
;
1949 for (i
= 0; i
< var
->n_var_parts
&& !found
; i
++)
1950 for (nextp
= var
->var_part
[i
].loc_chain
; nextp
&& !found
;
1951 nextp
= nextp
->next
)
1952 if (rtx_equal_p (nextp
->loc
, src
))
1954 set_src
= nextp
->set_src
;
1964 /* Compute the changes of variable locations in the basic block BB. */
1967 compute_bb_dataflow (basic_block bb
)
1971 dataflow_set old_out
;
1972 dataflow_set
*in
= &VTI (bb
)->in
;
1973 dataflow_set
*out
= &VTI (bb
)->out
;
1975 dataflow_set_init (&old_out
, htab_elements (VTI (bb
)->out
.vars
) + 3);
1976 dataflow_set_copy (&old_out
, out
);
1977 dataflow_set_copy (out
, in
);
1979 n
= VTI (bb
)->n_mos
;
1980 for (i
= 0; i
< n
; i
++)
1982 switch (VTI (bb
)->mos
[i
].type
)
1985 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
1986 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
1987 var_regno_delete (out
, r
);
1992 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1993 enum var_init_status status
= VAR_INIT_STATUS_UNINITIALIZED
;
1995 if (! flag_var_tracking_uninit
)
1996 status
= VAR_INIT_STATUS_INITIALIZED
;
1998 if (GET_CODE (loc
) == REG
)
1999 var_reg_set (out
, loc
, status
, NULL
);
2000 else if (GET_CODE (loc
) == MEM
)
2001 var_mem_set (out
, loc
, status
, NULL
);
2007 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2010 if (GET_CODE (loc
) == SET
)
2012 set_src
= SET_SRC (loc
);
2013 loc
= SET_DEST (loc
);
2017 var_reg_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2019 else if (MEM_P (loc
))
2020 var_mem_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2027 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2028 enum var_init_status src_status
;
2031 if (GET_CODE (loc
) == SET
)
2033 set_src
= SET_SRC (loc
);
2034 loc
= SET_DEST (loc
);
2037 if (! flag_var_tracking_uninit
)
2038 src_status
= VAR_INIT_STATUS_INITIALIZED
;
2040 src_status
= find_src_status (in
, set_src
);
2042 if (src_status
== VAR_INIT_STATUS_UNKNOWN
)
2043 src_status
= find_src_status (out
, set_src
);
2045 set_src
= find_src_set_src (in
, set_src
);
2048 var_reg_delete_and_set (out
, loc
, false, src_status
, set_src
);
2049 else if (MEM_P (loc
))
2050 var_mem_delete_and_set (out
, loc
, false, src_status
, set_src
);
2056 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2059 var_reg_delete (out
, loc
, false);
2060 else if (MEM_P (loc
))
2061 var_mem_delete (out
, loc
, false);
2067 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2070 var_reg_delete (out
, loc
, true);
2071 else if (MEM_P (loc
))
2072 var_mem_delete (out
, loc
, true);
2077 out
->stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
2082 changed
= dataflow_set_different (&old_out
, out
);
2083 dataflow_set_destroy (&old_out
);
2087 /* Find the locations of variables in the whole function. */
2090 vt_find_locations (void)
2092 fibheap_t worklist
, pending
, fibheap_swap
;
2093 sbitmap visited
, in_worklist
, in_pending
, sbitmap_swap
;
2100 /* Compute reverse completion order of depth first search of the CFG
2101 so that the data-flow runs faster. */
2102 rc_order
= XNEWVEC (int, n_basic_blocks
- NUM_FIXED_BLOCKS
);
2103 bb_order
= XNEWVEC (int, last_basic_block
);
2104 pre_and_rev_post_order_compute (NULL
, rc_order
, false);
2105 for (i
= 0; i
< n_basic_blocks
- NUM_FIXED_BLOCKS
; i
++)
2106 bb_order
[rc_order
[i
]] = i
;
2109 worklist
= fibheap_new ();
2110 pending
= fibheap_new ();
2111 visited
= sbitmap_alloc (last_basic_block
);
2112 in_worklist
= sbitmap_alloc (last_basic_block
);
2113 in_pending
= sbitmap_alloc (last_basic_block
);
2114 sbitmap_zero (in_worklist
);
2117 fibheap_insert (pending
, bb_order
[bb
->index
], bb
);
2118 sbitmap_ones (in_pending
);
2120 while (!fibheap_empty (pending
))
2122 fibheap_swap
= pending
;
2124 worklist
= fibheap_swap
;
2125 sbitmap_swap
= in_pending
;
2126 in_pending
= in_worklist
;
2127 in_worklist
= sbitmap_swap
;
2129 sbitmap_zero (visited
);
2131 while (!fibheap_empty (worklist
))
2133 bb
= fibheap_extract_min (worklist
);
2134 RESET_BIT (in_worklist
, bb
->index
);
2135 if (!TEST_BIT (visited
, bb
->index
))
2140 SET_BIT (visited
, bb
->index
);
2142 /* Calculate the IN set as union of predecessor OUT sets. */
2143 dataflow_set_clear (&VTI (bb
)->in
);
2144 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
2146 dataflow_set_union (&VTI (bb
)->in
, &VTI (e
->src
)->out
);
2149 changed
= compute_bb_dataflow (bb
);
2152 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
2154 if (e
->dest
== EXIT_BLOCK_PTR
)
2160 if (TEST_BIT (visited
, e
->dest
->index
))
2162 if (!TEST_BIT (in_pending
, e
->dest
->index
))
2164 /* Send E->DEST to next round. */
2165 SET_BIT (in_pending
, e
->dest
->index
);
2166 fibheap_insert (pending
,
2167 bb_order
[e
->dest
->index
],
2171 else if (!TEST_BIT (in_worklist
, e
->dest
->index
))
2173 /* Add E->DEST to current round. */
2174 SET_BIT (in_worklist
, e
->dest
->index
);
2175 fibheap_insert (worklist
, bb_order
[e
->dest
->index
],
2185 fibheap_delete (worklist
);
2186 fibheap_delete (pending
);
2187 sbitmap_free (visited
);
2188 sbitmap_free (in_worklist
);
2189 sbitmap_free (in_pending
);
2192 /* Print the content of the LIST to dump file. */
2195 dump_attrs_list (attrs list
)
2197 for (; list
; list
= list
->next
)
2199 print_mem_expr (dump_file
, list
->decl
);
2200 fprintf (dump_file
, "+" HOST_WIDE_INT_PRINT_DEC
, list
->offset
);
2202 fprintf (dump_file
, "\n");
2205 /* Print the information about variable *SLOT to dump file. */
2208 dump_variable (void **slot
, void *data ATTRIBUTE_UNUSED
)
2210 variable var
= *(variable
*) slot
;
2212 location_chain node
;
2214 fprintf (dump_file
, " name: %s",
2215 IDENTIFIER_POINTER (DECL_NAME (var
->decl
)));
2216 if (dump_flags
& TDF_UID
)
2217 fprintf (dump_file
, " D.%u\n", DECL_UID (var
->decl
));
2219 fprintf (dump_file
, "\n");
2221 for (i
= 0; i
< var
->n_var_parts
; i
++)
2223 fprintf (dump_file
, " offset %ld\n",
2224 (long) var
->var_part
[i
].offset
);
2225 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
2227 fprintf (dump_file
, " ");
2228 if (node
->init
== VAR_INIT_STATUS_UNINITIALIZED
)
2229 fprintf (dump_file
, "[uninit]");
2230 print_rtl_single (dump_file
, node
->loc
);
2234 /* Continue traversing the hash table. */
2238 /* Print the information about variables from hash table VARS to dump file. */
2241 dump_vars (htab_t vars
)
2243 if (htab_elements (vars
) > 0)
2245 fprintf (dump_file
, "Variables:\n");
2246 htab_traverse (vars
, dump_variable
, NULL
);
2250 /* Print the dataflow set SET to dump file. */
2253 dump_dataflow_set (dataflow_set
*set
)
2257 fprintf (dump_file
, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC
"\n",
2259 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2263 fprintf (dump_file
, "Reg %d:", i
);
2264 dump_attrs_list (set
->regs
[i
]);
2267 dump_vars (set
->vars
);
2268 fprintf (dump_file
, "\n");
2271 /* Print the IN and OUT sets for each basic block to dump file. */
2274 dump_dataflow_sets (void)
2280 fprintf (dump_file
, "\nBasic block %d:\n", bb
->index
);
2281 fprintf (dump_file
, "IN:\n");
2282 dump_dataflow_set (&VTI (bb
)->in
);
2283 fprintf (dump_file
, "OUT:\n");
2284 dump_dataflow_set (&VTI (bb
)->out
);
2288 /* Add variable VAR to the hash table of changed variables and
2289 if it has no locations delete it from hash table HTAB. */
2292 variable_was_changed (variable var
, htab_t htab
)
2294 hashval_t hash
= VARIABLE_HASH_VAL (var
->decl
);
2300 slot
= (variable
*) htab_find_slot_with_hash (changed_variables
,
2301 var
->decl
, hash
, INSERT
);
2303 if (htab
&& var
->n_var_parts
== 0)
2308 empty_var
= pool_alloc (var_pool
);
2309 empty_var
->decl
= var
->decl
;
2310 empty_var
->refcount
= 1;
2311 empty_var
->n_var_parts
= 0;
2314 old
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
2317 htab_clear_slot (htab
, old
);
2327 if (var
->n_var_parts
== 0)
2329 void **slot
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
2332 htab_clear_slot (htab
, slot
);
2337 /* Look for the index in VAR->var_part corresponding to OFFSET.
2338 Return -1 if not found. If INSERTION_POINT is non-NULL, the
2339 referenced int will be set to the index that the part has or should
2340 have, if it should be inserted. */
2343 find_variable_location_part (variable var
, HOST_WIDE_INT offset
,
2344 int *insertion_point
)
2348 /* Find the location part. */
2350 high
= var
->n_var_parts
;
2353 pos
= (low
+ high
) / 2;
2354 if (var
->var_part
[pos
].offset
< offset
)
2361 if (insertion_point
)
2362 *insertion_point
= pos
;
2364 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
2370 /* Set the part of variable's location in the dataflow set SET. The variable
2371 part is specified by variable's declaration DECL and offset OFFSET and the
2372 part's location by LOC. */
2375 set_variable_part (dataflow_set
*set
, rtx loc
, tree decl
, HOST_WIDE_INT offset
,
2376 enum var_init_status initialized
, rtx set_src
)
2379 location_chain node
, next
;
2380 location_chain
*nextp
;
2384 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
2385 VARIABLE_HASH_VAL (decl
), INSERT
);
2388 /* Create new variable information. */
2389 var
= pool_alloc (var_pool
);
2392 var
->n_var_parts
= 1;
2393 var
->var_part
[0].offset
= offset
;
2394 var
->var_part
[0].loc_chain
= NULL
;
2395 var
->var_part
[0].cur_loc
= NULL
;
2403 var
= (variable
) *slot
;
2405 pos
= find_variable_location_part (var
, offset
, &inspos
);
2409 node
= var
->var_part
[pos
].loc_chain
;
2412 && ((REG_P (node
->loc
) && REG_P (loc
)
2413 && REGNO (node
->loc
) == REGNO (loc
))
2414 || rtx_equal_p (node
->loc
, loc
)))
2416 /* LOC is in the beginning of the chain so we have nothing
2418 if (node
->init
< initialized
)
2419 node
->init
= initialized
;
2420 if (set_src
!= NULL
)
2421 node
->set_src
= set_src
;
2428 /* We have to make a copy of a shared variable. */
2429 if (var
->refcount
> 1)
2430 var
= unshare_variable (set
, var
, initialized
);
2435 /* We have not found the location part, new one will be created. */
2437 /* We have to make a copy of the shared variable. */
2438 if (var
->refcount
> 1)
2439 var
= unshare_variable (set
, var
, initialized
);
2441 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2442 thus there are at most MAX_VAR_PARTS different offsets. */
2443 gcc_assert (var
->n_var_parts
< MAX_VAR_PARTS
);
2445 /* We have to move the elements of array starting at index
2446 inspos to the next position. */
2447 for (pos
= var
->n_var_parts
; pos
> inspos
; pos
--)
2448 var
->var_part
[pos
] = var
->var_part
[pos
- 1];
2451 var
->var_part
[pos
].offset
= offset
;
2452 var
->var_part
[pos
].loc_chain
= NULL
;
2453 var
->var_part
[pos
].cur_loc
= NULL
;
2457 /* Delete the location from the list. */
2458 nextp
= &var
->var_part
[pos
].loc_chain
;
2459 for (node
= var
->var_part
[pos
].loc_chain
; node
; node
= next
)
2462 if ((REG_P (node
->loc
) && REG_P (loc
)
2463 && REGNO (node
->loc
) == REGNO (loc
))
2464 || rtx_equal_p (node
->loc
, loc
))
2466 /* Save these values, to assign to the new node, before
2467 deleting this one. */
2468 if (node
->init
> initialized
)
2469 initialized
= node
->init
;
2470 if (node
->set_src
!= NULL
&& set_src
== NULL
)
2471 set_src
= node
->set_src
;
2472 pool_free (loc_chain_pool
, node
);
2477 nextp
= &node
->next
;
2480 /* Add the location to the beginning. */
2481 node
= pool_alloc (loc_chain_pool
);
2483 node
->init
= initialized
;
2484 node
->set_src
= set_src
;
2485 node
->next
= var
->var_part
[pos
].loc_chain
;
2486 var
->var_part
[pos
].loc_chain
= node
;
2488 /* If no location was emitted do so. */
2489 if (var
->var_part
[pos
].cur_loc
== NULL
)
2491 var
->var_part
[pos
].cur_loc
= loc
;
2492 variable_was_changed (var
, set
->vars
);
2496 /* Remove all recorded register locations for the given variable part
2497 from dataflow set SET, except for those that are identical to loc.
2498 The variable part is specified by variable's declaration DECL and
2502 clobber_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2503 HOST_WIDE_INT offset
, rtx set_src
)
2507 if (! decl
|| ! DECL_P (decl
))
2510 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2514 variable var
= (variable
) *slot
;
2515 int pos
= find_variable_location_part (var
, offset
, NULL
);
2519 location_chain node
, next
;
2521 /* Remove the register locations from the dataflow set. */
2522 next
= var
->var_part
[pos
].loc_chain
;
2523 for (node
= next
; node
; node
= next
)
2526 if (node
->loc
!= loc
2527 && (!flag_var_tracking_uninit
2530 || !rtx_equal_p (set_src
, node
->set_src
)))
2532 if (REG_P (node
->loc
))
2537 /* Remove the variable part from the register's
2538 list, but preserve any other variable parts
2539 that might be regarded as live in that same
2541 anextp
= &set
->regs
[REGNO (node
->loc
)];
2542 for (anode
= *anextp
; anode
; anode
= anext
)
2544 anext
= anode
->next
;
2545 if (anode
->decl
== decl
2546 && anode
->offset
== offset
)
2548 pool_free (attrs_pool
, anode
);
2554 delete_variable_part (set
, node
->loc
, decl
, offset
);
2561 /* Delete the part of variable's location from dataflow set SET. The variable
2562 part is specified by variable's declaration DECL and offset OFFSET and the
2563 part's location by LOC. */
2566 delete_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2567 HOST_WIDE_INT offset
)
2571 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2575 variable var
= (variable
) *slot
;
2576 int pos
= find_variable_location_part (var
, offset
, NULL
);
2580 location_chain node
, next
;
2581 location_chain
*nextp
;
2584 if (var
->refcount
> 1)
2586 /* If the variable contains the location part we have to
2587 make a copy of the variable. */
2588 for (node
= var
->var_part
[pos
].loc_chain
; node
;
2591 if ((REG_P (node
->loc
) && REG_P (loc
)
2592 && REGNO (node
->loc
) == REGNO (loc
))
2593 || rtx_equal_p (node
->loc
, loc
))
2595 enum var_init_status status
= VAR_INIT_STATUS_UNKNOWN
;
2596 if (! flag_var_tracking_uninit
)
2597 status
= VAR_INIT_STATUS_INITIALIZED
;
2598 var
= unshare_variable (set
, var
, status
);
2604 /* Delete the location part. */
2605 nextp
= &var
->var_part
[pos
].loc_chain
;
2606 for (node
= *nextp
; node
; node
= next
)
2609 if ((REG_P (node
->loc
) && REG_P (loc
)
2610 && REGNO (node
->loc
) == REGNO (loc
))
2611 || rtx_equal_p (node
->loc
, loc
))
2613 pool_free (loc_chain_pool
, node
);
2618 nextp
= &node
->next
;
2621 /* If we have deleted the location which was last emitted
2622 we have to emit new location so add the variable to set
2623 of changed variables. */
2624 if (var
->var_part
[pos
].cur_loc
2626 && REG_P (var
->var_part
[pos
].cur_loc
)
2627 && REGNO (loc
) == REGNO (var
->var_part
[pos
].cur_loc
))
2628 || rtx_equal_p (loc
, var
->var_part
[pos
].cur_loc
)))
2631 if (var
->var_part
[pos
].loc_chain
)
2632 var
->var_part
[pos
].cur_loc
= var
->var_part
[pos
].loc_chain
->loc
;
2637 if (var
->var_part
[pos
].loc_chain
== NULL
)
2640 while (pos
< var
->n_var_parts
)
2642 var
->var_part
[pos
] = var
->var_part
[pos
+ 1];
2647 variable_was_changed (var
, set
->vars
);
2652 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2653 additional parameters: WHERE specifies whether the note shall be emitted
2654 before of after instruction INSN. */
2657 emit_note_insn_var_location (void **varp
, void *data
)
2659 variable var
= *(variable
*) varp
;
2660 rtx insn
= ((emit_note_data
*)data
)->insn
;
2661 enum emit_note_where where
= ((emit_note_data
*)data
)->where
;
2663 int i
, j
, n_var_parts
;
2665 enum var_init_status initialized
= VAR_INIT_STATUS_UNINITIALIZED
;
2666 HOST_WIDE_INT last_limit
;
2667 tree type_size_unit
;
2668 HOST_WIDE_INT offsets
[MAX_VAR_PARTS
];
2669 rtx loc
[MAX_VAR_PARTS
];
2671 gcc_assert (var
->decl
);
2673 if (! flag_var_tracking_uninit
)
2674 initialized
= VAR_INIT_STATUS_INITIALIZED
;
2679 for (i
= 0; i
< var
->n_var_parts
; i
++)
2681 enum machine_mode mode
, wider_mode
;
2683 if (last_limit
< var
->var_part
[i
].offset
)
2688 else if (last_limit
> var
->var_part
[i
].offset
)
2690 offsets
[n_var_parts
] = var
->var_part
[i
].offset
;
2691 loc
[n_var_parts
] = var
->var_part
[i
].loc_chain
->loc
;
2692 mode
= GET_MODE (loc
[n_var_parts
]);
2693 initialized
= var
->var_part
[i
].loc_chain
->init
;
2694 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2696 /* Attempt to merge adjacent registers or memory. */
2697 wider_mode
= GET_MODE_WIDER_MODE (mode
);
2698 for (j
= i
+ 1; j
< var
->n_var_parts
; j
++)
2699 if (last_limit
<= var
->var_part
[j
].offset
)
2701 if (j
< var
->n_var_parts
2702 && wider_mode
!= VOIDmode
2703 && GET_CODE (loc
[n_var_parts
])
2704 == GET_CODE (var
->var_part
[j
].loc_chain
->loc
)
2705 && mode
== GET_MODE (var
->var_part
[j
].loc_chain
->loc
)
2706 && last_limit
== var
->var_part
[j
].offset
)
2709 rtx loc2
= var
->var_part
[j
].loc_chain
->loc
;
2711 if (REG_P (loc
[n_var_parts
])
2712 && hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
] * 2
2713 == hard_regno_nregs
[REGNO (loc
[n_var_parts
])][wider_mode
]
2714 && end_hard_regno (mode
, REGNO (loc
[n_var_parts
]))
2717 if (! WORDS_BIG_ENDIAN
&& ! BYTES_BIG_ENDIAN
)
2718 new_loc
= simplify_subreg (wider_mode
, loc
[n_var_parts
],
2720 else if (WORDS_BIG_ENDIAN
&& BYTES_BIG_ENDIAN
)
2721 new_loc
= simplify_subreg (wider_mode
, loc2
, mode
, 0);
2724 if (!REG_P (new_loc
)
2725 || REGNO (new_loc
) != REGNO (loc
[n_var_parts
]))
2728 REG_ATTRS (new_loc
) = REG_ATTRS (loc
[n_var_parts
]);
2731 else if (MEM_P (loc
[n_var_parts
])
2732 && GET_CODE (XEXP (loc2
, 0)) == PLUS
2733 && GET_CODE (XEXP (XEXP (loc2
, 0), 0)) == REG
2734 && GET_CODE (XEXP (XEXP (loc2
, 0), 1)) == CONST_INT
)
2736 if ((GET_CODE (XEXP (loc
[n_var_parts
], 0)) == REG
2737 && rtx_equal_p (XEXP (loc
[n_var_parts
], 0),
2738 XEXP (XEXP (loc2
, 0), 0))
2739 && INTVAL (XEXP (XEXP (loc2
, 0), 1))
2740 == GET_MODE_SIZE (mode
))
2741 || (GET_CODE (XEXP (loc
[n_var_parts
], 0)) == PLUS
2742 && GET_CODE (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2744 && rtx_equal_p (XEXP (XEXP (loc
[n_var_parts
], 0), 0),
2745 XEXP (XEXP (loc2
, 0), 0))
2746 && INTVAL (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2747 + GET_MODE_SIZE (mode
)
2748 == INTVAL (XEXP (XEXP (loc2
, 0), 1))))
2749 new_loc
= adjust_address_nv (loc
[n_var_parts
],
2755 loc
[n_var_parts
] = new_loc
;
2757 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2763 type_size_unit
= TYPE_SIZE_UNIT (TREE_TYPE (var
->decl
));
2764 if ((unsigned HOST_WIDE_INT
) last_limit
< TREE_INT_CST_LOW (type_size_unit
))
2767 if (where
== EMIT_NOTE_AFTER_INSN
)
2768 note
= emit_note_after (NOTE_INSN_VAR_LOCATION
, insn
);
2770 note
= emit_note_before (NOTE_INSN_VAR_LOCATION
, insn
);
2772 if (! flag_var_tracking_uninit
)
2773 initialized
= VAR_INIT_STATUS_INITIALIZED
;
2777 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2778 NULL_RTX
, (int) initialized
);
2780 else if (n_var_parts
== 1)
2783 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[0], GEN_INT (offsets
[0]));
2785 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2789 else if (n_var_parts
)
2793 for (i
= 0; i
< n_var_parts
; i
++)
2795 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[i
], GEN_INT (offsets
[i
]));
2797 parallel
= gen_rtx_PARALLEL (VOIDmode
,
2798 gen_rtvec_v (n_var_parts
, loc
));
2799 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2804 htab_clear_slot (changed_variables
, varp
);
2806 /* When there are no location parts the variable has been already
2807 removed from hash table and a new empty variable was created.
2808 Free the empty variable. */
2809 if (var
->n_var_parts
== 0)
2811 pool_free (var_pool
, var
);
2814 /* Continue traversing the hash table. */
2818 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
2819 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
2820 shall be emitted before of after instruction INSN. */
2823 emit_notes_for_changes (rtx insn
, enum emit_note_where where
)
2825 emit_note_data data
;
2829 htab_traverse (changed_variables
, emit_note_insn_var_location
, &data
);
2832 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
2833 same variable in hash table DATA or is not there at all. */
2836 emit_notes_for_differences_1 (void **slot
, void *data
)
2838 htab_t new_vars
= (htab_t
) data
;
2839 variable old_var
, new_var
;
2841 old_var
= *(variable
*) slot
;
2842 new_var
= htab_find_with_hash (new_vars
, old_var
->decl
,
2843 VARIABLE_HASH_VAL (old_var
->decl
));
2847 /* Variable has disappeared. */
2850 empty_var
= pool_alloc (var_pool
);
2851 empty_var
->decl
= old_var
->decl
;
2852 empty_var
->refcount
= 1;
2853 empty_var
->n_var_parts
= 0;
2854 variable_was_changed (empty_var
, NULL
);
2856 else if (variable_different_p (old_var
, new_var
, true))
2858 variable_was_changed (new_var
, NULL
);
2861 /* Continue traversing the hash table. */
2865 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2869 emit_notes_for_differences_2 (void **slot
, void *data
)
2871 htab_t old_vars
= (htab_t
) data
;
2872 variable old_var
, new_var
;
2874 new_var
= *(variable
*) slot
;
2875 old_var
= htab_find_with_hash (old_vars
, new_var
->decl
,
2876 VARIABLE_HASH_VAL (new_var
->decl
));
2879 /* Variable has appeared. */
2880 variable_was_changed (new_var
, NULL
);
2883 /* Continue traversing the hash table. */
2887 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2891 emit_notes_for_differences (rtx insn
, dataflow_set
*old_set
,
2892 dataflow_set
*new_set
)
2894 htab_traverse (old_set
->vars
, emit_notes_for_differences_1
, new_set
->vars
);
2895 htab_traverse (new_set
->vars
, emit_notes_for_differences_2
, old_set
->vars
);
2896 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2899 /* Emit the notes for changes of location parts in the basic block BB. */
2902 emit_notes_in_bb (basic_block bb
)
2907 dataflow_set_init (&set
, htab_elements (VTI (bb
)->in
.vars
) + 3);
2908 dataflow_set_copy (&set
, &VTI (bb
)->in
);
2910 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
2912 rtx insn
= VTI (bb
)->mos
[i
].insn
;
2914 switch (VTI (bb
)->mos
[i
].type
)
2920 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
2921 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
2923 var_regno_delete (&set
, r
);
2925 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2931 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2933 enum var_init_status status
= VAR_INIT_STATUS_UNINITIALIZED
;
2934 if (! flag_var_tracking_uninit
)
2935 status
= VAR_INIT_STATUS_INITIALIZED
;
2936 if (GET_CODE (loc
) == REG
)
2937 var_reg_set (&set
, loc
, status
, NULL
);
2939 var_mem_set (&set
, loc
, status
, NULL
);
2941 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2947 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2950 if (GET_CODE (loc
) == SET
)
2952 set_src
= SET_SRC (loc
);
2953 loc
= SET_DEST (loc
);
2957 var_reg_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2960 var_mem_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2963 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
2969 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2970 enum var_init_status src_status
;
2973 if (GET_CODE (loc
) == SET
)
2975 set_src
= SET_SRC (loc
);
2976 loc
= SET_DEST (loc
);
2979 src_status
= find_src_status (&set
, set_src
);
2980 set_src
= find_src_set_src (&set
, set_src
);
2983 var_reg_delete_and_set (&set
, loc
, false, src_status
, set_src
);
2985 var_mem_delete_and_set (&set
, loc
, false, src_status
, set_src
);
2987 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
2993 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2996 var_reg_delete (&set
, loc
, false);
2998 var_mem_delete (&set
, loc
, false);
3000 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3006 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3009 var_reg_delete (&set
, loc
, true);
3011 var_mem_delete (&set
, loc
, true);
3013 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3018 set
.stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
3022 dataflow_set_destroy (&set
);
3025 /* Emit notes for the whole function. */
3028 vt_emit_notes (void)
3031 dataflow_set
*last_out
;
3034 gcc_assert (!htab_elements (changed_variables
));
3036 /* Enable emitting notes by functions (mainly by set_variable_part and
3037 delete_variable_part). */
3040 dataflow_set_init (&empty
, 7);
3045 /* Emit the notes for changes of variable locations between two
3046 subsequent basic blocks. */
3047 emit_notes_for_differences (BB_HEAD (bb
), last_out
, &VTI (bb
)->in
);
3049 /* Emit the notes for the changes in the basic block itself. */
3050 emit_notes_in_bb (bb
);
3052 last_out
= &VTI (bb
)->out
;
3054 dataflow_set_destroy (&empty
);
3058 /* If there is a declaration and offset associated with register/memory RTL
3059 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
3062 vt_get_decl_and_offset (rtx rtl
, tree
*declp
, HOST_WIDE_INT
*offsetp
)
3066 if (REG_ATTRS (rtl
))
3068 *declp
= REG_EXPR (rtl
);
3069 *offsetp
= REG_OFFSET (rtl
);
3073 else if (MEM_P (rtl
))
3075 if (MEM_ATTRS (rtl
))
3077 *declp
= MEM_EXPR (rtl
);
3078 *offsetp
= MEM_OFFSET (rtl
) ? INTVAL (MEM_OFFSET (rtl
)) : 0;
3085 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3088 vt_add_function_parameters (void)
3092 for (parm
= DECL_ARGUMENTS (current_function_decl
);
3093 parm
; parm
= TREE_CHAIN (parm
))
3095 rtx decl_rtl
= DECL_RTL_IF_SET (parm
);
3096 rtx incoming
= DECL_INCOMING_RTL (parm
);
3098 HOST_WIDE_INT offset
;
3101 if (TREE_CODE (parm
) != PARM_DECL
)
3104 if (!DECL_NAME (parm
))
3107 if (!decl_rtl
|| !incoming
)
3110 if (GET_MODE (decl_rtl
) == BLKmode
|| GET_MODE (incoming
) == BLKmode
)
3113 if (!vt_get_decl_and_offset (incoming
, &decl
, &offset
))
3114 if (!vt_get_decl_and_offset (decl_rtl
, &decl
, &offset
))
3120 gcc_assert (parm
== decl
);
3122 out
= &VTI (ENTRY_BLOCK_PTR
)->out
;
3124 if (REG_P (incoming
))
3126 gcc_assert (REGNO (incoming
) < FIRST_PSEUDO_REGISTER
);
3127 attrs_list_insert (&out
->regs
[REGNO (incoming
)],
3128 parm
, offset
, incoming
);
3129 set_variable_part (out
, incoming
, parm
, offset
, VAR_INIT_STATUS_INITIALIZED
,
3132 else if (MEM_P (incoming
))
3133 set_variable_part (out
, incoming
, parm
, offset
, VAR_INIT_STATUS_INITIALIZED
,
3138 /* Allocate and initialize the data structures for variable tracking
3139 and parse the RTL to get the micro operations. */
3142 vt_initialize (void)
3146 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def
));
3151 HOST_WIDE_INT pre
, post
= 0;
3153 /* Count the number of micro operations. */
3154 VTI (bb
)->n_mos
= 0;
3155 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
3156 insn
= NEXT_INSN (insn
))
3160 if (!frame_pointer_needed
)
3162 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3168 note_uses (&PATTERN (insn
), count_uses_1
, insn
);
3169 note_stores (PATTERN (insn
), count_stores
, insn
);
3175 /* Add the micro-operations to the array. */
3176 VTI (bb
)->mos
= XNEWVEC (micro_operation
, VTI (bb
)->n_mos
);
3177 VTI (bb
)->n_mos
= 0;
3178 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
3179 insn
= NEXT_INSN (insn
))
3185 if (!frame_pointer_needed
)
3187 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3190 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3192 mo
->type
= MO_ADJUST
;
3198 n1
= VTI (bb
)->n_mos
;
3199 note_uses (&PATTERN (insn
), add_uses_1
, insn
);
3200 n2
= VTI (bb
)->n_mos
- 1;
3202 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
3205 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_USE
)
3207 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_USE_NO_VAR
)
3213 sw
= VTI (bb
)->mos
[n1
];
3214 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
3215 VTI (bb
)->mos
[n2
] = sw
;
3221 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3227 n1
= VTI (bb
)->n_mos
;
3228 /* This will record NEXT_INSN (insn), such that we can
3229 insert notes before it without worrying about any
3230 notes that MO_USEs might emit after the insn. */
3231 note_stores (PATTERN (insn
), add_stores
, insn
);
3232 n2
= VTI (bb
)->n_mos
- 1;
3234 /* Order the MO_CLOBBERs to be before MO_SETs. */
3237 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_CLOBBER
)
3239 while (n1
< n2
&& (VTI (bb
)->mos
[n2
].type
== MO_SET
3240 || VTI (bb
)->mos
[n2
].type
== MO_COPY
))
3246 sw
= VTI (bb
)->mos
[n1
];
3247 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
3248 VTI (bb
)->mos
[n2
] = sw
;
3252 if (!frame_pointer_needed
&& post
)
3254 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3256 mo
->type
= MO_ADJUST
;
3257 mo
->u
.adjust
= post
;
3264 /* Init the IN and OUT sets. */
3267 VTI (bb
)->visited
= false;
3268 dataflow_set_init (&VTI (bb
)->in
, 7);
3269 dataflow_set_init (&VTI (bb
)->out
, 7);
3272 attrs_pool
= create_alloc_pool ("attrs_def pool",
3273 sizeof (struct attrs_def
), 1024);
3274 var_pool
= create_alloc_pool ("variable_def pool",
3275 sizeof (struct variable_def
), 64);
3276 loc_chain_pool
= create_alloc_pool ("location_chain_def pool",
3277 sizeof (struct location_chain_def
),
3279 changed_variables
= htab_create (10, variable_htab_hash
, variable_htab_eq
,
3281 vt_add_function_parameters ();
3284 /* Free the data structures needed for variable tracking. */
3293 free (VTI (bb
)->mos
);
3298 dataflow_set_destroy (&VTI (bb
)->in
);
3299 dataflow_set_destroy (&VTI (bb
)->out
);
3301 free_aux_for_blocks ();
3302 free_alloc_pool (attrs_pool
);
3303 free_alloc_pool (var_pool
);
3304 free_alloc_pool (loc_chain_pool
);
3305 htab_delete (changed_variables
);
3308 /* The entry point to variable tracking pass. */
3311 variable_tracking_main (void)
3313 if (n_basic_blocks
> 500 && n_edges
/ n_basic_blocks
>= 20)
3316 mark_dfs_back_edges ();
3318 if (!frame_pointer_needed
)
3320 if (!vt_stack_adjustments ())
3327 vt_find_locations ();
3330 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3332 dump_dataflow_sets ();
3333 dump_flow_info (dump_file
, dump_flags
);
3341 gate_handle_var_tracking (void)
3343 return (flag_var_tracking
);
3348 struct tree_opt_pass pass_variable_tracking
=
3350 "vartrack", /* name */
3351 gate_handle_var_tracking
, /* gate */
3352 variable_tracking_main
, /* execute */
3355 0, /* static_pass_number */
3356 TV_VAR_TRACKING
, /* tv_id */
3357 0, /* properties_required */
3358 0, /* properties_provided */
3359 0, /* properties_destroyed */
3360 0, /* todo_flags_start */
3361 TODO_dump_func
| TODO_verify_rtl_sharing
,/* todo_flags_finish */