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 a refcounted hash table. If refcount > 1,
186 it must be first unshared before modified. */
187 typedef struct shared_hash_def
189 /* Reference count. */
192 /* Actual hash table. */
196 /* Structure holding the IN or OUT set for a basic block. */
197 typedef struct dataflow_set_def
199 /* Adjustment of stack offset. */
200 HOST_WIDE_INT stack_adjust
;
202 /* Attributes for registers (lists of attrs). */
203 attrs regs
[FIRST_PSEUDO_REGISTER
];
205 /* Variable locations. */
209 /* The structure (one for each basic block) containing the information
210 needed for variable tracking. */
211 typedef struct variable_tracking_info_def
213 /* Number of micro operations stored in the MOS array. */
216 /* The array of micro operations. */
217 micro_operation
*mos
;
219 /* The IN and OUT set for dataflow analysis. */
223 /* Has the block been visited in DFS? */
225 } *variable_tracking_info
;
227 /* Structure for chaining the locations. */
228 typedef struct location_chain_def
230 /* Next element in the chain. */
231 struct location_chain_def
*next
;
233 /* The location (REG or MEM). */
236 /* The "value" stored in this location. */
240 enum var_init_status init
;
243 /* Structure describing one part of variable. */
244 typedef struct variable_part_def
246 /* Chain of locations of the part. */
247 location_chain loc_chain
;
249 /* Location which was last emitted to location list. */
252 /* The offset in the variable. */
253 HOST_WIDE_INT offset
;
256 /* Maximum number of location parts. */
257 #define MAX_VAR_PARTS 16
259 /* Structure describing where the variable is located. */
260 typedef struct variable_def
262 /* The declaration of the variable. */
265 /* Reference count. */
268 /* Number of variable parts. */
271 /* The variable parts. */
272 variable_part var_part
[MAX_VAR_PARTS
];
274 typedef const struct variable_def
*const_variable
;
276 /* Hash function for DECL for VARIABLE_HTAB. */
277 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
279 /* Pointer to the BB's information specific to variable tracking pass. */
280 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
282 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
283 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
285 /* Alloc pool for struct attrs_def. */
286 static alloc_pool attrs_pool
;
288 /* Alloc pool for struct variable_def. */
289 static alloc_pool var_pool
;
291 /* Alloc pool for struct location_chain_def. */
292 static alloc_pool loc_chain_pool
;
294 /* Alloc pool for struct shared_hash_def. */
295 static alloc_pool shared_hash_pool
;
297 /* Changed variables, notes will be emitted for them. */
298 static htab_t changed_variables
;
300 /* Shall notes be emitted? */
301 static bool emit_notes
;
303 /* Empty shared hashtable. */
304 static shared_hash empty_shared_hash
;
306 /* Local function prototypes. */
307 static void stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
309 static void insn_stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
311 static void bb_stack_adjust_offset (basic_block
);
312 static bool vt_stack_adjustments (void);
313 static rtx
adjust_stack_reference (rtx
, HOST_WIDE_INT
);
314 static hashval_t
variable_htab_hash (const void *);
315 static int variable_htab_eq (const void *, const void *);
316 static void variable_htab_free (void *);
318 static void init_attrs_list_set (attrs
*);
319 static void attrs_list_clear (attrs
*);
320 static attrs
attrs_list_member (attrs
, tree
, HOST_WIDE_INT
);
321 static void attrs_list_insert (attrs
*, tree
, HOST_WIDE_INT
, rtx
);
322 static void attrs_list_copy (attrs
*, attrs
);
323 static void attrs_list_union (attrs
*, attrs
);
325 static variable
unshare_variable (dataflow_set
*set
, variable var
,
326 enum var_init_status
);
327 static int vars_copy_1 (void **, void *);
328 static void vars_copy (htab_t
, htab_t
);
329 static tree
var_debug_decl (tree
);
330 static void var_reg_set (dataflow_set
*, rtx
, enum var_init_status
, rtx
);
331 static void var_reg_delete_and_set (dataflow_set
*, rtx
, bool,
332 enum var_init_status
, rtx
);
333 static void var_reg_delete (dataflow_set
*, rtx
, bool);
334 static void var_regno_delete (dataflow_set
*, int);
335 static void var_mem_set (dataflow_set
*, rtx
, enum var_init_status
, rtx
);
336 static void var_mem_delete_and_set (dataflow_set
*, rtx
, bool,
337 enum var_init_status
, rtx
);
338 static void var_mem_delete (dataflow_set
*, rtx
, bool);
340 static void dataflow_set_init (dataflow_set
*);
341 static void dataflow_set_clear (dataflow_set
*);
342 static void dataflow_set_copy (dataflow_set
*, dataflow_set
*);
343 static int variable_union_info_cmp_pos (const void *, const void *);
344 static int variable_union (void **, void *);
345 static int variable_canonicalize (void **, void *);
346 static void dataflow_set_union (dataflow_set
*, dataflow_set
*);
347 static bool variable_part_different_p (variable_part
*, variable_part
*);
348 static bool variable_different_p (variable
, variable
, bool);
349 static int dataflow_set_different_1 (void **, void *);
350 static bool dataflow_set_different (dataflow_set
*, dataflow_set
*);
351 static void dataflow_set_destroy (dataflow_set
*);
353 static bool contains_symbol_ref (rtx
);
354 static bool track_expr_p (tree
);
355 static bool same_variable_part_p (rtx
, tree
, HOST_WIDE_INT
);
356 static int count_uses (rtx
*, void *);
357 static void count_uses_1 (rtx
*, void *);
358 static void count_stores (rtx
, const_rtx
, void *);
359 static int add_uses (rtx
*, void *);
360 static void add_uses_1 (rtx
*, void *);
361 static void add_stores (rtx
, const_rtx
, void *);
362 static bool compute_bb_dataflow (basic_block
);
363 static void vt_find_locations (void);
365 static void dump_attrs_list (attrs
);
366 static int dump_variable (void **, void *);
367 static void dump_vars (htab_t
);
368 static void dump_dataflow_set (dataflow_set
*);
369 static void dump_dataflow_sets (void);
371 static void variable_was_changed (variable
, dataflow_set
*);
372 static void set_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
,
373 enum var_init_status
, rtx
);
374 static void clobber_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
,
376 static void delete_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
377 static int emit_note_insn_var_location (void **, void *);
378 static void emit_notes_for_changes (rtx
, enum emit_note_where
);
379 static int emit_notes_for_differences_1 (void **, void *);
380 static int emit_notes_for_differences_2 (void **, void *);
381 static void emit_notes_for_differences (rtx
, dataflow_set
*, dataflow_set
*);
382 static void emit_notes_in_bb (basic_block
);
383 static void vt_emit_notes (void);
385 static bool vt_get_decl_and_offset (rtx
, tree
*, HOST_WIDE_INT
*);
386 static void vt_add_function_parameters (void);
387 static void vt_initialize (void);
388 static void vt_finalize (void);
390 /* Given a SET, calculate the amount of stack adjustment it contains
391 PRE- and POST-modifying stack pointer.
392 This function is similar to stack_adjust_offset. */
395 stack_adjust_offset_pre_post (rtx pattern
, HOST_WIDE_INT
*pre
,
398 rtx src
= SET_SRC (pattern
);
399 rtx dest
= SET_DEST (pattern
);
402 if (dest
== stack_pointer_rtx
)
404 /* (set (reg sp) (plus (reg sp) (const_int))) */
405 code
= GET_CODE (src
);
406 if (! (code
== PLUS
|| code
== MINUS
)
407 || XEXP (src
, 0) != stack_pointer_rtx
408 || !CONST_INT_P (XEXP (src
, 1)))
412 *post
+= INTVAL (XEXP (src
, 1));
414 *post
-= INTVAL (XEXP (src
, 1));
416 else if (MEM_P (dest
))
418 /* (set (mem (pre_dec (reg sp))) (foo)) */
419 src
= XEXP (dest
, 0);
420 code
= GET_CODE (src
);
426 if (XEXP (src
, 0) == stack_pointer_rtx
)
428 rtx val
= XEXP (XEXP (src
, 1), 1);
429 /* We handle only adjustments by constant amount. */
430 gcc_assert (GET_CODE (XEXP (src
, 1)) == PLUS
&&
433 if (code
== PRE_MODIFY
)
434 *pre
-= INTVAL (val
);
436 *post
-= INTVAL (val
);
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
));
458 if (XEXP (src
, 0) == stack_pointer_rtx
)
460 *pre
-= GET_MODE_SIZE (GET_MODE (dest
));
466 if (XEXP (src
, 0) == stack_pointer_rtx
)
468 *post
-= GET_MODE_SIZE (GET_MODE (dest
));
479 /* Given an INSN, calculate the amount of stack adjustment it contains
480 PRE- and POST-modifying stack pointer. */
483 insn_stack_adjust_offset_pre_post (rtx insn
, HOST_WIDE_INT
*pre
,
491 pattern
= PATTERN (insn
);
492 if (RTX_FRAME_RELATED_P (insn
))
494 rtx expr
= find_reg_note (insn
, REG_FRAME_RELATED_EXPR
, NULL_RTX
);
496 pattern
= XEXP (expr
, 0);
499 if (GET_CODE (pattern
) == SET
)
500 stack_adjust_offset_pre_post (pattern
, pre
, post
);
501 else if (GET_CODE (pattern
) == PARALLEL
502 || GET_CODE (pattern
) == SEQUENCE
)
506 /* There may be stack adjustments inside compound insns. Search
508 for ( i
= XVECLEN (pattern
, 0) - 1; i
>= 0; i
--)
509 if (GET_CODE (XVECEXP (pattern
, 0, i
)) == SET
)
510 stack_adjust_offset_pre_post (XVECEXP (pattern
, 0, i
), pre
, post
);
514 /* Compute stack adjustment in basic block BB. */
517 bb_stack_adjust_offset (basic_block bb
)
519 HOST_WIDE_INT offset
;
522 offset
= VTI (bb
)->in
.stack_adjust
;
523 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
525 if (VTI (bb
)->mos
[i
].type
== MO_ADJUST
)
526 offset
+= VTI (bb
)->mos
[i
].u
.adjust
;
527 else if (VTI (bb
)->mos
[i
].type
!= MO_CALL
)
529 if (MEM_P (VTI (bb
)->mos
[i
].u
.loc
))
531 VTI (bb
)->mos
[i
].u
.loc
532 = adjust_stack_reference (VTI (bb
)->mos
[i
].u
.loc
, -offset
);
536 VTI (bb
)->out
.stack_adjust
= offset
;
539 /* Compute stack adjustments for all blocks by traversing DFS tree.
540 Return true when the adjustments on all incoming edges are consistent.
541 Heavily borrowed from pre_and_rev_post_order_compute. */
544 vt_stack_adjustments (void)
546 edge_iterator
*stack
;
549 /* Initialize entry block. */
550 VTI (ENTRY_BLOCK_PTR
)->visited
= true;
551 VTI (ENTRY_BLOCK_PTR
)->out
.stack_adjust
= INCOMING_FRAME_SP_OFFSET
;
553 /* Allocate stack for back-tracking up CFG. */
554 stack
= XNEWVEC (edge_iterator
, n_basic_blocks
+ 1);
557 /* Push the first edge on to the stack. */
558 stack
[sp
++] = ei_start (ENTRY_BLOCK_PTR
->succs
);
566 /* Look at the edge on the top of the stack. */
568 src
= ei_edge (ei
)->src
;
569 dest
= ei_edge (ei
)->dest
;
571 /* Check if the edge destination has been visited yet. */
572 if (!VTI (dest
)->visited
)
574 VTI (dest
)->visited
= true;
575 VTI (dest
)->in
.stack_adjust
= VTI (src
)->out
.stack_adjust
;
576 bb_stack_adjust_offset (dest
);
578 if (EDGE_COUNT (dest
->succs
) > 0)
579 /* Since the DEST node has been visited for the first
580 time, check its successors. */
581 stack
[sp
++] = ei_start (dest
->succs
);
585 /* Check whether the adjustments on the edges are the same. */
586 if (VTI (dest
)->in
.stack_adjust
!= VTI (src
)->out
.stack_adjust
)
592 if (! ei_one_before_end_p (ei
))
593 /* Go to the next edge. */
594 ei_next (&stack
[sp
- 1]);
596 /* Return to previous level if there are no more edges. */
605 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
606 to the argument pointer. Return the new rtx. */
609 adjust_stack_reference (rtx mem
, HOST_WIDE_INT adjustment
)
613 #ifdef FRAME_POINTER_CFA_OFFSET
614 adjustment
-= FRAME_POINTER_CFA_OFFSET (current_function_decl
);
615 cfa
= plus_constant (frame_pointer_rtx
, adjustment
);
617 adjustment
-= ARG_POINTER_CFA_OFFSET (current_function_decl
);
618 cfa
= plus_constant (arg_pointer_rtx
, adjustment
);
621 addr
= replace_rtx (copy_rtx (XEXP (mem
, 0)), stack_pointer_rtx
, cfa
);
622 tmp
= simplify_rtx (addr
);
626 return replace_equiv_address_nv (mem
, addr
);
629 /* The hash function for variable_htab, computes the hash value
630 from the declaration of variable X. */
633 variable_htab_hash (const void *x
)
635 const_variable
const v
= (const_variable
) x
;
637 return (VARIABLE_HASH_VAL (v
->decl
));
640 /* Compare the declaration of variable X with declaration Y. */
643 variable_htab_eq (const void *x
, const void *y
)
645 const_variable
const v
= (const_variable
) x
;
646 const_tree
const decl
= (const_tree
) y
;
648 return (VARIABLE_HASH_VAL (v
->decl
) == VARIABLE_HASH_VAL (decl
));
651 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
654 variable_htab_free (void *elem
)
657 variable var
= (variable
) elem
;
658 location_chain node
, next
;
660 gcc_assert (var
->refcount
> 0);
663 if (var
->refcount
> 0)
666 for (i
= 0; i
< var
->n_var_parts
; i
++)
668 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= next
)
671 pool_free (loc_chain_pool
, node
);
673 var
->var_part
[i
].loc_chain
= NULL
;
675 pool_free (var_pool
, var
);
678 /* Initialize the set (array) SET of attrs to empty lists. */
681 init_attrs_list_set (attrs
*set
)
685 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
689 /* Make the list *LISTP empty. */
692 attrs_list_clear (attrs
*listp
)
696 for (list
= *listp
; list
; list
= next
)
699 pool_free (attrs_pool
, list
);
704 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
707 attrs_list_member (attrs list
, tree decl
, HOST_WIDE_INT offset
)
709 for (; list
; list
= list
->next
)
710 if (list
->decl
== decl
&& list
->offset
== offset
)
715 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
718 attrs_list_insert (attrs
*listp
, tree decl
, HOST_WIDE_INT offset
, rtx loc
)
722 list
= (attrs
) pool_alloc (attrs_pool
);
725 list
->offset
= offset
;
730 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
733 attrs_list_copy (attrs
*dstp
, attrs src
)
737 attrs_list_clear (dstp
);
738 for (; src
; src
= src
->next
)
740 n
= (attrs
) pool_alloc (attrs_pool
);
743 n
->offset
= src
->offset
;
749 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
752 attrs_list_union (attrs
*dstp
, attrs src
)
754 for (; src
; src
= src
->next
)
756 if (!attrs_list_member (*dstp
, src
->decl
, src
->offset
))
757 attrs_list_insert (dstp
, src
->decl
, src
->offset
, src
->loc
);
761 /* Shared hashtable support. */
763 /* Return true if VARS is shared. */
766 shared_hash_shared (shared_hash vars
)
768 return vars
->refcount
> 1;
771 /* Return the hash table for VARS. */
774 shared_hash_htab (shared_hash vars
)
779 /* Copy variables into a new hash table. */
782 shared_hash_unshare (shared_hash vars
)
784 shared_hash new_vars
= (shared_hash
) pool_alloc (shared_hash_pool
);
785 gcc_assert (vars
->refcount
> 1);
786 new_vars
->refcount
= 1;
788 = htab_create (htab_elements (vars
->htab
) + 3, variable_htab_hash
,
789 variable_htab_eq
, variable_htab_free
);
790 vars_copy (new_vars
->htab
, vars
->htab
);
795 /* Increment reference counter on VARS and return it. */
797 static inline shared_hash
798 shared_hash_copy (shared_hash vars
)
804 /* Decrement reference counter and destroy hash table if not shared
808 shared_hash_destroy (shared_hash vars
)
810 gcc_assert (vars
->refcount
> 0);
811 if (--vars
->refcount
== 0)
813 htab_delete (vars
->htab
);
814 pool_free (shared_hash_pool
, vars
);
818 /* Unshare *PVARS if shared and return slot for DECL. If INS is
819 INSERT, insert it if not already present. */
821 static inline void **
822 shared_hash_find_slot_unshare (shared_hash
*pvars
, tree decl
,
823 enum insert_option ins
)
825 if (shared_hash_shared (*pvars
))
826 *pvars
= shared_hash_unshare (*pvars
);
827 return htab_find_slot_with_hash (shared_hash_htab (*pvars
), decl
,
828 VARIABLE_HASH_VAL (decl
), ins
);
831 /* Return slot for DECL, if it is already present in the hash table.
832 If it is not present, insert it only VARS is not shared, otherwise
835 static inline void **
836 shared_hash_find_slot (shared_hash vars
, tree decl
)
838 return htab_find_slot_with_hash (shared_hash_htab (vars
), decl
,
839 VARIABLE_HASH_VAL (decl
),
840 shared_hash_shared (vars
)
841 ? NO_INSERT
: INSERT
);
844 /* Return slot for DECL only if it is already present in the hash table. */
846 static inline void **
847 shared_hash_find_slot_noinsert (shared_hash vars
, tree decl
)
849 return htab_find_slot_with_hash (shared_hash_htab (vars
), decl
,
850 VARIABLE_HASH_VAL (decl
), NO_INSERT
);
853 /* Return variable for DECL or NULL if not already present in the hash
856 static inline variable
857 shared_hash_find (shared_hash vars
, tree decl
)
860 htab_find_with_hash (shared_hash_htab (vars
), decl
,
861 VARIABLE_HASH_VAL (decl
));
864 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
867 unshare_variable (dataflow_set
*set
, variable var
,
868 enum var_init_status initialized
)
874 new_var
= (variable
) pool_alloc (var_pool
);
875 new_var
->decl
= var
->decl
;
876 new_var
->refcount
= 1;
878 new_var
->n_var_parts
= var
->n_var_parts
;
880 if (! flag_var_tracking_uninit
)
881 initialized
= VAR_INIT_STATUS_INITIALIZED
;
883 for (i
= 0; i
< var
->n_var_parts
; i
++)
886 location_chain
*nextp
;
888 new_var
->var_part
[i
].offset
= var
->var_part
[i
].offset
;
889 nextp
= &new_var
->var_part
[i
].loc_chain
;
890 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
892 location_chain new_lc
;
894 new_lc
= (location_chain
) pool_alloc (loc_chain_pool
);
896 if (node
->init
> initialized
)
897 new_lc
->init
= node
->init
;
899 new_lc
->init
= initialized
;
900 if (node
->set_src
&& !(MEM_P (node
->set_src
)))
901 new_lc
->set_src
= node
->set_src
;
903 new_lc
->set_src
= NULL
;
904 new_lc
->loc
= node
->loc
;
907 nextp
= &new_lc
->next
;
910 /* We are at the basic block boundary when copying variable description
911 so set the CUR_LOC to be the first element of the chain. */
912 if (new_var
->var_part
[i
].loc_chain
)
913 new_var
->var_part
[i
].cur_loc
= new_var
->var_part
[i
].loc_chain
->loc
;
915 new_var
->var_part
[i
].cur_loc
= NULL
;
918 slot
= shared_hash_find_slot_unshare (&set
->vars
, new_var
->decl
, INSERT
);
923 /* Add a variable from *SLOT to hash table DATA and increase its reference
927 vars_copy_1 (void **slot
, void *data
)
929 htab_t dst
= (htab_t
) data
;
932 src
= *(variable
*) slot
;
935 dstp
= (variable
*) htab_find_slot_with_hash (dst
, src
->decl
,
936 VARIABLE_HASH_VAL (src
->decl
),
940 /* Continue traversing the hash table. */
944 /* Copy all variables from hash table SRC to hash table DST. */
947 vars_copy (htab_t dst
, htab_t src
)
949 htab_traverse_noresize (src
, vars_copy_1
, dst
);
952 /* Map a decl to its main debug decl. */
955 var_debug_decl (tree decl
)
957 if (decl
&& DECL_P (decl
)
958 && DECL_DEBUG_EXPR_IS_FROM (decl
) && DECL_DEBUG_EXPR (decl
)
959 && DECL_P (DECL_DEBUG_EXPR (decl
)))
960 decl
= DECL_DEBUG_EXPR (decl
);
965 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
968 var_reg_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
971 tree decl
= REG_EXPR (loc
);
972 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
975 decl
= var_debug_decl (decl
);
977 for (node
= set
->regs
[REGNO (loc
)]; node
; node
= node
->next
)
978 if (node
->decl
== decl
&& node
->offset
== offset
)
981 attrs_list_insert (&set
->regs
[REGNO (loc
)], decl
, offset
, loc
);
982 set_variable_part (set
, loc
, decl
, offset
, initialized
, set_src
);
985 static enum var_init_status
986 get_init_value (dataflow_set
*set
, rtx loc
, tree decl
)
990 enum var_init_status ret_val
= VAR_INIT_STATUS_UNKNOWN
;
992 if (! flag_var_tracking_uninit
)
993 return VAR_INIT_STATUS_INITIALIZED
;
995 var
= shared_hash_find (set
->vars
, decl
);
998 for (i
= 0; i
< var
->n_var_parts
&& ret_val
== VAR_INIT_STATUS_UNKNOWN
; i
++)
1000 location_chain nextp
;
1001 for (nextp
= var
->var_part
[i
].loc_chain
; nextp
; nextp
= nextp
->next
)
1002 if (rtx_equal_p (nextp
->loc
, loc
))
1004 ret_val
= nextp
->init
;
1013 /* Delete current content of register LOC in dataflow set SET and set
1014 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
1015 MODIFY is true, any other live copies of the same variable part are
1016 also deleted from the dataflow set, otherwise the variable part is
1017 assumed to be copied from another location holding the same
1021 var_reg_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
,
1022 enum var_init_status initialized
, rtx set_src
)
1024 tree decl
= REG_EXPR (loc
);
1025 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
1029 decl
= var_debug_decl (decl
);
1031 if (initialized
== VAR_INIT_STATUS_UNKNOWN
)
1032 initialized
= get_init_value (set
, loc
, decl
);
1034 nextp
= &set
->regs
[REGNO (loc
)];
1035 for (node
= *nextp
; node
; node
= next
)
1038 if (node
->decl
!= decl
|| node
->offset
!= offset
)
1040 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
1041 pool_free (attrs_pool
, node
);
1047 nextp
= &node
->next
;
1051 clobber_variable_part (set
, loc
, decl
, offset
, set_src
);
1052 var_reg_set (set
, loc
, initialized
, set_src
);
1055 /* Delete current content of register LOC in dataflow set SET. If
1056 CLOBBER is true, also delete any other live copies of the same
1060 var_reg_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
1062 attrs
*reg
= &set
->regs
[REGNO (loc
)];
1067 tree decl
= REG_EXPR (loc
);
1068 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
1070 decl
= var_debug_decl (decl
);
1072 clobber_variable_part (set
, NULL
, decl
, offset
, NULL
);
1075 for (node
= *reg
; node
; node
= next
)
1078 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
1079 pool_free (attrs_pool
, node
);
1084 /* Delete content of register with number REGNO in dataflow set SET. */
1087 var_regno_delete (dataflow_set
*set
, int regno
)
1089 attrs
*reg
= &set
->regs
[regno
];
1092 for (node
= *reg
; node
; node
= next
)
1095 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
1096 pool_free (attrs_pool
, node
);
1101 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
1103 Adjust the address first if it is stack pointer based. */
1106 var_mem_set (dataflow_set
*set
, rtx loc
, enum var_init_status initialized
,
1109 tree decl
= MEM_EXPR (loc
);
1110 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
1112 decl
= var_debug_decl (decl
);
1114 set_variable_part (set
, loc
, decl
, offset
, initialized
, set_src
);
1117 /* Delete and set the location part of variable MEM_EXPR (LOC) in
1118 dataflow set SET to LOC. If MODIFY is true, any other live copies
1119 of the same variable part are also deleted from the dataflow set,
1120 otherwise the variable part is assumed to be copied from another
1121 location holding the same part.
1122 Adjust the address first if it is stack pointer based. */
1125 var_mem_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
,
1126 enum var_init_status initialized
, rtx set_src
)
1128 tree decl
= MEM_EXPR (loc
);
1129 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
1131 decl
= var_debug_decl (decl
);
1133 if (initialized
== VAR_INIT_STATUS_UNKNOWN
)
1134 initialized
= get_init_value (set
, loc
, decl
);
1137 clobber_variable_part (set
, NULL
, decl
, offset
, set_src
);
1138 var_mem_set (set
, loc
, initialized
, set_src
);
1141 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
1142 true, also delete any other live copies of the same variable part.
1143 Adjust the address first if it is stack pointer based. */
1146 var_mem_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
1148 tree decl
= MEM_EXPR (loc
);
1149 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
1151 decl
= var_debug_decl (decl
);
1153 clobber_variable_part (set
, NULL
, decl
, offset
, NULL
);
1154 delete_variable_part (set
, loc
, decl
, offset
);
1157 /* Initialize dataflow set SET to be empty.
1158 VARS_SIZE is the initial size of hash table VARS. */
1161 dataflow_set_init (dataflow_set
*set
)
1163 init_attrs_list_set (set
->regs
);
1164 set
->vars
= shared_hash_copy (empty_shared_hash
);
1165 set
->stack_adjust
= 0;
1168 /* Delete the contents of dataflow set SET. */
1171 dataflow_set_clear (dataflow_set
*set
)
1175 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1176 attrs_list_clear (&set
->regs
[i
]);
1178 shared_hash_destroy (set
->vars
);
1179 set
->vars
= shared_hash_copy (empty_shared_hash
);
1182 /* Copy the contents of dataflow set SRC to DST. */
1185 dataflow_set_copy (dataflow_set
*dst
, dataflow_set
*src
)
1189 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1190 attrs_list_copy (&dst
->regs
[i
], src
->regs
[i
]);
1192 shared_hash_destroy (dst
->vars
);
1193 dst
->vars
= shared_hash_copy (src
->vars
);
1194 dst
->stack_adjust
= src
->stack_adjust
;
1197 /* Information for merging lists of locations for a given offset of variable.
1199 struct variable_union_info
1201 /* Node of the location chain. */
1204 /* The sum of positions in the input chains. */
1207 /* The position in the chain of DST dataflow set. */
1211 /* Buffer for location list sorting and its allocated size. */
1212 static struct variable_union_info
*vui_vec
;
1213 static int vui_allocated
;
1215 /* Compare function for qsort, order the structures by POS element. */
1218 variable_union_info_cmp_pos (const void *n1
, const void *n2
)
1220 const struct variable_union_info
*const i1
=
1221 (const struct variable_union_info
*) n1
;
1222 const struct variable_union_info
*const i2
=
1223 ( const struct variable_union_info
*) n2
;
1225 if (i1
->pos
!= i2
->pos
)
1226 return i1
->pos
- i2
->pos
;
1228 return (i1
->pos_dst
- i2
->pos_dst
);
1231 /* Compute union of location parts of variable *SLOT and the same variable
1232 from hash table DATA. Compute "sorted" union of the location chains
1233 for common offsets, i.e. the locations of a variable part are sorted by
1234 a priority where the priority is the sum of the positions in the 2 chains
1235 (if a location is only in one list the position in the second list is
1236 defined to be larger than the length of the chains).
1237 When we are updating the location parts the newest location is in the
1238 beginning of the chain, so when we do the described "sorted" union
1239 we keep the newest locations in the beginning. */
1242 variable_union (void **slot
, void *data
)
1246 dataflow_set
*set
= (dataflow_set
*) data
;
1249 src
= *(variable
*) slot
;
1250 dstp
= shared_hash_find_slot (set
->vars
, src
->decl
);
1251 if (!dstp
|| !*dstp
)
1255 /* If CUR_LOC of some variable part is not the first element of
1256 the location chain we are going to change it so we have to make
1257 a copy of the variable. */
1258 for (k
= 0; k
< src
->n_var_parts
; k
++)
1260 gcc_assert (!src
->var_part
[k
].loc_chain
1261 == !src
->var_part
[k
].cur_loc
);
1262 if (src
->var_part
[k
].loc_chain
)
1264 gcc_assert (src
->var_part
[k
].cur_loc
);
1265 if (src
->var_part
[k
].cur_loc
!= src
->var_part
[k
].loc_chain
->loc
)
1269 if (k
< src
->n_var_parts
)
1272 *dstp
= (void *) src
;
1273 unshare_variable (set
, src
, VAR_INIT_STATUS_UNKNOWN
);
1278 dstp
= shared_hash_find_slot_unshare (&set
->vars
, src
->decl
,
1280 *dstp
= (void *) src
;
1283 /* Continue traversing the hash table. */
1287 dst
= (variable
) *dstp
;
1289 gcc_assert (src
->n_var_parts
);
1291 /* Count the number of location parts, result is K. */
1292 for (i
= 0, j
= 0, k
= 0;
1293 i
< src
->n_var_parts
&& j
< dst
->n_var_parts
; k
++)
1295 if (src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1300 else if (src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1305 k
+= src
->n_var_parts
- i
;
1306 k
+= dst
->n_var_parts
- j
;
1308 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1309 thus there are at most MAX_VAR_PARTS different offsets. */
1310 gcc_assert (k
<= MAX_VAR_PARTS
);
1312 if ((dst
->refcount
> 1 || shared_hash_shared (set
->vars
))
1313 && dst
->n_var_parts
!= k
)
1314 dst
= unshare_variable (set
, dst
, VAR_INIT_STATUS_UNKNOWN
);
1316 i
= src
->n_var_parts
- 1;
1317 j
= dst
->n_var_parts
- 1;
1318 dst
->n_var_parts
= k
;
1320 for (k
--; k
>= 0; k
--)
1322 location_chain node
, node2
;
1324 if (i
>= 0 && j
>= 0
1325 && src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1327 /* Compute the "sorted" union of the chains, i.e. the locations which
1328 are in both chains go first, they are sorted by the sum of
1329 positions in the chains. */
1332 struct variable_union_info
*vui
;
1334 /* If DST is shared compare the location chains.
1335 If they are different we will modify the chain in DST with
1336 high probability so make a copy of DST. */
1337 if (dst
->refcount
> 1 || shared_hash_shared (set
->vars
))
1339 for (node
= src
->var_part
[i
].loc_chain
,
1340 node2
= dst
->var_part
[j
].loc_chain
; node
&& node2
;
1341 node
= node
->next
, node2
= node2
->next
)
1343 if (!((REG_P (node2
->loc
)
1344 && REG_P (node
->loc
)
1345 && REGNO (node2
->loc
) == REGNO (node
->loc
))
1346 || rtx_equal_p (node2
->loc
, node
->loc
)))
1348 if (node2
->init
< node
->init
)
1349 node2
->init
= node
->init
;
1354 dst
= unshare_variable (set
, dst
, VAR_INIT_STATUS_UNKNOWN
);
1358 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1361 for (node
= dst
->var_part
[j
].loc_chain
; node
; node
= node
->next
)
1366 /* The most common case, much simpler, no qsort is needed. */
1367 location_chain dstnode
= dst
->var_part
[j
].loc_chain
;
1368 dst
->var_part
[k
].loc_chain
= dstnode
;
1369 dst
->var_part
[k
].offset
= dst
->var_part
[j
].offset
;
1371 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1372 if (!((REG_P (dstnode
->loc
)
1373 && REG_P (node
->loc
)
1374 && REGNO (dstnode
->loc
) == REGNO (node
->loc
))
1375 || rtx_equal_p (dstnode
->loc
, node
->loc
)))
1377 location_chain new_node
;
1379 /* Copy the location from SRC. */
1380 new_node
= (location_chain
) pool_alloc (loc_chain_pool
);
1381 new_node
->loc
= node
->loc
;
1382 new_node
->init
= node
->init
;
1383 if (!node
->set_src
|| MEM_P (node
->set_src
))
1384 new_node
->set_src
= NULL
;
1386 new_node
->set_src
= node
->set_src
;
1387 node2
->next
= new_node
;
1394 if (src_l
+ dst_l
> vui_allocated
)
1396 vui_allocated
= MAX (vui_allocated
* 2, src_l
+ dst_l
);
1397 vui_vec
= XRESIZEVEC (struct variable_union_info
, vui_vec
,
1402 /* Fill in the locations from DST. */
1403 for (node
= dst
->var_part
[j
].loc_chain
, jj
= 0; node
;
1404 node
= node
->next
, jj
++)
1407 vui
[jj
].pos_dst
= jj
;
1409 /* Pos plus value larger than a sum of 2 valid positions. */
1410 vui
[jj
].pos
= jj
+ src_l
+ dst_l
;
1413 /* Fill in the locations from SRC. */
1415 for (node
= src
->var_part
[i
].loc_chain
, ii
= 0; node
;
1416 node
= node
->next
, ii
++)
1418 /* Find location from NODE. */
1419 for (jj
= 0; jj
< dst_l
; jj
++)
1421 if ((REG_P (vui
[jj
].lc
->loc
)
1422 && REG_P (node
->loc
)
1423 && REGNO (vui
[jj
].lc
->loc
) == REGNO (node
->loc
))
1424 || rtx_equal_p (vui
[jj
].lc
->loc
, node
->loc
))
1426 vui
[jj
].pos
= jj
+ ii
;
1430 if (jj
>= dst_l
) /* The location has not been found. */
1432 location_chain new_node
;
1434 /* Copy the location from SRC. */
1435 new_node
= (location_chain
) pool_alloc (loc_chain_pool
);
1436 new_node
->loc
= node
->loc
;
1437 new_node
->init
= node
->init
;
1438 if (!node
->set_src
|| MEM_P (node
->set_src
))
1439 new_node
->set_src
= NULL
;
1441 new_node
->set_src
= node
->set_src
;
1442 vui
[n
].lc
= new_node
;
1443 vui
[n
].pos_dst
= src_l
+ dst_l
;
1444 vui
[n
].pos
= ii
+ src_l
+ dst_l
;
1451 /* Special case still very common case. For dst_l == 2
1452 all entries dst_l ... n-1 are sorted, with for i >= dst_l
1453 vui[i].pos == i + src_l + dst_l. */
1454 if (vui
[0].pos
> vui
[1].pos
)
1456 /* Order should be 1, 0, 2... */
1457 dst
->var_part
[k
].loc_chain
= vui
[1].lc
;
1458 vui
[1].lc
->next
= vui
[0].lc
;
1461 vui
[0].lc
->next
= vui
[2].lc
;
1462 vui
[n
- 1].lc
->next
= NULL
;
1465 vui
[0].lc
->next
= NULL
;
1470 dst
->var_part
[k
].loc_chain
= vui
[0].lc
;
1471 if (n
>= 3 && vui
[2].pos
< vui
[1].pos
)
1473 /* Order should be 0, 2, 1, 3... */
1474 vui
[0].lc
->next
= vui
[2].lc
;
1475 vui
[2].lc
->next
= vui
[1].lc
;
1478 vui
[1].lc
->next
= vui
[3].lc
;
1479 vui
[n
- 1].lc
->next
= NULL
;
1482 vui
[1].lc
->next
= NULL
;
1487 /* Order should be 0, 1, 2... */
1489 vui
[n
- 1].lc
->next
= NULL
;
1492 for (; ii
< n
; ii
++)
1493 vui
[ii
- 1].lc
->next
= vui
[ii
].lc
;
1497 qsort (vui
, n
, sizeof (struct variable_union_info
),
1498 variable_union_info_cmp_pos
);
1500 /* Reconnect the nodes in sorted order. */
1501 for (ii
= 1; ii
< n
; ii
++)
1502 vui
[ii
- 1].lc
->next
= vui
[ii
].lc
;
1503 vui
[n
- 1].lc
->next
= NULL
;
1504 dst
->var_part
[k
].loc_chain
= vui
[0].lc
;
1507 dst
->var_part
[k
].offset
= dst
->var_part
[j
].offset
;
1512 else if ((i
>= 0 && j
>= 0
1513 && src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1516 dst
->var_part
[k
] = dst
->var_part
[j
];
1519 else if ((i
>= 0 && j
>= 0
1520 && src
->var_part
[i
].offset
> dst
->var_part
[j
].offset
)
1523 location_chain
*nextp
;
1525 /* Copy the chain from SRC. */
1526 nextp
= &dst
->var_part
[k
].loc_chain
;
1527 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1529 location_chain new_lc
;
1531 new_lc
= (location_chain
) pool_alloc (loc_chain_pool
);
1532 new_lc
->next
= NULL
;
1533 new_lc
->init
= node
->init
;
1534 if (!node
->set_src
|| MEM_P (node
->set_src
))
1535 new_lc
->set_src
= NULL
;
1537 new_lc
->set_src
= node
->set_src
;
1538 new_lc
->loc
= node
->loc
;
1541 nextp
= &new_lc
->next
;
1544 dst
->var_part
[k
].offset
= src
->var_part
[i
].offset
;
1548 /* We are at the basic block boundary when computing union
1549 so set the CUR_LOC to be the first element of the chain. */
1550 if (dst
->var_part
[k
].loc_chain
)
1551 dst
->var_part
[k
].cur_loc
= dst
->var_part
[k
].loc_chain
->loc
;
1553 dst
->var_part
[k
].cur_loc
= NULL
;
1556 if (flag_var_tracking_uninit
)
1557 for (i
= 0; i
< src
->n_var_parts
&& i
< dst
->n_var_parts
; i
++)
1559 location_chain node
, node2
;
1560 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1561 for (node2
= dst
->var_part
[i
].loc_chain
; node2
; node2
= node2
->next
)
1562 if (rtx_equal_p (node
->loc
, node2
->loc
))
1564 if (node
->init
> node2
->init
)
1565 node2
->init
= node
->init
;
1569 /* Continue traversing the hash table. */
1573 /* Like variable_union, but only used when doing dataflow_set_union
1574 into an empty hashtab. To allow sharing, dst is initially shared
1575 with src (so all variables are "copied" from src to dst hashtab),
1576 so only unshare_variable for variables that need canonicalization
1580 variable_canonicalize (void **slot
, void *data
)
1583 dataflow_set
*set
= (dataflow_set
*) data
;
1586 src
= *(variable
*) slot
;
1588 /* If CUR_LOC of some variable part is not the first element of
1589 the location chain we are going to change it so we have to make
1590 a copy of the variable. */
1591 for (k
= 0; k
< src
->n_var_parts
; k
++)
1593 gcc_assert (!src
->var_part
[k
].loc_chain
== !src
->var_part
[k
].cur_loc
);
1594 if (src
->var_part
[k
].loc_chain
)
1596 gcc_assert (src
->var_part
[k
].cur_loc
);
1597 if (src
->var_part
[k
].cur_loc
!= src
->var_part
[k
].loc_chain
->loc
)
1601 if (k
< src
->n_var_parts
)
1602 unshare_variable (set
, src
, VAR_INIT_STATUS_UNKNOWN
);
1606 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1609 dataflow_set_union (dataflow_set
*dst
, dataflow_set
*src
)
1613 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1614 attrs_list_union (&dst
->regs
[i
], src
->regs
[i
]);
1616 if (dst
->vars
== empty_shared_hash
)
1618 shared_hash_destroy (dst
->vars
);
1619 dst
->vars
= shared_hash_copy (src
->vars
);
1620 htab_traverse (shared_hash_htab (src
->vars
), variable_canonicalize
, dst
);
1623 htab_traverse (shared_hash_htab (src
->vars
), variable_union
, dst
);
1626 /* Flag whether two dataflow sets being compared contain different data. */
1628 dataflow_set_different_value
;
1631 variable_part_different_p (variable_part
*vp1
, variable_part
*vp2
)
1633 location_chain lc1
, lc2
;
1635 for (lc1
= vp1
->loc_chain
; lc1
; lc1
= lc1
->next
)
1637 for (lc2
= vp2
->loc_chain
; lc2
; lc2
= lc2
->next
)
1639 if (REG_P (lc1
->loc
) && REG_P (lc2
->loc
))
1641 if (REGNO (lc1
->loc
) == REGNO (lc2
->loc
))
1644 if (rtx_equal_p (lc1
->loc
, lc2
->loc
))
1653 /* Return true if variables VAR1 and VAR2 are different.
1654 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1658 variable_different_p (variable var1
, variable var2
,
1659 bool compare_current_location
)
1666 if (var1
->n_var_parts
!= var2
->n_var_parts
)
1669 for (i
= 0; i
< var1
->n_var_parts
; i
++)
1671 if (var1
->var_part
[i
].offset
!= var2
->var_part
[i
].offset
)
1673 if (compare_current_location
)
1675 if (!((REG_P (var1
->var_part
[i
].cur_loc
)
1676 && REG_P (var2
->var_part
[i
].cur_loc
)
1677 && (REGNO (var1
->var_part
[i
].cur_loc
)
1678 == REGNO (var2
->var_part
[i
].cur_loc
)))
1679 || rtx_equal_p (var1
->var_part
[i
].cur_loc
,
1680 var2
->var_part
[i
].cur_loc
)))
1683 if (variable_part_different_p (&var1
->var_part
[i
], &var2
->var_part
[i
]))
1685 if (variable_part_different_p (&var2
->var_part
[i
], &var1
->var_part
[i
]))
1691 /* Compare variable *SLOT with the same variable in hash table DATA
1692 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1695 dataflow_set_different_1 (void **slot
, void *data
)
1697 htab_t htab
= (htab_t
) data
;
1698 variable var1
, var2
;
1700 var1
= *(variable
*) slot
;
1701 var2
= (variable
) htab_find_with_hash (htab
, var1
->decl
,
1702 VARIABLE_HASH_VAL (var1
->decl
));
1705 dataflow_set_different_value
= true;
1707 /* Stop traversing the hash table. */
1711 if (variable_different_p (var1
, var2
, false))
1713 dataflow_set_different_value
= true;
1715 /* Stop traversing the hash table. */
1719 /* Continue traversing the hash table. */
1723 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1726 dataflow_set_different (dataflow_set
*old_set
, dataflow_set
*new_set
)
1728 if (old_set
->vars
== new_set
->vars
)
1731 if (htab_elements (shared_hash_htab (old_set
->vars
))
1732 != htab_elements (shared_hash_htab (new_set
->vars
)))
1735 dataflow_set_different_value
= false;
1737 htab_traverse (shared_hash_htab (old_set
->vars
), dataflow_set_different_1
,
1738 shared_hash_htab (new_set
->vars
));
1739 /* No need to traverse the second hashtab, if both have the same number
1740 of elements and the second one had all entries found in the first one,
1741 then it can't have any extra entries. */
1742 return dataflow_set_different_value
;
1745 /* Free the contents of dataflow set SET. */
1748 dataflow_set_destroy (dataflow_set
*set
)
1752 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1753 attrs_list_clear (&set
->regs
[i
]);
1755 shared_hash_destroy (set
->vars
);
1759 /* Return true if RTL X contains a SYMBOL_REF. */
1762 contains_symbol_ref (rtx x
)
1771 code
= GET_CODE (x
);
1772 if (code
== SYMBOL_REF
)
1775 fmt
= GET_RTX_FORMAT (code
);
1776 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1780 if (contains_symbol_ref (XEXP (x
, i
)))
1783 else if (fmt
[i
] == 'E')
1786 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1787 if (contains_symbol_ref (XVECEXP (x
, i
, j
)))
1795 /* Shall EXPR be tracked? */
1798 track_expr_p (tree expr
)
1803 /* If EXPR is not a parameter or a variable do not track it. */
1804 if (TREE_CODE (expr
) != VAR_DECL
&& TREE_CODE (expr
) != PARM_DECL
)
1807 /* It also must have a name... */
1808 if (!DECL_NAME (expr
))
1811 /* ... and a RTL assigned to it. */
1812 decl_rtl
= DECL_RTL_IF_SET (expr
);
1816 /* If this expression is really a debug alias of some other declaration, we
1817 don't need to track this expression if the ultimate declaration is
1820 if (DECL_DEBUG_EXPR_IS_FROM (realdecl
) && DECL_DEBUG_EXPR (realdecl
))
1822 realdecl
= DECL_DEBUG_EXPR (realdecl
);
1823 /* ??? We don't yet know how to emit DW_OP_piece for variable
1824 that has been SRA'ed. */
1825 if (!DECL_P (realdecl
))
1829 /* Do not track EXPR if REALDECL it should be ignored for debugging
1831 if (DECL_IGNORED_P (realdecl
))
1834 /* Do not track global variables until we are able to emit correct location
1836 if (TREE_STATIC (realdecl
))
1839 /* When the EXPR is a DECL for alias of some variable (see example)
1840 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1841 DECL_RTL contains SYMBOL_REF.
1844 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1847 if (MEM_P (decl_rtl
)
1848 && contains_symbol_ref (XEXP (decl_rtl
, 0)))
1851 /* If RTX is a memory it should not be very large (because it would be
1852 an array or struct). */
1853 if (MEM_P (decl_rtl
))
1855 /* Do not track structures and arrays. */
1856 if (GET_MODE (decl_rtl
) == BLKmode
1857 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl
)))
1859 if (MEM_SIZE (decl_rtl
)
1860 && INTVAL (MEM_SIZE (decl_rtl
)) > MAX_VAR_PARTS
)
1867 /* Determine whether a given LOC refers to the same variable part as
1871 same_variable_part_p (rtx loc
, tree expr
, HOST_WIDE_INT offset
)
1874 HOST_WIDE_INT offset2
;
1876 if (! DECL_P (expr
))
1881 expr2
= REG_EXPR (loc
);
1882 offset2
= REG_OFFSET (loc
);
1884 else if (MEM_P (loc
))
1886 expr2
= MEM_EXPR (loc
);
1887 offset2
= INT_MEM_OFFSET (loc
);
1892 if (! expr2
|| ! DECL_P (expr2
))
1895 expr
= var_debug_decl (expr
);
1896 expr2
= var_debug_decl (expr2
);
1898 return (expr
== expr2
&& offset
== offset2
);
1901 /* LOC is a REG or MEM that we would like to track if possible.
1902 If EXPR is null, we don't know what expression LOC refers to,
1903 otherwise it refers to EXPR + OFFSET. STORE_REG_P is true if
1904 LOC is an lvalue register.
1906 Return true if EXPR is nonnull and if LOC, or some lowpart of it,
1907 is something we can track. When returning true, store the mode of
1908 the lowpart we can track in *MODE_OUT (if nonnull) and its offset
1909 from EXPR in *OFFSET_OUT (if nonnull). */
1912 track_loc_p (rtx loc
, tree expr
, HOST_WIDE_INT offset
, bool store_reg_p
,
1913 enum machine_mode
*mode_out
, HOST_WIDE_INT
*offset_out
)
1915 enum machine_mode mode
;
1917 if (expr
== NULL
|| !track_expr_p (expr
))
1920 /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
1921 whole subreg, but only the old inner part is really relevant. */
1922 mode
= GET_MODE (loc
);
1923 if (REG_P (loc
) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc
)))
1925 enum machine_mode pseudo_mode
;
1927 pseudo_mode
= PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc
));
1928 if (GET_MODE_SIZE (mode
) > GET_MODE_SIZE (pseudo_mode
))
1930 offset
+= byte_lowpart_offset (pseudo_mode
, mode
);
1935 /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
1936 Do the same if we are storing to a register and EXPR occupies
1937 the whole of register LOC; in that case, the whole of EXPR is
1938 being changed. We exclude complex modes from the second case
1939 because the real and imaginary parts are represented as separate
1940 pseudo registers, even if the whole complex value fits into one
1942 if ((GET_MODE_SIZE (mode
) > GET_MODE_SIZE (DECL_MODE (expr
))
1944 && !COMPLEX_MODE_P (DECL_MODE (expr
))
1945 && hard_regno_nregs
[REGNO (loc
)][DECL_MODE (expr
)] == 1))
1946 && offset
+ byte_lowpart_offset (DECL_MODE (expr
), mode
) == 0)
1948 mode
= DECL_MODE (expr
);
1952 if (offset
< 0 || offset
>= MAX_VAR_PARTS
)
1958 *offset_out
= offset
;
1962 /* Return the MODE lowpart of LOC, or null if LOC is not something we
1963 want to track. When returning nonnull, make sure that the attributes
1964 on the returned value are updated. */
1967 var_lowpart (enum machine_mode mode
, rtx loc
)
1969 unsigned int offset
, reg_offset
, regno
;
1971 if (!REG_P (loc
) && !MEM_P (loc
))
1974 if (GET_MODE (loc
) == mode
)
1977 offset
= byte_lowpart_offset (mode
, GET_MODE (loc
));
1980 return adjust_address_nv (loc
, mode
, offset
);
1982 reg_offset
= subreg_lowpart_offset (mode
, GET_MODE (loc
));
1983 regno
= REGNO (loc
) + subreg_regno_offset (REGNO (loc
), GET_MODE (loc
),
1985 return gen_rtx_REG_offset (loc
, mode
, regno
, offset
);
1988 /* Count uses (register and memory references) LOC which will be tracked.
1989 INSN is instruction which the LOC is part of. */
1992 count_uses (rtx
*loc
, void *insn
)
1994 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1998 gcc_assert (REGNO (*loc
) < FIRST_PSEUDO_REGISTER
);
2001 else if (MEM_P (*loc
)
2002 && track_loc_p (*loc
, MEM_EXPR (*loc
), INT_MEM_OFFSET (*loc
),
2011 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
2014 count_uses_1 (rtx
*x
, void *insn
)
2016 for_each_rtx (x
, count_uses
, insn
);
2019 /* Count stores (register and memory references) LOC which will be tracked.
2020 INSN is instruction which the LOC is part of. */
2023 count_stores (rtx loc
, const_rtx expr ATTRIBUTE_UNUSED
, void *insn
)
2025 count_uses (&loc
, insn
);
2028 /* Add uses (register and memory references) LOC which will be tracked
2029 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
2032 add_uses (rtx
*loc
, void *insn
)
2034 enum machine_mode mode
;
2038 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
2039 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2041 if (track_loc_p (*loc
, REG_EXPR (*loc
), REG_OFFSET (*loc
),
2042 false, &mode
, NULL
))
2045 mo
->u
.loc
= var_lowpart (mode
, *loc
);
2049 mo
->type
= MO_USE_NO_VAR
;
2052 mo
->insn
= (rtx
) insn
;
2054 else if (MEM_P (*loc
)
2055 && track_loc_p (*loc
, MEM_EXPR (*loc
), INT_MEM_OFFSET (*loc
),
2056 false, &mode
, NULL
))
2058 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
2059 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2062 mo
->u
.loc
= var_lowpart (mode
, *loc
);
2063 mo
->insn
= (rtx
) insn
;
2069 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
2072 add_uses_1 (rtx
*x
, void *insn
)
2074 for_each_rtx (x
, add_uses
, insn
);
2077 /* Add stores (register and memory references) LOC which will be tracked
2078 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
2079 INSN is instruction which the LOC is part of. */
2082 add_stores (rtx loc
, const_rtx expr
, void *insn
)
2084 enum machine_mode mode
;
2088 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
2089 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2091 if (GET_CODE (expr
) == CLOBBER
2092 || !track_loc_p (loc
, REG_EXPR (loc
), REG_OFFSET (loc
),
2095 mo
->type
= MO_CLOBBER
;
2102 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
2103 src
= var_lowpart (mode
, SET_SRC (expr
));
2104 loc
= var_lowpart (mode
, loc
);
2113 if (SET_SRC (expr
) != src
)
2114 expr
= gen_rtx_SET (VOIDmode
, loc
, src
);
2115 if (same_variable_part_p (src
, REG_EXPR (loc
), REG_OFFSET (loc
)))
2119 mo
->u
.loc
= CONST_CAST_RTX (expr
);
2122 mo
->insn
= (rtx
) insn
;
2124 else if (MEM_P (loc
)
2125 && track_loc_p (loc
, MEM_EXPR (loc
), INT_MEM_OFFSET (loc
),
2126 false, &mode
, NULL
))
2128 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
2129 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2131 if (GET_CODE (expr
) == CLOBBER
)
2133 mo
->type
= MO_CLOBBER
;
2134 mo
->u
.loc
= var_lowpart (mode
, loc
);
2140 if (GET_CODE (expr
) == SET
&& SET_DEST (expr
) == loc
)
2141 src
= var_lowpart (mode
, SET_SRC (expr
));
2142 loc
= var_lowpart (mode
, loc
);
2151 if (SET_SRC (expr
) != src
)
2152 expr
= gen_rtx_SET (VOIDmode
, loc
, src
);
2153 if (same_variable_part_p (SET_SRC (expr
),
2155 INT_MEM_OFFSET (loc
)))
2159 mo
->u
.loc
= CONST_CAST_RTX (expr
);
2162 mo
->insn
= (rtx
) insn
;
2166 static enum var_init_status
2167 find_src_status (dataflow_set
*in
, rtx src
)
2169 tree decl
= NULL_TREE
;
2170 enum var_init_status status
= VAR_INIT_STATUS_UNINITIALIZED
;
2172 if (! flag_var_tracking_uninit
)
2173 status
= VAR_INIT_STATUS_INITIALIZED
;
2175 if (src
&& REG_P (src
))
2176 decl
= var_debug_decl (REG_EXPR (src
));
2177 else if (src
&& MEM_P (src
))
2178 decl
= var_debug_decl (MEM_EXPR (src
));
2181 status
= get_init_value (in
, src
, decl
);
2186 /* SRC is the source of an assignment. Use SET to try to find what
2187 was ultimately assigned to SRC. Return that value if known,
2188 otherwise return SRC itself. */
2191 find_src_set_src (dataflow_set
*set
, rtx src
)
2193 tree decl
= NULL_TREE
; /* The variable being copied around. */
2194 rtx set_src
= NULL_RTX
; /* The value for "decl" stored in "src". */
2196 location_chain nextp
;
2200 if (src
&& REG_P (src
))
2201 decl
= var_debug_decl (REG_EXPR (src
));
2202 else if (src
&& MEM_P (src
))
2203 decl
= var_debug_decl (MEM_EXPR (src
));
2207 var
= shared_hash_find (set
->vars
, decl
);
2211 for (i
= 0; i
< var
->n_var_parts
&& !found
; i
++)
2212 for (nextp
= var
->var_part
[i
].loc_chain
; nextp
&& !found
;
2213 nextp
= nextp
->next
)
2214 if (rtx_equal_p (nextp
->loc
, src
))
2216 set_src
= nextp
->set_src
;
2226 /* Compute the changes of variable locations in the basic block BB. */
2229 compute_bb_dataflow (basic_block bb
)
2233 dataflow_set old_out
;
2234 dataflow_set
*in
= &VTI (bb
)->in
;
2235 dataflow_set
*out
= &VTI (bb
)->out
;
2237 dataflow_set_init (&old_out
);
2238 dataflow_set_copy (&old_out
, out
);
2239 dataflow_set_copy (out
, in
);
2241 n
= VTI (bb
)->n_mos
;
2242 for (i
= 0; i
< n
; i
++)
2244 switch (VTI (bb
)->mos
[i
].type
)
2247 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
2248 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
2249 var_regno_delete (out
, r
);
2254 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2257 var_reg_set (out
, loc
, VAR_INIT_STATUS_UNINITIALIZED
, NULL
);
2258 else if (MEM_P (loc
))
2259 var_mem_set (out
, loc
, VAR_INIT_STATUS_UNINITIALIZED
, NULL
);
2265 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2268 if (GET_CODE (loc
) == SET
)
2270 set_src
= SET_SRC (loc
);
2271 loc
= SET_DEST (loc
);
2275 var_reg_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2277 else if (MEM_P (loc
))
2278 var_mem_delete_and_set (out
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
2285 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2286 enum var_init_status src_status
;
2289 if (GET_CODE (loc
) == SET
)
2291 set_src
= SET_SRC (loc
);
2292 loc
= SET_DEST (loc
);
2295 if (! flag_var_tracking_uninit
)
2296 src_status
= VAR_INIT_STATUS_INITIALIZED
;
2299 src_status
= find_src_status (in
, set_src
);
2301 if (src_status
== VAR_INIT_STATUS_UNKNOWN
)
2302 src_status
= find_src_status (out
, set_src
);
2305 set_src
= find_src_set_src (in
, set_src
);
2308 var_reg_delete_and_set (out
, loc
, false, src_status
, set_src
);
2309 else if (MEM_P (loc
))
2310 var_mem_delete_and_set (out
, loc
, false, src_status
, set_src
);
2316 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2319 var_reg_delete (out
, loc
, false);
2320 else if (MEM_P (loc
))
2321 var_mem_delete (out
, loc
, false);
2327 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2330 var_reg_delete (out
, loc
, true);
2331 else if (MEM_P (loc
))
2332 var_mem_delete (out
, loc
, true);
2337 out
->stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
2342 changed
= dataflow_set_different (&old_out
, out
);
2343 dataflow_set_destroy (&old_out
);
2347 /* Find the locations of variables in the whole function. */
2350 vt_find_locations (void)
2352 fibheap_t worklist
, pending
, fibheap_swap
;
2353 sbitmap visited
, in_worklist
, in_pending
, sbitmap_swap
;
2360 /* Compute reverse completion order of depth first search of the CFG
2361 so that the data-flow runs faster. */
2362 rc_order
= XNEWVEC (int, n_basic_blocks
- NUM_FIXED_BLOCKS
);
2363 bb_order
= XNEWVEC (int, last_basic_block
);
2364 pre_and_rev_post_order_compute (NULL
, rc_order
, false);
2365 for (i
= 0; i
< n_basic_blocks
- NUM_FIXED_BLOCKS
; i
++)
2366 bb_order
[rc_order
[i
]] = i
;
2369 worklist
= fibheap_new ();
2370 pending
= fibheap_new ();
2371 visited
= sbitmap_alloc (last_basic_block
);
2372 in_worklist
= sbitmap_alloc (last_basic_block
);
2373 in_pending
= sbitmap_alloc (last_basic_block
);
2374 sbitmap_zero (in_worklist
);
2377 fibheap_insert (pending
, bb_order
[bb
->index
], bb
);
2378 sbitmap_ones (in_pending
);
2380 while (!fibheap_empty (pending
))
2382 fibheap_swap
= pending
;
2384 worklist
= fibheap_swap
;
2385 sbitmap_swap
= in_pending
;
2386 in_pending
= in_worklist
;
2387 in_worklist
= sbitmap_swap
;
2389 sbitmap_zero (visited
);
2391 while (!fibheap_empty (worklist
))
2393 bb
= (basic_block
) fibheap_extract_min (worklist
);
2394 RESET_BIT (in_worklist
, bb
->index
);
2395 if (!TEST_BIT (visited
, bb
->index
))
2400 SET_BIT (visited
, bb
->index
);
2402 /* Calculate the IN set as union of predecessor OUT sets. */
2403 dataflow_set_clear (&VTI (bb
)->in
);
2404 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
2406 dataflow_set_union (&VTI (bb
)->in
, &VTI (e
->src
)->out
);
2409 changed
= compute_bb_dataflow (bb
);
2412 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
2414 if (e
->dest
== EXIT_BLOCK_PTR
)
2420 if (TEST_BIT (visited
, e
->dest
->index
))
2422 if (!TEST_BIT (in_pending
, e
->dest
->index
))
2424 /* Send E->DEST to next round. */
2425 SET_BIT (in_pending
, e
->dest
->index
);
2426 fibheap_insert (pending
,
2427 bb_order
[e
->dest
->index
],
2431 else if (!TEST_BIT (in_worklist
, e
->dest
->index
))
2433 /* Add E->DEST to current round. */
2434 SET_BIT (in_worklist
, e
->dest
->index
);
2435 fibheap_insert (worklist
, bb_order
[e
->dest
->index
],
2445 fibheap_delete (worklist
);
2446 fibheap_delete (pending
);
2447 sbitmap_free (visited
);
2448 sbitmap_free (in_worklist
);
2449 sbitmap_free (in_pending
);
2452 /* Print the content of the LIST to dump file. */
2455 dump_attrs_list (attrs list
)
2457 for (; list
; list
= list
->next
)
2459 print_mem_expr (dump_file
, list
->decl
);
2460 fprintf (dump_file
, "+" HOST_WIDE_INT_PRINT_DEC
, list
->offset
);
2462 fprintf (dump_file
, "\n");
2465 /* Print the information about variable *SLOT to dump file. */
2468 dump_variable (void **slot
, void *data ATTRIBUTE_UNUSED
)
2470 variable var
= *(variable
*) slot
;
2472 location_chain node
;
2474 fprintf (dump_file
, " name: %s",
2475 IDENTIFIER_POINTER (DECL_NAME (var
->decl
)));
2476 if (dump_flags
& TDF_UID
)
2477 fprintf (dump_file
, " D.%u\n", DECL_UID (var
->decl
));
2479 fprintf (dump_file
, "\n");
2481 for (i
= 0; i
< var
->n_var_parts
; i
++)
2483 fprintf (dump_file
, " offset %ld\n",
2484 (long) var
->var_part
[i
].offset
);
2485 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
2487 fprintf (dump_file
, " ");
2488 if (node
->init
== VAR_INIT_STATUS_UNINITIALIZED
)
2489 fprintf (dump_file
, "[uninit]");
2490 print_rtl_single (dump_file
, node
->loc
);
2494 /* Continue traversing the hash table. */
2498 /* Print the information about variables from hash table VARS to dump file. */
2501 dump_vars (htab_t vars
)
2503 if (htab_elements (vars
) > 0)
2505 fprintf (dump_file
, "Variables:\n");
2506 htab_traverse (vars
, dump_variable
, NULL
);
2510 /* Print the dataflow set SET to dump file. */
2513 dump_dataflow_set (dataflow_set
*set
)
2517 fprintf (dump_file
, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC
"\n",
2519 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2523 fprintf (dump_file
, "Reg %d:", i
);
2524 dump_attrs_list (set
->regs
[i
]);
2527 dump_vars (shared_hash_htab (set
->vars
));
2528 fprintf (dump_file
, "\n");
2531 /* Print the IN and OUT sets for each basic block to dump file. */
2534 dump_dataflow_sets (void)
2540 fprintf (dump_file
, "\nBasic block %d:\n", bb
->index
);
2541 fprintf (dump_file
, "IN:\n");
2542 dump_dataflow_set (&VTI (bb
)->in
);
2543 fprintf (dump_file
, "OUT:\n");
2544 dump_dataflow_set (&VTI (bb
)->out
);
2548 /* Add variable VAR to the hash table of changed variables and
2549 if it has no locations delete it from SET's hash table. */
2552 variable_was_changed (variable var
, dataflow_set
*set
)
2554 hashval_t hash
= VARIABLE_HASH_VAL (var
->decl
);
2560 slot
= (variable
*) htab_find_slot_with_hash (changed_variables
,
2561 var
->decl
, hash
, INSERT
);
2563 if (set
&& var
->n_var_parts
== 0)
2567 empty_var
= (variable
) pool_alloc (var_pool
);
2568 empty_var
->decl
= var
->decl
;
2569 empty_var
->refcount
= 1;
2570 empty_var
->n_var_parts
= 0;
2583 if (var
->n_var_parts
== 0)
2588 slot
= shared_hash_find_slot_noinsert (set
->vars
, var
->decl
);
2591 if (shared_hash_shared (set
->vars
))
2592 slot
= shared_hash_find_slot_unshare (&set
->vars
, var
->decl
,
2594 htab_clear_slot (shared_hash_htab (set
->vars
), slot
);
2600 /* Look for the index in VAR->var_part corresponding to OFFSET.
2601 Return -1 if not found. If INSERTION_POINT is non-NULL, the
2602 referenced int will be set to the index that the part has or should
2603 have, if it should be inserted. */
2606 find_variable_location_part (variable var
, HOST_WIDE_INT offset
,
2607 int *insertion_point
)
2611 /* Find the location part. */
2613 high
= var
->n_var_parts
;
2616 pos
= (low
+ high
) / 2;
2617 if (var
->var_part
[pos
].offset
< offset
)
2624 if (insertion_point
)
2625 *insertion_point
= pos
;
2627 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
2633 /* Set the part of variable's location in the dataflow set SET. The variable
2634 part is specified by variable's declaration DECL and offset OFFSET and the
2635 part's location by LOC. */
2638 set_variable_part (dataflow_set
*set
, rtx loc
, tree decl
, HOST_WIDE_INT offset
,
2639 enum var_init_status initialized
, rtx set_src
)
2642 location_chain node
, next
;
2643 location_chain
*nextp
;
2645 void **slot
= shared_hash_find_slot (set
->vars
, decl
);
2647 if (! flag_var_tracking_uninit
)
2648 initialized
= VAR_INIT_STATUS_INITIALIZED
;
2650 if (!slot
|| !*slot
)
2653 slot
= shared_hash_find_slot_unshare (&set
->vars
, decl
, INSERT
);
2654 /* Create new variable information. */
2655 var
= (variable
) pool_alloc (var_pool
);
2658 var
->n_var_parts
= 1;
2659 var
->var_part
[0].offset
= offset
;
2660 var
->var_part
[0].loc_chain
= NULL
;
2661 var
->var_part
[0].cur_loc
= NULL
;
2669 var
= (variable
) *slot
;
2671 pos
= find_variable_location_part (var
, offset
, &inspos
);
2675 node
= var
->var_part
[pos
].loc_chain
;
2678 && ((REG_P (node
->loc
) && REG_P (loc
)
2679 && REGNO (node
->loc
) == REGNO (loc
))
2680 || rtx_equal_p (node
->loc
, loc
)))
2682 /* LOC is in the beginning of the chain so we have nothing
2684 if (node
->init
< initialized
)
2685 node
->init
= initialized
;
2686 if (set_src
!= NULL
)
2687 node
->set_src
= set_src
;
2693 /* We have to make a copy of a shared variable. */
2694 if (var
->refcount
> 1 || shared_hash_shared (set
->vars
))
2695 var
= unshare_variable (set
, var
, initialized
);
2700 /* We have not found the location part, new one will be created. */
2702 /* We have to make a copy of the shared variable. */
2703 if (var
->refcount
> 1 || shared_hash_shared (set
->vars
))
2704 var
= unshare_variable (set
, var
, initialized
);
2706 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2707 thus there are at most MAX_VAR_PARTS different offsets. */
2708 gcc_assert (var
->n_var_parts
< MAX_VAR_PARTS
);
2710 /* We have to move the elements of array starting at index
2711 inspos to the next position. */
2712 for (pos
= var
->n_var_parts
; pos
> inspos
; pos
--)
2713 var
->var_part
[pos
] = var
->var_part
[pos
- 1];
2716 var
->var_part
[pos
].offset
= offset
;
2717 var
->var_part
[pos
].loc_chain
= NULL
;
2718 var
->var_part
[pos
].cur_loc
= NULL
;
2722 /* Delete the location from the list. */
2723 nextp
= &var
->var_part
[pos
].loc_chain
;
2724 for (node
= var
->var_part
[pos
].loc_chain
; node
; node
= next
)
2727 if ((REG_P (node
->loc
) && REG_P (loc
)
2728 && REGNO (node
->loc
) == REGNO (loc
))
2729 || rtx_equal_p (node
->loc
, loc
))
2731 /* Save these values, to assign to the new node, before
2732 deleting this one. */
2733 if (node
->init
> initialized
)
2734 initialized
= node
->init
;
2735 if (node
->set_src
!= NULL
&& set_src
== NULL
)
2736 set_src
= node
->set_src
;
2737 pool_free (loc_chain_pool
, node
);
2742 nextp
= &node
->next
;
2745 /* Add the location to the beginning. */
2746 node
= (location_chain
) pool_alloc (loc_chain_pool
);
2748 node
->init
= initialized
;
2749 node
->set_src
= set_src
;
2750 node
->next
= var
->var_part
[pos
].loc_chain
;
2751 var
->var_part
[pos
].loc_chain
= node
;
2753 /* If no location was emitted do so. */
2754 if (var
->var_part
[pos
].cur_loc
== NULL
)
2756 var
->var_part
[pos
].cur_loc
= loc
;
2757 variable_was_changed (var
, set
);
2761 /* Remove all recorded register locations for the given variable part
2762 from dataflow set SET, except for those that are identical to loc.
2763 The variable part is specified by variable's declaration DECL and
2767 clobber_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2768 HOST_WIDE_INT offset
, rtx set_src
)
2772 if (! decl
|| ! DECL_P (decl
))
2775 var
= shared_hash_find (set
->vars
, decl
);
2778 int pos
= find_variable_location_part (var
, offset
, NULL
);
2782 location_chain node
, next
;
2784 /* Remove the register locations from the dataflow set. */
2785 next
= var
->var_part
[pos
].loc_chain
;
2786 for (node
= next
; node
; node
= next
)
2789 if (node
->loc
!= loc
2790 && (!flag_var_tracking_uninit
2793 || !rtx_equal_p (set_src
, node
->set_src
)))
2795 if (REG_P (node
->loc
))
2800 /* Remove the variable part from the register's
2801 list, but preserve any other variable parts
2802 that might be regarded as live in that same
2804 anextp
= &set
->regs
[REGNO (node
->loc
)];
2805 for (anode
= *anextp
; anode
; anode
= anext
)
2807 anext
= anode
->next
;
2808 if (anode
->decl
== decl
2809 && anode
->offset
== offset
)
2811 pool_free (attrs_pool
, anode
);
2815 anextp
= &anode
->next
;
2819 delete_variable_part (set
, node
->loc
, decl
, offset
);
2826 /* Delete the part of variable's location from dataflow set SET. The variable
2827 part is specified by variable's declaration DECL and offset OFFSET and the
2828 part's location by LOC. */
2831 delete_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2832 HOST_WIDE_INT offset
)
2834 variable var
= shared_hash_find (set
->vars
, decl
);;
2837 int pos
= find_variable_location_part (var
, offset
, NULL
);
2841 location_chain node
, next
;
2842 location_chain
*nextp
;
2845 if (var
->refcount
> 1 || shared_hash_shared (set
->vars
))
2847 /* If the variable contains the location part we have to
2848 make a copy of the variable. */
2849 for (node
= var
->var_part
[pos
].loc_chain
; node
;
2852 if ((REG_P (node
->loc
) && REG_P (loc
)
2853 && REGNO (node
->loc
) == REGNO (loc
))
2854 || rtx_equal_p (node
->loc
, loc
))
2856 var
= unshare_variable (set
, var
,
2857 VAR_INIT_STATUS_UNKNOWN
);
2863 /* Delete the location part. */
2864 nextp
= &var
->var_part
[pos
].loc_chain
;
2865 for (node
= *nextp
; node
; node
= next
)
2868 if ((REG_P (node
->loc
) && REG_P (loc
)
2869 && REGNO (node
->loc
) == REGNO (loc
))
2870 || rtx_equal_p (node
->loc
, loc
))
2872 pool_free (loc_chain_pool
, node
);
2877 nextp
= &node
->next
;
2880 /* If we have deleted the location which was last emitted
2881 we have to emit new location so add the variable to set
2882 of changed variables. */
2883 if (var
->var_part
[pos
].cur_loc
2885 && REG_P (var
->var_part
[pos
].cur_loc
)
2886 && REGNO (loc
) == REGNO (var
->var_part
[pos
].cur_loc
))
2887 || rtx_equal_p (loc
, var
->var_part
[pos
].cur_loc
)))
2890 if (var
->var_part
[pos
].loc_chain
)
2891 var
->var_part
[pos
].cur_loc
= var
->var_part
[pos
].loc_chain
->loc
;
2896 if (var
->var_part
[pos
].loc_chain
== NULL
)
2899 while (pos
< var
->n_var_parts
)
2901 var
->var_part
[pos
] = var
->var_part
[pos
+ 1];
2906 variable_was_changed (var
, set
);
2911 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2912 additional parameters: WHERE specifies whether the note shall be emitted
2913 before of after instruction INSN. */
2916 emit_note_insn_var_location (void **varp
, void *data
)
2918 variable var
= *(variable
*) varp
;
2919 rtx insn
= ((emit_note_data
*)data
)->insn
;
2920 enum emit_note_where where
= ((emit_note_data
*)data
)->where
;
2922 int i
, j
, n_var_parts
;
2924 enum var_init_status initialized
= VAR_INIT_STATUS_UNINITIALIZED
;
2925 HOST_WIDE_INT last_limit
;
2926 tree type_size_unit
;
2927 HOST_WIDE_INT offsets
[MAX_VAR_PARTS
];
2928 rtx loc
[MAX_VAR_PARTS
];
2930 gcc_assert (var
->decl
);
2935 for (i
= 0; i
< var
->n_var_parts
; i
++)
2937 enum machine_mode mode
, wider_mode
;
2939 if (last_limit
< var
->var_part
[i
].offset
)
2944 else if (last_limit
> var
->var_part
[i
].offset
)
2946 offsets
[n_var_parts
] = var
->var_part
[i
].offset
;
2947 loc
[n_var_parts
] = var
->var_part
[i
].loc_chain
->loc
;
2948 mode
= GET_MODE (loc
[n_var_parts
]);
2949 initialized
= var
->var_part
[i
].loc_chain
->init
;
2950 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2952 /* Attempt to merge adjacent registers or memory. */
2953 wider_mode
= GET_MODE_WIDER_MODE (mode
);
2954 for (j
= i
+ 1; j
< var
->n_var_parts
; j
++)
2955 if (last_limit
<= var
->var_part
[j
].offset
)
2957 if (j
< var
->n_var_parts
2958 && wider_mode
!= VOIDmode
2959 && GET_CODE (loc
[n_var_parts
])
2960 == GET_CODE (var
->var_part
[j
].loc_chain
->loc
)
2961 && mode
== GET_MODE (var
->var_part
[j
].loc_chain
->loc
)
2962 && last_limit
== var
->var_part
[j
].offset
)
2965 rtx loc2
= var
->var_part
[j
].loc_chain
->loc
;
2967 if (REG_P (loc
[n_var_parts
])
2968 && hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
] * 2
2969 == hard_regno_nregs
[REGNO (loc
[n_var_parts
])][wider_mode
]
2970 && end_hard_regno (mode
, REGNO (loc
[n_var_parts
]))
2973 if (! WORDS_BIG_ENDIAN
&& ! BYTES_BIG_ENDIAN
)
2974 new_loc
= simplify_subreg (wider_mode
, loc
[n_var_parts
],
2976 else if (WORDS_BIG_ENDIAN
&& BYTES_BIG_ENDIAN
)
2977 new_loc
= simplify_subreg (wider_mode
, loc2
, mode
, 0);
2980 if (!REG_P (new_loc
)
2981 || REGNO (new_loc
) != REGNO (loc
[n_var_parts
]))
2984 REG_ATTRS (new_loc
) = REG_ATTRS (loc
[n_var_parts
]);
2987 else if (MEM_P (loc
[n_var_parts
])
2988 && GET_CODE (XEXP (loc2
, 0)) == PLUS
2989 && REG_P (XEXP (XEXP (loc2
, 0), 0))
2990 && CONST_INT_P (XEXP (XEXP (loc2
, 0), 1)))
2992 if ((REG_P (XEXP (loc
[n_var_parts
], 0))
2993 && rtx_equal_p (XEXP (loc
[n_var_parts
], 0),
2994 XEXP (XEXP (loc2
, 0), 0))
2995 && INTVAL (XEXP (XEXP (loc2
, 0), 1))
2996 == GET_MODE_SIZE (mode
))
2997 || (GET_CODE (XEXP (loc
[n_var_parts
], 0)) == PLUS
2998 && CONST_INT_P (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2999 && rtx_equal_p (XEXP (XEXP (loc
[n_var_parts
], 0), 0),
3000 XEXP (XEXP (loc2
, 0), 0))
3001 && INTVAL (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
3002 + GET_MODE_SIZE (mode
)
3003 == INTVAL (XEXP (XEXP (loc2
, 0), 1))))
3004 new_loc
= adjust_address_nv (loc
[n_var_parts
],
3010 loc
[n_var_parts
] = new_loc
;
3012 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
3018 type_size_unit
= TYPE_SIZE_UNIT (TREE_TYPE (var
->decl
));
3019 if ((unsigned HOST_WIDE_INT
) last_limit
< TREE_INT_CST_LOW (type_size_unit
))
3022 if (where
== EMIT_NOTE_AFTER_INSN
)
3023 note
= emit_note_after (NOTE_INSN_VAR_LOCATION
, insn
);
3025 note
= emit_note_before (NOTE_INSN_VAR_LOCATION
, insn
);
3027 if (! flag_var_tracking_uninit
)
3028 initialized
= VAR_INIT_STATUS_INITIALIZED
;
3032 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
3033 NULL_RTX
, (int) initialized
);
3035 else if (n_var_parts
== 1)
3038 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[0], GEN_INT (offsets
[0]));
3040 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
3044 else if (n_var_parts
)
3048 for (i
= 0; i
< n_var_parts
; i
++)
3050 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[i
], GEN_INT (offsets
[i
]));
3052 parallel
= gen_rtx_PARALLEL (VOIDmode
,
3053 gen_rtvec_v (n_var_parts
, loc
));
3054 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
3059 htab_clear_slot (changed_variables
, varp
);
3061 /* Continue traversing the hash table. */
3065 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
3066 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
3067 shall be emitted before of after instruction INSN. */
3070 emit_notes_for_changes (rtx insn
, enum emit_note_where where
)
3072 emit_note_data data
;
3076 htab_traverse (changed_variables
, emit_note_insn_var_location
, &data
);
3079 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
3080 same variable in hash table DATA or is not there at all. */
3083 emit_notes_for_differences_1 (void **slot
, void *data
)
3085 htab_t new_vars
= (htab_t
) data
;
3086 variable old_var
, new_var
;
3088 old_var
= *(variable
*) slot
;
3089 new_var
= (variable
) htab_find_with_hash (new_vars
, old_var
->decl
,
3090 VARIABLE_HASH_VAL (old_var
->decl
));
3094 /* Variable has disappeared. */
3097 empty_var
= (variable
) pool_alloc (var_pool
);
3098 empty_var
->decl
= old_var
->decl
;
3099 empty_var
->refcount
= 0;
3100 empty_var
->n_var_parts
= 0;
3101 variable_was_changed (empty_var
, NULL
);
3103 else if (variable_different_p (old_var
, new_var
, true))
3105 variable_was_changed (new_var
, NULL
);
3108 /* Continue traversing the hash table. */
3112 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
3116 emit_notes_for_differences_2 (void **slot
, void *data
)
3118 htab_t old_vars
= (htab_t
) data
;
3119 variable old_var
, new_var
;
3121 new_var
= *(variable
*) slot
;
3122 old_var
= (variable
) htab_find_with_hash (old_vars
, new_var
->decl
,
3123 VARIABLE_HASH_VAL (new_var
->decl
));
3126 /* Variable has appeared. */
3127 variable_was_changed (new_var
, NULL
);
3130 /* Continue traversing the hash table. */
3134 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
3138 emit_notes_for_differences (rtx insn
, dataflow_set
*old_set
,
3139 dataflow_set
*new_set
)
3141 htab_traverse (shared_hash_htab (old_set
->vars
),
3142 emit_notes_for_differences_1
,
3143 shared_hash_htab (new_set
->vars
));
3144 htab_traverse (shared_hash_htab (new_set
->vars
),
3145 emit_notes_for_differences_2
,
3146 shared_hash_htab (old_set
->vars
));
3147 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
3150 /* Emit the notes for changes of location parts in the basic block BB. */
3153 emit_notes_in_bb (basic_block bb
)
3158 dataflow_set_init (&set
);
3159 dataflow_set_copy (&set
, &VTI (bb
)->in
);
3161 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
3163 rtx insn
= VTI (bb
)->mos
[i
].insn
;
3165 switch (VTI (bb
)->mos
[i
].type
)
3171 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
3172 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
3174 var_regno_delete (&set
, r
);
3176 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3182 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3185 var_reg_set (&set
, loc
, VAR_INIT_STATUS_UNINITIALIZED
, NULL
);
3187 var_mem_set (&set
, loc
, VAR_INIT_STATUS_UNINITIALIZED
, NULL
);
3189 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3195 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3198 if (GET_CODE (loc
) == SET
)
3200 set_src
= SET_SRC (loc
);
3201 loc
= SET_DEST (loc
);
3205 var_reg_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
3208 var_mem_delete_and_set (&set
, loc
, true, VAR_INIT_STATUS_INITIALIZED
,
3211 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3217 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3218 enum var_init_status src_status
;
3221 if (GET_CODE (loc
) == SET
)
3223 set_src
= SET_SRC (loc
);
3224 loc
= SET_DEST (loc
);
3227 src_status
= find_src_status (&set
, set_src
);
3228 set_src
= find_src_set_src (&set
, set_src
);
3231 var_reg_delete_and_set (&set
, loc
, false, src_status
, set_src
);
3233 var_mem_delete_and_set (&set
, loc
, false, src_status
, set_src
);
3235 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3241 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3244 var_reg_delete (&set
, loc
, false);
3246 var_mem_delete (&set
, loc
, false);
3248 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
3254 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
3257 var_reg_delete (&set
, loc
, true);
3259 var_mem_delete (&set
, loc
, true);
3261 emit_notes_for_changes (NEXT_INSN (insn
), EMIT_NOTE_BEFORE_INSN
);
3266 set
.stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
3270 dataflow_set_destroy (&set
);
3273 /* Emit notes for the whole function. */
3276 vt_emit_notes (void)
3279 dataflow_set
*last_out
;
3282 gcc_assert (!htab_elements (changed_variables
));
3284 /* Enable emitting notes by functions (mainly by set_variable_part and
3285 delete_variable_part). */
3288 dataflow_set_init (&empty
);
3293 /* Emit the notes for changes of variable locations between two
3294 subsequent basic blocks. */
3295 emit_notes_for_differences (BB_HEAD (bb
), last_out
, &VTI (bb
)->in
);
3297 /* Emit the notes for the changes in the basic block itself. */
3298 emit_notes_in_bb (bb
);
3300 last_out
= &VTI (bb
)->out
;
3302 dataflow_set_destroy (&empty
);
3306 /* If there is a declaration and offset associated with register/memory RTL
3307 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
3310 vt_get_decl_and_offset (rtx rtl
, tree
*declp
, HOST_WIDE_INT
*offsetp
)
3314 if (REG_ATTRS (rtl
))
3316 *declp
= REG_EXPR (rtl
);
3317 *offsetp
= REG_OFFSET (rtl
);
3321 else if (MEM_P (rtl
))
3323 if (MEM_ATTRS (rtl
))
3325 *declp
= MEM_EXPR (rtl
);
3326 *offsetp
= INT_MEM_OFFSET (rtl
);
3333 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
3336 vt_add_function_parameters (void)
3340 for (parm
= DECL_ARGUMENTS (current_function_decl
);
3341 parm
; parm
= TREE_CHAIN (parm
))
3343 rtx decl_rtl
= DECL_RTL_IF_SET (parm
);
3344 rtx incoming
= DECL_INCOMING_RTL (parm
);
3346 enum machine_mode mode
;
3347 HOST_WIDE_INT offset
;
3350 if (TREE_CODE (parm
) != PARM_DECL
)
3353 if (!DECL_NAME (parm
))
3356 if (!decl_rtl
|| !incoming
)
3359 if (GET_MODE (decl_rtl
) == BLKmode
|| GET_MODE (incoming
) == BLKmode
)
3362 if (!vt_get_decl_and_offset (incoming
, &decl
, &offset
))
3364 if (!vt_get_decl_and_offset (decl_rtl
, &decl
, &offset
))
3366 offset
+= byte_lowpart_offset (GET_MODE (incoming
),
3367 GET_MODE (decl_rtl
));
3375 /* Assume that DECL_RTL was a pseudo that got spilled to
3376 memory. The spill slot sharing code will force the
3377 memory to reference spill_slot_decl (%sfp), so we don't
3378 match above. That's ok, the pseudo must have referenced
3379 the entire parameter, so just reset OFFSET. */
3380 gcc_assert (decl
== get_spill_slot_decl (false));
3384 if (!track_loc_p (incoming
, parm
, offset
, false, &mode
, &offset
))
3387 out
= &VTI (ENTRY_BLOCK_PTR
)->out
;
3389 if (REG_P (incoming
))
3391 incoming
= var_lowpart (mode
, incoming
);
3392 gcc_assert (REGNO (incoming
) < FIRST_PSEUDO_REGISTER
);
3393 attrs_list_insert (&out
->regs
[REGNO (incoming
)],
3394 parm
, offset
, incoming
);
3395 set_variable_part (out
, incoming
, parm
, offset
, VAR_INIT_STATUS_INITIALIZED
,
3398 else if (MEM_P (incoming
))
3400 incoming
= var_lowpart (mode
, incoming
);
3401 set_variable_part (out
, incoming
, parm
, offset
,
3402 VAR_INIT_STATUS_INITIALIZED
, NULL
);
3407 /* Allocate and initialize the data structures for variable tracking
3408 and parse the RTL to get the micro operations. */
3411 vt_initialize (void)
3415 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def
));
3420 HOST_WIDE_INT pre
, post
= 0;
3422 /* Count the number of micro operations. */
3423 VTI (bb
)->n_mos
= 0;
3424 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
3425 insn
= NEXT_INSN (insn
))
3429 if (!frame_pointer_needed
)
3431 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3437 note_uses (&PATTERN (insn
), count_uses_1
, insn
);
3438 note_stores (PATTERN (insn
), count_stores
, insn
);
3444 /* Add the micro-operations to the array. */
3445 VTI (bb
)->mos
= XNEWVEC (micro_operation
, VTI (bb
)->n_mos
);
3446 VTI (bb
)->n_mos
= 0;
3447 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
3448 insn
= NEXT_INSN (insn
))
3454 if (!frame_pointer_needed
)
3456 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
3459 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3461 mo
->type
= MO_ADJUST
;
3467 n1
= VTI (bb
)->n_mos
;
3468 note_uses (&PATTERN (insn
), add_uses_1
, insn
);
3469 n2
= VTI (bb
)->n_mos
- 1;
3471 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
3474 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_USE
)
3476 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_USE_NO_VAR
)
3482 sw
= VTI (bb
)->mos
[n1
];
3483 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
3484 VTI (bb
)->mos
[n2
] = sw
;
3490 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3496 n1
= VTI (bb
)->n_mos
;
3497 /* This will record NEXT_INSN (insn), such that we can
3498 insert notes before it without worrying about any
3499 notes that MO_USEs might emit after the insn. */
3500 note_stores (PATTERN (insn
), add_stores
, insn
);
3501 n2
= VTI (bb
)->n_mos
- 1;
3503 /* Order the MO_CLOBBERs to be before MO_SETs. */
3506 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_CLOBBER
)
3508 while (n1
< n2
&& (VTI (bb
)->mos
[n2
].type
== MO_SET
3509 || VTI (bb
)->mos
[n2
].type
== MO_COPY
))
3515 sw
= VTI (bb
)->mos
[n1
];
3516 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
3517 VTI (bb
)->mos
[n2
] = sw
;
3521 if (!frame_pointer_needed
&& post
)
3523 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
3525 mo
->type
= MO_ADJUST
;
3526 mo
->u
.adjust
= post
;
3533 attrs_pool
= create_alloc_pool ("attrs_def pool",
3534 sizeof (struct attrs_def
), 1024);
3535 var_pool
= create_alloc_pool ("variable_def pool",
3536 sizeof (struct variable_def
), 64);
3537 loc_chain_pool
= create_alloc_pool ("location_chain_def pool",
3538 sizeof (struct location_chain_def
),
3540 shared_hash_pool
= create_alloc_pool ("shared_hash_def pool",
3541 sizeof (struct shared_hash_def
), 256);
3542 empty_shared_hash
= (shared_hash
) pool_alloc (shared_hash_pool
);
3543 empty_shared_hash
->refcount
= 1;
3544 empty_shared_hash
->htab
3545 = htab_create (1, variable_htab_hash
, variable_htab_eq
,
3546 variable_htab_free
);
3547 changed_variables
= htab_create (10, variable_htab_hash
, variable_htab_eq
,
3548 variable_htab_free
);
3550 /* Init the IN and OUT sets. */
3553 VTI (bb
)->visited
= false;
3554 dataflow_set_init (&VTI (bb
)->in
);
3555 dataflow_set_init (&VTI (bb
)->out
);
3558 vt_add_function_parameters ();
3561 /* Free the data structures needed for variable tracking. */
3570 free (VTI (bb
)->mos
);
3575 dataflow_set_destroy (&VTI (bb
)->in
);
3576 dataflow_set_destroy (&VTI (bb
)->out
);
3578 free_aux_for_blocks ();
3579 htab_delete (empty_shared_hash
->htab
);
3580 htab_delete (changed_variables
);
3581 free_alloc_pool (attrs_pool
);
3582 free_alloc_pool (var_pool
);
3583 free_alloc_pool (loc_chain_pool
);
3584 free_alloc_pool (shared_hash_pool
);
3591 /* The entry point to variable tracking pass. */
3594 variable_tracking_main (void)
3596 if (n_basic_blocks
> 500 && n_edges
/ n_basic_blocks
>= 20)
3599 mark_dfs_back_edges ();
3601 if (!frame_pointer_needed
)
3603 if (!vt_stack_adjustments ())
3610 vt_find_locations ();
3613 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3615 dump_dataflow_sets ();
3616 dump_flow_info (dump_file
, dump_flags
);
3624 gate_handle_var_tracking (void)
3626 return (flag_var_tracking
);
3631 struct rtl_opt_pass pass_variable_tracking
=
3635 "vartrack", /* name */
3636 gate_handle_var_tracking
, /* gate */
3637 variable_tracking_main
, /* execute */
3640 0, /* static_pass_number */
3641 TV_VAR_TRACKING
, /* tv_id */
3642 0, /* properties_required */
3643 0, /* properties_provided */
3644 0, /* properties_destroyed */
3645 0, /* todo_flags_start */
3646 TODO_dump_func
| TODO_verify_rtl_sharing
/* todo_flags_finish */