1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
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_CLOBBER
, /* Clobber location. */
118 MO_CALL
, /* Call insn. */
119 MO_ADJUST
/* Adjust stack pointer. */
122 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
125 EMIT_NOTE_BEFORE_INSN
,
129 /* Structure holding information about micro operation. */
130 typedef struct micro_operation_def
132 /* Type of micro operation. */
133 enum micro_operation_type type
;
139 /* Stack adjustment. */
140 HOST_WIDE_INT adjust
;
143 /* The instruction which the micro operation is in. */
147 /* Structure for passing some other parameters to function
148 emit_note_insn_var_location. */
149 typedef struct emit_note_data_def
151 /* The instruction which the note will be emitted before/after. */
154 /* Where the note will be emitted (before/after insn)? */
155 enum emit_note_where where
;
158 /* Description of location of a part of a variable. The content of a physical
159 register is described by a chain of these structures.
160 The chains are pretty short (usually 1 or 2 elements) and thus
161 chain is the best data structure. */
162 typedef struct attrs_def
164 /* Pointer to next member of the list. */
165 struct attrs_def
*next
;
167 /* The rtx of register. */
170 /* The declaration corresponding to LOC. */
173 /* Offset from start of DECL. */
174 HOST_WIDE_INT offset
;
177 /* Structure holding the IN or OUT set for a basic block. */
178 typedef struct dataflow_set_def
180 /* Adjustment of stack offset. */
181 HOST_WIDE_INT stack_adjust
;
183 /* Attributes for registers (lists of attrs). */
184 attrs regs
[FIRST_PSEUDO_REGISTER
];
186 /* Variable locations. */
190 /* The structure (one for each basic block) containing the information
191 needed for variable tracking. */
192 typedef struct variable_tracking_info_def
194 /* Number of micro operations stored in the MOS array. */
197 /* The array of micro operations. */
198 micro_operation
*mos
;
200 /* The IN and OUT set for dataflow analysis. */
204 /* Has the block been visited in DFS? */
206 } *variable_tracking_info
;
208 /* Structure for chaining the locations. */
209 typedef struct location_chain_def
211 /* Next element in the chain. */
212 struct location_chain_def
*next
;
214 /* The location (REG or MEM). */
218 /* Structure describing one part of variable. */
219 typedef struct variable_part_def
221 /* Chain of locations of the part. */
222 location_chain loc_chain
;
224 /* Location which was last emitted to location list. */
227 /* The offset in the variable. */
228 HOST_WIDE_INT offset
;
231 /* Maximum number of location parts. */
232 #define MAX_VAR_PARTS 16
234 /* Structure describing where the variable is located. */
235 typedef struct variable_def
237 /* The declaration of the variable. */
240 /* Reference count. */
243 /* Number of variable parts. */
246 /* The variable parts. */
247 variable_part var_part
[MAX_VAR_PARTS
];
250 /* Hash function for DECL for VARIABLE_HTAB. */
251 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
253 /* Pointer to the BB's information specific to variable tracking pass. */
254 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
256 /* Alloc pool for struct attrs_def. */
257 static alloc_pool attrs_pool
;
259 /* Alloc pool for struct variable_def. */
260 static alloc_pool var_pool
;
262 /* Alloc pool for struct location_chain_def. */
263 static alloc_pool loc_chain_pool
;
265 /* Changed variables, notes will be emitted for them. */
266 static htab_t changed_variables
;
268 /* Shall notes be emitted? */
269 static bool emit_notes
;
271 /* Local function prototypes. */
272 static void stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
274 static void insn_stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
276 static void bb_stack_adjust_offset (basic_block
);
277 static bool vt_stack_adjustments (void);
278 static rtx
adjust_stack_reference (rtx
, HOST_WIDE_INT
);
279 static hashval_t
variable_htab_hash (const void *);
280 static int variable_htab_eq (const void *, const void *);
281 static void variable_htab_free (void *);
283 static void init_attrs_list_set (attrs
*);
284 static void attrs_list_clear (attrs
*);
285 static attrs
attrs_list_member (attrs
, tree
, HOST_WIDE_INT
);
286 static void attrs_list_insert (attrs
*, tree
, HOST_WIDE_INT
, rtx
);
287 static void attrs_list_copy (attrs
*, attrs
);
288 static void attrs_list_union (attrs
*, attrs
);
290 static void vars_clear (htab_t
);
291 static variable
unshare_variable (dataflow_set
*set
, variable var
);
292 static int vars_copy_1 (void **, void *);
293 static void vars_copy (htab_t
, htab_t
);
294 static void var_reg_delete_and_set (dataflow_set
*, rtx
);
295 static void var_reg_delete (dataflow_set
*, rtx
);
296 static void var_regno_delete (dataflow_set
*, int);
297 static void var_mem_delete_and_set (dataflow_set
*, rtx
);
298 static void var_mem_delete (dataflow_set
*, rtx
);
300 static void dataflow_set_init (dataflow_set
*, int);
301 static void dataflow_set_clear (dataflow_set
*);
302 static void dataflow_set_copy (dataflow_set
*, dataflow_set
*);
303 static int variable_union_info_cmp_pos (const void *, const void *);
304 static int variable_union (void **, void *);
305 static void dataflow_set_union (dataflow_set
*, dataflow_set
*);
306 static bool variable_part_different_p (variable_part
*, variable_part
*);
307 static bool variable_different_p (variable
, variable
, bool);
308 static int dataflow_set_different_1 (void **, void *);
309 static int dataflow_set_different_2 (void **, void *);
310 static bool dataflow_set_different (dataflow_set
*, dataflow_set
*);
311 static void dataflow_set_destroy (dataflow_set
*);
313 static bool contains_symbol_ref (rtx
);
314 static bool track_expr_p (tree
);
315 static int count_uses (rtx
*, void *);
316 static void count_uses_1 (rtx
*, void *);
317 static void count_stores (rtx
, rtx
, void *);
318 static int add_uses (rtx
*, void *);
319 static void add_uses_1 (rtx
*, void *);
320 static void add_stores (rtx
, rtx
, void *);
321 static bool compute_bb_dataflow (basic_block
);
322 static void vt_find_locations (void);
324 static void dump_attrs_list (attrs
);
325 static int dump_variable (void **, void *);
326 static void dump_vars (htab_t
);
327 static void dump_dataflow_set (dataflow_set
*);
328 static void dump_dataflow_sets (void);
330 static void variable_was_changed (variable
, htab_t
);
331 static void set_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
332 static void delete_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
333 static int emit_note_insn_var_location (void **, void *);
334 static void emit_notes_for_changes (rtx
, enum emit_note_where
);
335 static int emit_notes_for_differences_1 (void **, void *);
336 static int emit_notes_for_differences_2 (void **, void *);
337 static void emit_notes_for_differences (rtx
, dataflow_set
*, dataflow_set
*);
338 static void emit_notes_in_bb (basic_block
);
339 static void vt_emit_notes (void);
341 static bool vt_get_decl_and_offset (rtx
, tree
*, HOST_WIDE_INT
*);
342 static void vt_add_function_parameters (void);
343 static void vt_initialize (void);
344 static void vt_finalize (void);
346 /* Given a SET, calculate the amount of stack adjustment it contains
347 PRE- and POST-modifying stack pointer.
348 This function is similar to stack_adjust_offset. */
351 stack_adjust_offset_pre_post (rtx pattern
, HOST_WIDE_INT
*pre
,
354 rtx src
= SET_SRC (pattern
);
355 rtx dest
= SET_DEST (pattern
);
358 if (dest
== stack_pointer_rtx
)
360 /* (set (reg sp) (plus (reg sp) (const_int))) */
361 code
= GET_CODE (src
);
362 if (! (code
== PLUS
|| code
== MINUS
)
363 || XEXP (src
, 0) != stack_pointer_rtx
364 || GET_CODE (XEXP (src
, 1)) != CONST_INT
)
368 *post
+= INTVAL (XEXP (src
, 1));
370 *post
-= INTVAL (XEXP (src
, 1));
372 else if (MEM_P (dest
))
374 /* (set (mem (pre_dec (reg sp))) (foo)) */
375 src
= XEXP (dest
, 0);
376 code
= GET_CODE (src
);
382 if (XEXP (src
, 0) == stack_pointer_rtx
)
384 rtx val
= XEXP (XEXP (src
, 1), 1);
385 /* We handle only adjustments by constant amount. */
386 gcc_assert (GET_CODE (XEXP (src
, 1)) == PLUS
&&
387 GET_CODE (val
) == CONST_INT
);
389 if (code
== PRE_MODIFY
)
390 *pre
-= INTVAL (val
);
392 *post
-= INTVAL (val
);
398 if (XEXP (src
, 0) == stack_pointer_rtx
)
400 *pre
+= GET_MODE_SIZE (GET_MODE (dest
));
406 if (XEXP (src
, 0) == stack_pointer_rtx
)
408 *post
+= GET_MODE_SIZE (GET_MODE (dest
));
414 if (XEXP (src
, 0) == stack_pointer_rtx
)
416 *pre
-= GET_MODE_SIZE (GET_MODE (dest
));
422 if (XEXP (src
, 0) == stack_pointer_rtx
)
424 *post
-= GET_MODE_SIZE (GET_MODE (dest
));
435 /* Given an INSN, calculate the amount of stack adjustment it contains
436 PRE- and POST-modifying stack pointer. */
439 insn_stack_adjust_offset_pre_post (rtx insn
, HOST_WIDE_INT
*pre
,
445 if (GET_CODE (PATTERN (insn
)) == SET
)
446 stack_adjust_offset_pre_post (PATTERN (insn
), pre
, post
);
447 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
448 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
452 /* There may be stack adjustments inside compound insns. Search
454 for ( i
= XVECLEN (PATTERN (insn
), 0) - 1; i
>= 0; i
--)
455 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
456 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn
), 0, i
),
461 /* Compute stack adjustment in basic block BB. */
464 bb_stack_adjust_offset (basic_block bb
)
466 HOST_WIDE_INT offset
;
469 offset
= VTI (bb
)->in
.stack_adjust
;
470 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
472 if (VTI (bb
)->mos
[i
].type
== MO_ADJUST
)
473 offset
+= VTI (bb
)->mos
[i
].u
.adjust
;
474 else if (VTI (bb
)->mos
[i
].type
!= MO_CALL
)
476 if (MEM_P (VTI (bb
)->mos
[i
].u
.loc
))
478 VTI (bb
)->mos
[i
].u
.loc
479 = adjust_stack_reference (VTI (bb
)->mos
[i
].u
.loc
, -offset
);
483 VTI (bb
)->out
.stack_adjust
= offset
;
486 /* Compute stack adjustments for all blocks by traversing DFS tree.
487 Return true when the adjustments on all incoming edges are consistent.
488 Heavily borrowed from flow_depth_first_order_compute. */
491 vt_stack_adjustments (void)
493 edge_iterator
*stack
;
496 /* Initialize entry block. */
497 VTI (ENTRY_BLOCK_PTR
)->visited
= true;
498 VTI (ENTRY_BLOCK_PTR
)->out
.stack_adjust
= INCOMING_FRAME_SP_OFFSET
;
500 /* Allocate stack for back-tracking up CFG. */
501 stack
= xmalloc ((n_basic_blocks
+ 1) * sizeof (edge_iterator
));
504 /* Push the first edge on to the stack. */
505 stack
[sp
++] = ei_start (ENTRY_BLOCK_PTR
->succs
);
513 /* Look at the edge on the top of the stack. */
515 src
= ei_edge (ei
)->src
;
516 dest
= ei_edge (ei
)->dest
;
518 /* Check if the edge destination has been visited yet. */
519 if (!VTI (dest
)->visited
)
521 VTI (dest
)->visited
= true;
522 VTI (dest
)->in
.stack_adjust
= VTI (src
)->out
.stack_adjust
;
523 bb_stack_adjust_offset (dest
);
525 if (EDGE_COUNT (dest
->succs
) > 0)
526 /* Since the DEST node has been visited for the first
527 time, check its successors. */
528 stack
[sp
++] = ei_start (dest
->succs
);
532 /* Check whether the adjustments on the edges are the same. */
533 if (VTI (dest
)->in
.stack_adjust
!= VTI (src
)->out
.stack_adjust
)
539 if (! ei_one_before_end_p (ei
))
540 /* Go to the next edge. */
541 ei_next (&stack
[sp
- 1]);
543 /* Return to previous level if there are no more edges. */
552 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
553 to the argument pointer. Return the new rtx. */
556 adjust_stack_reference (rtx mem
, HOST_WIDE_INT adjustment
)
560 adjustment
-= ARG_POINTER_CFA_OFFSET (current_function_decl
);
561 cfa
= plus_constant (arg_pointer_rtx
, adjustment
);
563 addr
= replace_rtx (copy_rtx (XEXP (mem
, 0)), stack_pointer_rtx
, cfa
);
564 tmp
= simplify_rtx (addr
);
568 return replace_equiv_address_nv (mem
, addr
);
571 /* The hash function for variable_htab, computes the hash value
572 from the declaration of variable X. */
575 variable_htab_hash (const void *x
)
577 const variable v
= (const variable
) x
;
579 return (VARIABLE_HASH_VAL (v
->decl
));
582 /* Compare the declaration of variable X with declaration Y. */
585 variable_htab_eq (const void *x
, const void *y
)
587 const variable v
= (const variable
) x
;
588 const tree decl
= (const tree
) y
;
590 return (VARIABLE_HASH_VAL (v
->decl
) == VARIABLE_HASH_VAL (decl
));
593 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
596 variable_htab_free (void *elem
)
599 variable var
= (variable
) elem
;
600 location_chain node
, next
;
602 gcc_assert (var
->refcount
> 0);
605 if (var
->refcount
> 0)
608 for (i
= 0; i
< var
->n_var_parts
; i
++)
610 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= next
)
613 pool_free (loc_chain_pool
, node
);
615 var
->var_part
[i
].loc_chain
= NULL
;
617 pool_free (var_pool
, var
);
620 /* Initialize the set (array) SET of attrs to empty lists. */
623 init_attrs_list_set (attrs
*set
)
627 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
631 /* Make the list *LISTP empty. */
634 attrs_list_clear (attrs
*listp
)
638 for (list
= *listp
; list
; list
= next
)
641 pool_free (attrs_pool
, list
);
646 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
649 attrs_list_member (attrs list
, tree decl
, HOST_WIDE_INT offset
)
651 for (; list
; list
= list
->next
)
652 if (list
->decl
== decl
&& list
->offset
== offset
)
657 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
660 attrs_list_insert (attrs
*listp
, tree decl
, HOST_WIDE_INT offset
, rtx loc
)
664 list
= pool_alloc (attrs_pool
);
667 list
->offset
= offset
;
672 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
675 attrs_list_copy (attrs
*dstp
, attrs src
)
679 attrs_list_clear (dstp
);
680 for (; src
; src
= src
->next
)
682 n
= pool_alloc (attrs_pool
);
685 n
->offset
= src
->offset
;
691 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
694 attrs_list_union (attrs
*dstp
, attrs src
)
696 for (; src
; src
= src
->next
)
698 if (!attrs_list_member (*dstp
, src
->decl
, src
->offset
))
699 attrs_list_insert (dstp
, src
->decl
, src
->offset
, src
->loc
);
703 /* Delete all variables from hash table VARS. */
706 vars_clear (htab_t vars
)
711 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
714 unshare_variable (dataflow_set
*set
, variable var
)
720 new_var
= pool_alloc (var_pool
);
721 new_var
->decl
= var
->decl
;
722 new_var
->refcount
= 1;
724 new_var
->n_var_parts
= var
->n_var_parts
;
726 for (i
= 0; i
< var
->n_var_parts
; i
++)
729 location_chain
*nextp
;
731 new_var
->var_part
[i
].offset
= var
->var_part
[i
].offset
;
732 nextp
= &new_var
->var_part
[i
].loc_chain
;
733 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
735 location_chain new_lc
;
737 new_lc
= pool_alloc (loc_chain_pool
);
739 new_lc
->loc
= node
->loc
;
742 nextp
= &new_lc
->next
;
745 /* We are at the basic block boundary when copying variable description
746 so set the CUR_LOC to be the first element of the chain. */
747 if (new_var
->var_part
[i
].loc_chain
)
748 new_var
->var_part
[i
].cur_loc
= new_var
->var_part
[i
].loc_chain
->loc
;
750 new_var
->var_part
[i
].cur_loc
= NULL
;
753 slot
= htab_find_slot_with_hash (set
->vars
, new_var
->decl
,
754 VARIABLE_HASH_VAL (new_var
->decl
),
760 /* Add a variable from *SLOT to hash table DATA and increase its reference
764 vars_copy_1 (void **slot
, void *data
)
766 htab_t dst
= (htab_t
) data
;
769 src
= *(variable
*) slot
;
772 dstp
= (variable
*) htab_find_slot_with_hash (dst
, src
->decl
,
773 VARIABLE_HASH_VAL (src
->decl
),
777 /* Continue traversing the hash table. */
781 /* Copy all variables from hash table SRC to hash table DST. */
784 vars_copy (htab_t dst
, htab_t src
)
787 htab_traverse (src
, vars_copy_1
, dst
);
790 /* Delete current content of register LOC in dataflow set SET
791 and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
794 var_reg_delete_and_set (dataflow_set
*set
, rtx loc
)
796 tree decl
= REG_EXPR (loc
);
797 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
801 nextp
= &set
->regs
[REGNO (loc
)];
802 for (node
= *nextp
; node
; node
= next
)
805 if (node
->decl
!= decl
|| node
->offset
!= offset
)
807 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
808 pool_free (attrs_pool
, node
);
817 if (set
->regs
[REGNO (loc
)] == NULL
)
818 attrs_list_insert (&set
->regs
[REGNO (loc
)], decl
, offset
, loc
);
819 set_variable_part (set
, loc
, decl
, offset
);
822 /* Delete current content of register LOC in dataflow set SET. */
825 var_reg_delete (dataflow_set
*set
, rtx loc
)
827 attrs
*reg
= &set
->regs
[REGNO (loc
)];
830 for (node
= *reg
; node
; node
= next
)
833 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
834 pool_free (attrs_pool
, node
);
839 /* Delete content of register with number REGNO in dataflow set SET. */
842 var_regno_delete (dataflow_set
*set
, int regno
)
844 attrs
*reg
= &set
->regs
[regno
];
847 for (node
= *reg
; node
; node
= next
)
850 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
851 pool_free (attrs_pool
, node
);
856 /* Delete and set the location part of variable MEM_EXPR (LOC)
857 in dataflow set SET to LOC.
858 Adjust the address first if it is stack pointer based. */
861 var_mem_delete_and_set (dataflow_set
*set
, rtx loc
)
863 tree decl
= MEM_EXPR (loc
);
864 HOST_WIDE_INT offset
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
866 set_variable_part (set
, loc
, decl
, offset
);
869 /* Delete the location part LOC from dataflow set SET.
870 Adjust the address first if it is stack pointer based. */
873 var_mem_delete (dataflow_set
*set
, rtx loc
)
875 tree decl
= MEM_EXPR (loc
);
876 HOST_WIDE_INT offset
= MEM_OFFSET (loc
) ? INTVAL (MEM_OFFSET (loc
)) : 0;
878 delete_variable_part (set
, loc
, decl
, offset
);
881 /* Initialize dataflow set SET to be empty.
882 VARS_SIZE is the initial size of hash table VARS. */
885 dataflow_set_init (dataflow_set
*set
, int vars_size
)
887 init_attrs_list_set (set
->regs
);
888 set
->vars
= htab_create (vars_size
, variable_htab_hash
, variable_htab_eq
,
890 set
->stack_adjust
= 0;
893 /* Delete the contents of dataflow set SET. */
896 dataflow_set_clear (dataflow_set
*set
)
900 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
901 attrs_list_clear (&set
->regs
[i
]);
903 vars_clear (set
->vars
);
906 /* Copy the contents of dataflow set SRC to DST. */
909 dataflow_set_copy (dataflow_set
*dst
, dataflow_set
*src
)
913 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
914 attrs_list_copy (&dst
->regs
[i
], src
->regs
[i
]);
916 vars_copy (dst
->vars
, src
->vars
);
917 dst
->stack_adjust
= src
->stack_adjust
;
920 /* Information for merging lists of locations for a given offset of variable.
922 struct variable_union_info
924 /* Node of the location chain. */
927 /* The sum of positions in the input chains. */
930 /* The position in the chains of SRC and DST dataflow sets. */
935 /* Compare function for qsort, order the structures by POS element. */
938 variable_union_info_cmp_pos (const void *n1
, const void *n2
)
940 const struct variable_union_info
*i1
= n1
;
941 const struct variable_union_info
*i2
= n2
;
943 if (i1
->pos
!= i2
->pos
)
944 return i1
->pos
- i2
->pos
;
946 return (i1
->pos_dst
- i2
->pos_dst
);
949 /* Compute union of location parts of variable *SLOT and the same variable
950 from hash table DATA. Compute "sorted" union of the location chains
951 for common offsets, i.e. the locations of a variable part are sorted by
952 a priority where the priority is the sum of the positions in the 2 chains
953 (if a location is only in one list the position in the second list is
954 defined to be larger than the length of the chains).
955 When we are updating the location parts the newest location is in the
956 beginning of the chain, so when we do the described "sorted" union
957 we keep the newest locations in the beginning. */
960 variable_union (void **slot
, void *data
)
962 variable src
, dst
, *dstp
;
963 dataflow_set
*set
= (dataflow_set
*) data
;
966 src
= *(variable
*) slot
;
967 dstp
= (variable
*) htab_find_slot_with_hash (set
->vars
, src
->decl
,
968 VARIABLE_HASH_VAL (src
->decl
),
974 /* If CUR_LOC of some variable part is not the first element of
975 the location chain we are going to change it so we have to make
976 a copy of the variable. */
977 for (k
= 0; k
< src
->n_var_parts
; k
++)
979 gcc_assert (!src
->var_part
[k
].loc_chain
980 == !src
->var_part
[k
].cur_loc
);
981 if (src
->var_part
[k
].loc_chain
)
983 gcc_assert (src
->var_part
[k
].cur_loc
);
984 if (src
->var_part
[k
].cur_loc
!= src
->var_part
[k
].loc_chain
->loc
)
988 if (k
< src
->n_var_parts
)
989 unshare_variable (set
, src
);
993 /* Continue traversing the hash table. */
999 gcc_assert (src
->n_var_parts
);
1001 /* Count the number of location parts, result is K. */
1002 for (i
= 0, j
= 0, k
= 0;
1003 i
< src
->n_var_parts
&& j
< dst
->n_var_parts
; k
++)
1005 if (src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1010 else if (src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1015 k
+= src
->n_var_parts
- i
;
1016 k
+= dst
->n_var_parts
- j
;
1018 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1019 thus there are at most MAX_VAR_PARTS different offsets. */
1020 gcc_assert (k
<= MAX_VAR_PARTS
);
1022 if (dst
->refcount
> 1 && dst
->n_var_parts
!= k
)
1023 dst
= unshare_variable (set
, dst
);
1025 i
= src
->n_var_parts
- 1;
1026 j
= dst
->n_var_parts
- 1;
1027 dst
->n_var_parts
= k
;
1029 for (k
--; k
>= 0; k
--)
1031 location_chain node
, node2
;
1033 if (i
>= 0 && j
>= 0
1034 && src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1036 /* Compute the "sorted" union of the chains, i.e. the locations which
1037 are in both chains go first, they are sorted by the sum of
1038 positions in the chains. */
1041 struct variable_union_info
*vui
;
1043 /* If DST is shared compare the location chains.
1044 If they are different we will modify the chain in DST with
1045 high probability so make a copy of DST. */
1046 if (dst
->refcount
> 1)
1048 for (node
= src
->var_part
[i
].loc_chain
,
1049 node2
= dst
->var_part
[j
].loc_chain
; node
&& node2
;
1050 node
= node
->next
, node2
= node2
->next
)
1052 if (!((REG_P (node2
->loc
)
1053 && REG_P (node
->loc
)
1054 && REGNO (node2
->loc
) == REGNO (node
->loc
))
1055 || rtx_equal_p (node2
->loc
, node
->loc
)))
1059 dst
= unshare_variable (set
, dst
);
1063 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1066 for (node
= dst
->var_part
[j
].loc_chain
; node
; node
= node
->next
)
1068 vui
= xcalloc (src_l
+ dst_l
, sizeof (struct variable_union_info
));
1070 /* Fill in the locations from DST. */
1071 for (node
= dst
->var_part
[j
].loc_chain
, jj
= 0; node
;
1072 node
= node
->next
, jj
++)
1075 vui
[jj
].pos_dst
= jj
;
1077 /* Value larger than a sum of 2 valid positions. */
1078 vui
[jj
].pos_src
= src_l
+ dst_l
;
1081 /* Fill in the locations from SRC. */
1083 for (node
= src
->var_part
[i
].loc_chain
, ii
= 0; node
;
1084 node
= node
->next
, ii
++)
1086 /* Find location from NODE. */
1087 for (jj
= 0; jj
< dst_l
; jj
++)
1089 if ((REG_P (vui
[jj
].lc
->loc
)
1090 && REG_P (node
->loc
)
1091 && REGNO (vui
[jj
].lc
->loc
) == REGNO (node
->loc
))
1092 || rtx_equal_p (vui
[jj
].lc
->loc
, node
->loc
))
1094 vui
[jj
].pos_src
= ii
;
1098 if (jj
>= dst_l
) /* The location has not been found. */
1100 location_chain new_node
;
1102 /* Copy the location from SRC. */
1103 new_node
= pool_alloc (loc_chain_pool
);
1104 new_node
->loc
= node
->loc
;
1105 vui
[n
].lc
= new_node
;
1106 vui
[n
].pos_src
= ii
;
1107 vui
[n
].pos_dst
= src_l
+ dst_l
;
1112 for (ii
= 0; ii
< src_l
+ dst_l
; ii
++)
1113 vui
[ii
].pos
= vui
[ii
].pos_src
+ vui
[ii
].pos_dst
;
1115 qsort (vui
, n
, sizeof (struct variable_union_info
),
1116 variable_union_info_cmp_pos
);
1118 /* Reconnect the nodes in sorted order. */
1119 for (ii
= 1; ii
< n
; ii
++)
1120 vui
[ii
- 1].lc
->next
= vui
[ii
].lc
;
1121 vui
[n
- 1].lc
->next
= NULL
;
1123 dst
->var_part
[k
].loc_chain
= vui
[0].lc
;
1124 dst
->var_part
[k
].offset
= dst
->var_part
[j
].offset
;
1130 else if ((i
>= 0 && j
>= 0
1131 && src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1134 dst
->var_part
[k
] = dst
->var_part
[j
];
1137 else if ((i
>= 0 && j
>= 0
1138 && src
->var_part
[i
].offset
> dst
->var_part
[j
].offset
)
1141 location_chain
*nextp
;
1143 /* Copy the chain from SRC. */
1144 nextp
= &dst
->var_part
[k
].loc_chain
;
1145 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1147 location_chain new_lc
;
1149 new_lc
= pool_alloc (loc_chain_pool
);
1150 new_lc
->next
= NULL
;
1151 new_lc
->loc
= node
->loc
;
1154 nextp
= &new_lc
->next
;
1157 dst
->var_part
[k
].offset
= src
->var_part
[i
].offset
;
1161 /* We are at the basic block boundary when computing union
1162 so set the CUR_LOC to be the first element of the chain. */
1163 if (dst
->var_part
[k
].loc_chain
)
1164 dst
->var_part
[k
].cur_loc
= dst
->var_part
[k
].loc_chain
->loc
;
1166 dst
->var_part
[k
].cur_loc
= NULL
;
1169 /* Continue traversing the hash table. */
1173 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1176 dataflow_set_union (dataflow_set
*dst
, dataflow_set
*src
)
1180 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1181 attrs_list_union (&dst
->regs
[i
], src
->regs
[i
]);
1183 htab_traverse (src
->vars
, variable_union
, dst
);
1186 /* Flag whether two dataflow sets being compared contain different data. */
1188 dataflow_set_different_value
;
1191 variable_part_different_p (variable_part
*vp1
, variable_part
*vp2
)
1193 location_chain lc1
, lc2
;
1195 for (lc1
= vp1
->loc_chain
; lc1
; lc1
= lc1
->next
)
1197 for (lc2
= vp2
->loc_chain
; lc2
; lc2
= lc2
->next
)
1199 if (REG_P (lc1
->loc
) && REG_P (lc2
->loc
))
1201 if (REGNO (lc1
->loc
) == REGNO (lc2
->loc
))
1204 if (rtx_equal_p (lc1
->loc
, lc2
->loc
))
1213 /* Return true if variables VAR1 and VAR2 are different.
1214 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1218 variable_different_p (variable var1
, variable var2
,
1219 bool compare_current_location
)
1226 if (var1
->n_var_parts
!= var2
->n_var_parts
)
1229 for (i
= 0; i
< var1
->n_var_parts
; i
++)
1231 if (var1
->var_part
[i
].offset
!= var2
->var_part
[i
].offset
)
1233 if (compare_current_location
)
1235 if (!((REG_P (var1
->var_part
[i
].cur_loc
)
1236 && REG_P (var2
->var_part
[i
].cur_loc
)
1237 && (REGNO (var1
->var_part
[i
].cur_loc
)
1238 == REGNO (var2
->var_part
[i
].cur_loc
)))
1239 || rtx_equal_p (var1
->var_part
[i
].cur_loc
,
1240 var2
->var_part
[i
].cur_loc
)))
1243 if (variable_part_different_p (&var1
->var_part
[i
], &var2
->var_part
[i
]))
1245 if (variable_part_different_p (&var2
->var_part
[i
], &var1
->var_part
[i
]))
1251 /* Compare variable *SLOT with the same variable in hash table DATA
1252 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1255 dataflow_set_different_1 (void **slot
, void *data
)
1257 htab_t htab
= (htab_t
) data
;
1258 variable var1
, var2
;
1260 var1
= *(variable
*) slot
;
1261 var2
= htab_find_with_hash (htab
, var1
->decl
,
1262 VARIABLE_HASH_VAL (var1
->decl
));
1265 dataflow_set_different_value
= true;
1267 /* Stop traversing the hash table. */
1271 if (variable_different_p (var1
, var2
, false))
1273 dataflow_set_different_value
= true;
1275 /* Stop traversing the hash table. */
1279 /* Continue traversing the hash table. */
1283 /* Compare variable *SLOT with the same variable in hash table DATA
1284 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1287 dataflow_set_different_2 (void **slot
, void *data
)
1289 htab_t htab
= (htab_t
) data
;
1290 variable var1
, var2
;
1292 var1
= *(variable
*) slot
;
1293 var2
= htab_find_with_hash (htab
, var1
->decl
,
1294 VARIABLE_HASH_VAL (var1
->decl
));
1297 dataflow_set_different_value
= true;
1299 /* Stop traversing the hash table. */
1303 /* If both variables are defined they have been already checked for
1305 gcc_assert (!variable_different_p (var1
, var2
, false));
1307 /* Continue traversing the hash table. */
1311 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1314 dataflow_set_different (dataflow_set
*old_set
, dataflow_set
*new_set
)
1316 dataflow_set_different_value
= false;
1318 htab_traverse (old_set
->vars
, dataflow_set_different_1
, new_set
->vars
);
1319 if (!dataflow_set_different_value
)
1321 /* We have compared the variables which are in both hash tables
1322 so now only check whether there are some variables in NEW_SET->VARS
1323 which are not in OLD_SET->VARS. */
1324 htab_traverse (new_set
->vars
, dataflow_set_different_2
, old_set
->vars
);
1326 return dataflow_set_different_value
;
1329 /* Free the contents of dataflow set SET. */
1332 dataflow_set_destroy (dataflow_set
*set
)
1336 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1337 attrs_list_clear (&set
->regs
[i
]);
1339 htab_delete (set
->vars
);
1343 /* Return true if RTL X contains a SYMBOL_REF. */
1346 contains_symbol_ref (rtx x
)
1355 code
= GET_CODE (x
);
1356 if (code
== SYMBOL_REF
)
1359 fmt
= GET_RTX_FORMAT (code
);
1360 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1364 if (contains_symbol_ref (XEXP (x
, i
)))
1367 else if (fmt
[i
] == 'E')
1370 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1371 if (contains_symbol_ref (XVECEXP (x
, i
, j
)))
1379 /* Shall EXPR be tracked? */
1382 track_expr_p (tree expr
)
1387 /* If EXPR is not a parameter or a variable do not track it. */
1388 if (TREE_CODE (expr
) != VAR_DECL
&& TREE_CODE (expr
) != PARM_DECL
)
1391 /* It also must have a name... */
1392 if (!DECL_NAME (expr
))
1395 /* ... and a RTL assigned to it. */
1396 decl_rtl
= DECL_RTL_IF_SET (expr
);
1400 /* If this expression is really a debug alias of some other declaration, we
1401 don't need to track this expression if the ultimate declaration is
1404 if (DECL_DEBUG_EXPR_IS_FROM (realdecl
) && DECL_DEBUG_EXPR (realdecl
))
1406 realdecl
= DECL_DEBUG_EXPR (realdecl
);
1407 /* ??? We don't yet know how to emit DW_OP_piece for variable
1408 that has been SRA'ed. */
1409 if (!DECL_P (realdecl
))
1413 /* Do not track EXPR if REALDECL it should be ignored for debugging
1415 if (DECL_IGNORED_P (realdecl
))
1418 /* Do not track global variables until we are able to emit correct location
1420 if (TREE_STATIC (realdecl
))
1423 /* When the EXPR is a DECL for alias of some variable (see example)
1424 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1425 DECL_RTL contains SYMBOL_REF.
1428 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1431 if (MEM_P (decl_rtl
)
1432 && contains_symbol_ref (XEXP (decl_rtl
, 0)))
1435 /* If RTX is a memory it should not be very large (because it would be
1436 an array or struct). */
1437 if (MEM_P (decl_rtl
))
1439 /* Do not track structures and arrays. */
1440 if (GET_MODE (decl_rtl
) == BLKmode
)
1442 if (MEM_SIZE (decl_rtl
)
1443 && INTVAL (MEM_SIZE (decl_rtl
)) > MAX_VAR_PARTS
)
1450 /* Count uses (register and memory references) LOC which will be tracked.
1451 INSN is instruction which the LOC is part of. */
1454 count_uses (rtx
*loc
, void *insn
)
1456 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1460 gcc_assert (REGNO (*loc
) < FIRST_PSEUDO_REGISTER
);
1463 else if (MEM_P (*loc
)
1465 && track_expr_p (MEM_EXPR (*loc
)))
1473 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1476 count_uses_1 (rtx
*x
, void *insn
)
1478 for_each_rtx (x
, count_uses
, insn
);
1481 /* Count stores (register and memory references) LOC which will be tracked.
1482 INSN is instruction which the LOC is part of. */
1485 count_stores (rtx loc
, rtx expr ATTRIBUTE_UNUSED
, void *insn
)
1487 count_uses (&loc
, insn
);
1490 /* Add uses (register and memory references) LOC which will be tracked
1491 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
1494 add_uses (rtx
*loc
, void *insn
)
1498 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1499 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1501 mo
->type
= ((REG_EXPR (*loc
) && track_expr_p (REG_EXPR (*loc
)))
1502 ? MO_USE
: MO_USE_NO_VAR
);
1504 mo
->insn
= (rtx
) insn
;
1506 else if (MEM_P (*loc
)
1508 && track_expr_p (MEM_EXPR (*loc
)))
1510 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1511 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1515 mo
->insn
= (rtx
) insn
;
1521 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1524 add_uses_1 (rtx
*x
, void *insn
)
1526 for_each_rtx (x
, add_uses
, insn
);
1529 /* Add stores (register and memory references) LOC which will be tracked
1530 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
1531 INSN is instruction which the LOC is part of. */
1534 add_stores (rtx loc
, rtx expr
, void *insn
)
1538 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1539 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1541 mo
->type
= ((GET_CODE (expr
) != CLOBBER
&& REG_EXPR (loc
)
1542 && track_expr_p (REG_EXPR (loc
)))
1543 ? MO_SET
: MO_CLOBBER
);
1545 mo
->insn
= (rtx
) insn
;
1547 else if (MEM_P (loc
)
1549 && track_expr_p (MEM_EXPR (loc
)))
1551 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1552 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1554 mo
->type
= GET_CODE (expr
) == CLOBBER
? MO_CLOBBER
: MO_SET
;
1556 mo
->insn
= (rtx
) insn
;
1560 /* Compute the changes of variable locations in the basic block BB. */
1563 compute_bb_dataflow (basic_block bb
)
1567 dataflow_set old_out
;
1568 dataflow_set
*in
= &VTI (bb
)->in
;
1569 dataflow_set
*out
= &VTI (bb
)->out
;
1571 dataflow_set_init (&old_out
, htab_elements (VTI (bb
)->out
.vars
) + 3);
1572 dataflow_set_copy (&old_out
, out
);
1573 dataflow_set_copy (out
, in
);
1575 n
= VTI (bb
)->n_mos
;
1576 for (i
= 0; i
< n
; i
++)
1578 switch (VTI (bb
)->mos
[i
].type
)
1581 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
1582 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
1583 var_regno_delete (out
, r
);
1589 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1592 var_reg_delete_and_set (out
, loc
);
1593 else if (MEM_P (loc
))
1594 var_mem_delete_and_set (out
, loc
);
1601 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1604 var_reg_delete (out
, loc
);
1605 else if (MEM_P (loc
))
1606 var_mem_delete (out
, loc
);
1611 out
->stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
1616 changed
= dataflow_set_different (&old_out
, out
);
1617 dataflow_set_destroy (&old_out
);
1621 /* Find the locations of variables in the whole function. */
1624 vt_find_locations (void)
1626 fibheap_t worklist
, pending
, fibheap_swap
;
1627 sbitmap visited
, in_worklist
, in_pending
, sbitmap_swap
;
1634 /* Compute reverse completion order of depth first search of the CFG
1635 so that the data-flow runs faster. */
1636 rc_order
= xmalloc (n_basic_blocks
* sizeof (int));
1637 bb_order
= xmalloc (last_basic_block
* sizeof (int));
1638 flow_depth_first_order_compute (NULL
, rc_order
);
1639 for (i
= 0; i
< n_basic_blocks
; i
++)
1640 bb_order
[rc_order
[i
]] = i
;
1643 worklist
= fibheap_new ();
1644 pending
= fibheap_new ();
1645 visited
= sbitmap_alloc (last_basic_block
);
1646 in_worklist
= sbitmap_alloc (last_basic_block
);
1647 in_pending
= sbitmap_alloc (last_basic_block
);
1648 sbitmap_zero (in_worklist
);
1651 fibheap_insert (pending
, bb_order
[bb
->index
], bb
);
1652 sbitmap_ones (in_pending
);
1654 while (!fibheap_empty (pending
))
1656 fibheap_swap
= pending
;
1658 worklist
= fibheap_swap
;
1659 sbitmap_swap
= in_pending
;
1660 in_pending
= in_worklist
;
1661 in_worklist
= sbitmap_swap
;
1663 sbitmap_zero (visited
);
1665 while (!fibheap_empty (worklist
))
1667 bb
= fibheap_extract_min (worklist
);
1668 RESET_BIT (in_worklist
, bb
->index
);
1669 if (!TEST_BIT (visited
, bb
->index
))
1674 SET_BIT (visited
, bb
->index
);
1676 /* Calculate the IN set as union of predecessor OUT sets. */
1677 dataflow_set_clear (&VTI (bb
)->in
);
1678 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
1680 dataflow_set_union (&VTI (bb
)->in
, &VTI (e
->src
)->out
);
1683 changed
= compute_bb_dataflow (bb
);
1686 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1688 if (e
->dest
== EXIT_BLOCK_PTR
)
1694 if (TEST_BIT (visited
, e
->dest
->index
))
1696 if (!TEST_BIT (in_pending
, e
->dest
->index
))
1698 /* Send E->DEST to next round. */
1699 SET_BIT (in_pending
, e
->dest
->index
);
1700 fibheap_insert (pending
,
1701 bb_order
[e
->dest
->index
],
1705 else if (!TEST_BIT (in_worklist
, e
->dest
->index
))
1707 /* Add E->DEST to current round. */
1708 SET_BIT (in_worklist
, e
->dest
->index
);
1709 fibheap_insert (worklist
, bb_order
[e
->dest
->index
],
1719 fibheap_delete (worklist
);
1720 fibheap_delete (pending
);
1721 sbitmap_free (visited
);
1722 sbitmap_free (in_worklist
);
1723 sbitmap_free (in_pending
);
1726 /* Print the content of the LIST to dump file. */
1729 dump_attrs_list (attrs list
)
1731 for (; list
; list
= list
->next
)
1733 print_mem_expr (dump_file
, list
->decl
);
1734 fprintf (dump_file
, "+" HOST_WIDE_INT_PRINT_DEC
, list
->offset
);
1736 fprintf (dump_file
, "\n");
1739 /* Print the information about variable *SLOT to dump file. */
1742 dump_variable (void **slot
, void *data ATTRIBUTE_UNUSED
)
1744 variable var
= *(variable
*) slot
;
1746 location_chain node
;
1748 fprintf (dump_file
, " name: %s\n",
1749 IDENTIFIER_POINTER (DECL_NAME (var
->decl
)));
1750 for (i
= 0; i
< var
->n_var_parts
; i
++)
1752 fprintf (dump_file
, " offset %ld\n",
1753 (long) var
->var_part
[i
].offset
);
1754 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1756 fprintf (dump_file
, " ");
1757 print_rtl_single (dump_file
, node
->loc
);
1761 /* Continue traversing the hash table. */
1765 /* Print the information about variables from hash table VARS to dump file. */
1768 dump_vars (htab_t vars
)
1770 if (htab_elements (vars
) > 0)
1772 fprintf (dump_file
, "Variables:\n");
1773 htab_traverse (vars
, dump_variable
, NULL
);
1777 /* Print the dataflow set SET to dump file. */
1780 dump_dataflow_set (dataflow_set
*set
)
1784 fprintf (dump_file
, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC
"\n",
1786 for (i
= 1; i
< FIRST_PSEUDO_REGISTER
; i
++)
1790 fprintf (dump_file
, "Reg %d:", i
);
1791 dump_attrs_list (set
->regs
[i
]);
1794 dump_vars (set
->vars
);
1795 fprintf (dump_file
, "\n");
1798 /* Print the IN and OUT sets for each basic block to dump file. */
1801 dump_dataflow_sets (void)
1807 fprintf (dump_file
, "\nBasic block %d:\n", bb
->index
);
1808 fprintf (dump_file
, "IN:\n");
1809 dump_dataflow_set (&VTI (bb
)->in
);
1810 fprintf (dump_file
, "OUT:\n");
1811 dump_dataflow_set (&VTI (bb
)->out
);
1815 /* Add variable VAR to the hash table of changed variables and
1816 if it has no locations delete it from hash table HTAB. */
1819 variable_was_changed (variable var
, htab_t htab
)
1821 hashval_t hash
= VARIABLE_HASH_VAL (var
->decl
);
1827 slot
= (variable
*) htab_find_slot_with_hash (changed_variables
,
1828 var
->decl
, hash
, INSERT
);
1830 if (htab
&& var
->n_var_parts
== 0)
1835 empty_var
= pool_alloc (var_pool
);
1836 empty_var
->decl
= var
->decl
;
1837 empty_var
->refcount
= 1;
1838 empty_var
->n_var_parts
= 0;
1841 old
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
1844 htab_clear_slot (htab
, old
);
1854 if (var
->n_var_parts
== 0)
1856 void **slot
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
1859 htab_clear_slot (htab
, slot
);
1864 /* Set the part of variable's location in the dataflow set SET. The variable
1865 part is specified by variable's declaration DECL and offset OFFSET and the
1866 part's location by LOC. */
1869 set_variable_part (dataflow_set
*set
, rtx loc
, tree decl
, HOST_WIDE_INT offset
)
1872 location_chain node
, next
;
1873 location_chain
*nextp
;
1877 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
1878 VARIABLE_HASH_VAL (decl
), INSERT
);
1881 /* Create new variable information. */
1882 var
= pool_alloc (var_pool
);
1885 var
->n_var_parts
= 1;
1886 var
->var_part
[0].offset
= offset
;
1887 var
->var_part
[0].loc_chain
= NULL
;
1888 var
->var_part
[0].cur_loc
= NULL
;
1894 var
= (variable
) *slot
;
1896 /* Find the location part. */
1898 high
= var
->n_var_parts
;
1901 pos
= (low
+ high
) / 2;
1902 if (var
->var_part
[pos
].offset
< offset
)
1909 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
1911 node
= var
->var_part
[pos
].loc_chain
;
1914 && ((REG_P (node
->loc
) && REG_P (loc
)
1915 && REGNO (node
->loc
) == REGNO (loc
))
1916 || rtx_equal_p (node
->loc
, loc
)))
1918 /* LOC is in the beginning of the chain so we have nothing
1924 /* We have to make a copy of a shared variable. */
1925 if (var
->refcount
> 1)
1926 var
= unshare_variable (set
, var
);
1931 /* We have not found the location part, new one will be created. */
1933 /* We have to make a copy of the shared variable. */
1934 if (var
->refcount
> 1)
1935 var
= unshare_variable (set
, var
);
1937 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1938 thus there are at most MAX_VAR_PARTS different offsets. */
1939 gcc_assert (var
->n_var_parts
< MAX_VAR_PARTS
);
1941 /* We have to move the elements of array starting at index low to the
1943 for (high
= var
->n_var_parts
; high
> low
; high
--)
1944 var
->var_part
[high
] = var
->var_part
[high
- 1];
1947 var
->var_part
[pos
].offset
= offset
;
1948 var
->var_part
[pos
].loc_chain
= NULL
;
1949 var
->var_part
[pos
].cur_loc
= NULL
;
1953 /* Delete the location from the list. */
1954 nextp
= &var
->var_part
[pos
].loc_chain
;
1955 for (node
= var
->var_part
[pos
].loc_chain
; node
; node
= next
)
1958 if ((REG_P (node
->loc
) && REG_P (loc
)
1959 && REGNO (node
->loc
) == REGNO (loc
))
1960 || rtx_equal_p (node
->loc
, loc
))
1962 pool_free (loc_chain_pool
, node
);
1967 nextp
= &node
->next
;
1970 /* Add the location to the beginning. */
1971 node
= pool_alloc (loc_chain_pool
);
1973 node
->next
= var
->var_part
[pos
].loc_chain
;
1974 var
->var_part
[pos
].loc_chain
= node
;
1976 /* If no location was emitted do so. */
1977 if (var
->var_part
[pos
].cur_loc
== NULL
)
1979 var
->var_part
[pos
].cur_loc
= loc
;
1980 variable_was_changed (var
, set
->vars
);
1984 /* Delete the part of variable's location from dataflow set SET. The variable
1985 part is specified by variable's declaration DECL and offset OFFSET and the
1986 part's location by LOC. */
1989 delete_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
1990 HOST_WIDE_INT offset
)
1995 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
1999 variable var
= (variable
) *slot
;
2001 /* Find the location part. */
2003 high
= var
->n_var_parts
;
2006 pos
= (low
+ high
) / 2;
2007 if (var
->var_part
[pos
].offset
< offset
)
2014 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
2016 location_chain node
, next
;
2017 location_chain
*nextp
;
2020 if (var
->refcount
> 1)
2022 /* If the variable contains the location part we have to
2023 make a copy of the variable. */
2024 for (node
= var
->var_part
[pos
].loc_chain
; node
;
2027 if ((REG_P (node
->loc
) && REG_P (loc
)
2028 && REGNO (node
->loc
) == REGNO (loc
))
2029 || rtx_equal_p (node
->loc
, loc
))
2031 var
= unshare_variable (set
, var
);
2037 /* Delete the location part. */
2038 nextp
= &var
->var_part
[pos
].loc_chain
;
2039 for (node
= *nextp
; node
; node
= next
)
2042 if ((REG_P (node
->loc
) && REG_P (loc
)
2043 && REGNO (node
->loc
) == REGNO (loc
))
2044 || rtx_equal_p (node
->loc
, loc
))
2046 pool_free (loc_chain_pool
, node
);
2051 nextp
= &node
->next
;
2054 /* If we have deleted the location which was last emitted
2055 we have to emit new location so add the variable to set
2056 of changed variables. */
2057 if (var
->var_part
[pos
].cur_loc
2059 && REG_P (var
->var_part
[pos
].cur_loc
)
2060 && REGNO (loc
) == REGNO (var
->var_part
[pos
].cur_loc
))
2061 || rtx_equal_p (loc
, var
->var_part
[pos
].cur_loc
)))
2064 if (var
->var_part
[pos
].loc_chain
)
2065 var
->var_part
[pos
].cur_loc
= var
->var_part
[pos
].loc_chain
->loc
;
2070 if (var
->var_part
[pos
].loc_chain
== NULL
)
2073 while (pos
< var
->n_var_parts
)
2075 var
->var_part
[pos
] = var
->var_part
[pos
+ 1];
2080 variable_was_changed (var
, set
->vars
);
2085 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2086 additional parameters: WHERE specifies whether the note shall be emitted
2087 before of after instruction INSN. */
2090 emit_note_insn_var_location (void **varp
, void *data
)
2092 variable var
= *(variable
*) varp
;
2093 rtx insn
= ((emit_note_data
*)data
)->insn
;
2094 enum emit_note_where where
= ((emit_note_data
*)data
)->where
;
2096 int i
, j
, n_var_parts
;
2098 HOST_WIDE_INT last_limit
;
2099 tree type_size_unit
;
2100 HOST_WIDE_INT offsets
[MAX_VAR_PARTS
];
2101 rtx loc
[MAX_VAR_PARTS
];
2103 gcc_assert (var
->decl
);
2108 for (i
= 0; i
< var
->n_var_parts
; i
++)
2110 enum machine_mode mode
, wider_mode
;
2112 if (last_limit
< var
->var_part
[i
].offset
)
2117 else if (last_limit
> var
->var_part
[i
].offset
)
2119 offsets
[n_var_parts
] = var
->var_part
[i
].offset
;
2120 loc
[n_var_parts
] = var
->var_part
[i
].loc_chain
->loc
;
2121 mode
= GET_MODE (loc
[n_var_parts
]);
2122 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2124 /* Attempt to merge adjacent registers or memory. */
2125 wider_mode
= GET_MODE_WIDER_MODE (mode
);
2126 for (j
= i
+ 1; j
< var
->n_var_parts
; j
++)
2127 if (last_limit
<= var
->var_part
[j
].offset
)
2129 if (j
< var
->n_var_parts
2130 && wider_mode
!= VOIDmode
2131 && GET_CODE (loc
[n_var_parts
])
2132 == GET_CODE (var
->var_part
[j
].loc_chain
->loc
)
2133 && mode
== GET_MODE (var
->var_part
[j
].loc_chain
->loc
)
2134 && last_limit
== var
->var_part
[j
].offset
)
2137 rtx loc2
= var
->var_part
[j
].loc_chain
->loc
;
2139 if (REG_P (loc
[n_var_parts
])
2140 && hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
] * 2
2141 == hard_regno_nregs
[REGNO (loc
[n_var_parts
])][wider_mode
]
2142 && REGNO (loc
[n_var_parts
])
2143 + hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
]
2146 if (! WORDS_BIG_ENDIAN
&& ! BYTES_BIG_ENDIAN
)
2147 new_loc
= simplify_subreg (wider_mode
, loc
[n_var_parts
],
2149 else if (WORDS_BIG_ENDIAN
&& BYTES_BIG_ENDIAN
)
2150 new_loc
= simplify_subreg (wider_mode
, loc2
, mode
, 0);
2153 if (!REG_P (new_loc
)
2154 || REGNO (new_loc
) != REGNO (loc
[n_var_parts
]))
2157 REG_ATTRS (new_loc
) = REG_ATTRS (loc
[n_var_parts
]);
2160 else if (MEM_P (loc
[n_var_parts
])
2161 && GET_CODE (XEXP (loc2
, 0)) == PLUS
2162 && GET_CODE (XEXP (XEXP (loc2
, 0), 0)) == REG
2163 && GET_CODE (XEXP (XEXP (loc2
, 0), 1)) == CONST_INT
)
2165 if ((GET_CODE (XEXP (loc
[n_var_parts
], 0)) == REG
2166 && rtx_equal_p (XEXP (loc
[n_var_parts
], 0),
2167 XEXP (XEXP (loc2
, 0), 0))
2168 && INTVAL (XEXP (XEXP (loc2
, 0), 1))
2169 == GET_MODE_SIZE (mode
))
2170 || (GET_CODE (XEXP (loc
[n_var_parts
], 0)) == PLUS
2171 && GET_CODE (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2173 && rtx_equal_p (XEXP (XEXP (loc
[n_var_parts
], 0), 0),
2174 XEXP (XEXP (loc2
, 0), 0))
2175 && INTVAL (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2176 + GET_MODE_SIZE (mode
)
2177 == INTVAL (XEXP (XEXP (loc2
, 0), 1))))
2178 new_loc
= adjust_address_nv (loc
[n_var_parts
],
2184 loc
[n_var_parts
] = new_loc
;
2186 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2192 type_size_unit
= TYPE_SIZE_UNIT (TREE_TYPE (var
->decl
));
2193 if ((unsigned HOST_WIDE_INT
) last_limit
< TREE_INT_CST_LOW (type_size_unit
))
2196 if (where
== EMIT_NOTE_AFTER_INSN
)
2197 note
= emit_note_after (NOTE_INSN_VAR_LOCATION
, insn
);
2199 note
= emit_note_before (NOTE_INSN_VAR_LOCATION
, insn
);
2203 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2206 else if (n_var_parts
== 1)
2209 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[0], GEN_INT (offsets
[0]));
2211 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2214 else if (n_var_parts
)
2218 for (i
= 0; i
< n_var_parts
; i
++)
2220 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[i
], GEN_INT (offsets
[i
]));
2222 parallel
= gen_rtx_PARALLEL (VOIDmode
,
2223 gen_rtvec_v (n_var_parts
, loc
));
2224 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2228 htab_clear_slot (changed_variables
, varp
);
2230 /* When there are no location parts the variable has been already
2231 removed from hash table and a new empty variable was created.
2232 Free the empty variable. */
2233 if (var
->n_var_parts
== 0)
2235 pool_free (var_pool
, var
);
2238 /* Continue traversing the hash table. */
2242 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
2243 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
2244 shall be emitted before of after instruction INSN. */
2247 emit_notes_for_changes (rtx insn
, enum emit_note_where where
)
2249 emit_note_data data
;
2253 htab_traverse (changed_variables
, emit_note_insn_var_location
, &data
);
2256 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
2257 same variable in hash table DATA or is not there at all. */
2260 emit_notes_for_differences_1 (void **slot
, void *data
)
2262 htab_t new_vars
= (htab_t
) data
;
2263 variable old_var
, new_var
;
2265 old_var
= *(variable
*) slot
;
2266 new_var
= htab_find_with_hash (new_vars
, old_var
->decl
,
2267 VARIABLE_HASH_VAL (old_var
->decl
));
2271 /* Variable has disappeared. */
2274 empty_var
= pool_alloc (var_pool
);
2275 empty_var
->decl
= old_var
->decl
;
2276 empty_var
->refcount
= 1;
2277 empty_var
->n_var_parts
= 0;
2278 variable_was_changed (empty_var
, NULL
);
2280 else if (variable_different_p (old_var
, new_var
, true))
2282 variable_was_changed (new_var
, NULL
);
2285 /* Continue traversing the hash table. */
2289 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2293 emit_notes_for_differences_2 (void **slot
, void *data
)
2295 htab_t old_vars
= (htab_t
) data
;
2296 variable old_var
, new_var
;
2298 new_var
= *(variable
*) slot
;
2299 old_var
= htab_find_with_hash (old_vars
, new_var
->decl
,
2300 VARIABLE_HASH_VAL (new_var
->decl
));
2303 /* Variable has appeared. */
2304 variable_was_changed (new_var
, NULL
);
2307 /* Continue traversing the hash table. */
2311 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2315 emit_notes_for_differences (rtx insn
, dataflow_set
*old_set
,
2316 dataflow_set
*new_set
)
2318 htab_traverse (old_set
->vars
, emit_notes_for_differences_1
, new_set
->vars
);
2319 htab_traverse (new_set
->vars
, emit_notes_for_differences_2
, old_set
->vars
);
2320 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2323 /* Emit the notes for changes of location parts in the basic block BB. */
2326 emit_notes_in_bb (basic_block bb
)
2331 dataflow_set_init (&set
, htab_elements (VTI (bb
)->in
.vars
) + 3);
2332 dataflow_set_copy (&set
, &VTI (bb
)->in
);
2334 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
2336 rtx insn
= VTI (bb
)->mos
[i
].insn
;
2338 switch (VTI (bb
)->mos
[i
].type
)
2344 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
2345 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
2347 var_regno_delete (&set
, r
);
2349 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2356 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2359 var_reg_delete_and_set (&set
, loc
);
2361 var_mem_delete_and_set (&set
, loc
);
2363 if (VTI (bb
)->mos
[i
].type
== MO_USE
)
2364 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2366 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2373 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2376 var_reg_delete (&set
, loc
);
2378 var_mem_delete (&set
, loc
);
2380 if (VTI (bb
)->mos
[i
].type
== MO_USE_NO_VAR
)
2381 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2383 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2388 set
.stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
2392 dataflow_set_destroy (&set
);
2395 /* Emit notes for the whole function. */
2398 vt_emit_notes (void)
2401 dataflow_set
*last_out
;
2404 gcc_assert (!htab_elements (changed_variables
));
2406 /* Enable emitting notes by functions (mainly by set_variable_part and
2407 delete_variable_part). */
2410 dataflow_set_init (&empty
, 7);
2415 /* Emit the notes for changes of variable locations between two
2416 subsequent basic blocks. */
2417 emit_notes_for_differences (BB_HEAD (bb
), last_out
, &VTI (bb
)->in
);
2419 /* Emit the notes for the changes in the basic block itself. */
2420 emit_notes_in_bb (bb
);
2422 last_out
= &VTI (bb
)->out
;
2424 dataflow_set_destroy (&empty
);
2428 /* If there is a declaration and offset associated with register/memory RTL
2429 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
2432 vt_get_decl_and_offset (rtx rtl
, tree
*declp
, HOST_WIDE_INT
*offsetp
)
2436 if (REG_ATTRS (rtl
))
2438 *declp
= REG_EXPR (rtl
);
2439 *offsetp
= REG_OFFSET (rtl
);
2443 else if (MEM_P (rtl
))
2445 if (MEM_ATTRS (rtl
))
2447 *declp
= MEM_EXPR (rtl
);
2448 *offsetp
= MEM_OFFSET (rtl
) ? INTVAL (MEM_OFFSET (rtl
)) : 0;
2455 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
2458 vt_add_function_parameters (void)
2462 for (parm
= DECL_ARGUMENTS (current_function_decl
);
2463 parm
; parm
= TREE_CHAIN (parm
))
2465 rtx decl_rtl
= DECL_RTL_IF_SET (parm
);
2466 rtx incoming
= DECL_INCOMING_RTL (parm
);
2468 HOST_WIDE_INT offset
;
2471 if (TREE_CODE (parm
) != PARM_DECL
)
2474 if (!DECL_NAME (parm
))
2477 if (!decl_rtl
|| !incoming
)
2480 if (GET_MODE (decl_rtl
) == BLKmode
|| GET_MODE (incoming
) == BLKmode
)
2483 if (!vt_get_decl_and_offset (incoming
, &decl
, &offset
))
2484 if (!vt_get_decl_and_offset (decl_rtl
, &decl
, &offset
))
2490 gcc_assert (parm
== decl
);
2492 out
= &VTI (ENTRY_BLOCK_PTR
)->out
;
2494 if (REG_P (incoming
))
2496 gcc_assert (REGNO (incoming
) < FIRST_PSEUDO_REGISTER
);
2497 attrs_list_insert (&out
->regs
[REGNO (incoming
)],
2498 parm
, offset
, incoming
);
2499 set_variable_part (out
, incoming
, parm
, offset
);
2501 else if (MEM_P (incoming
))
2502 set_variable_part (out
, incoming
, parm
, offset
);
2506 /* Allocate and initialize the data structures for variable tracking
2507 and parse the RTL to get the micro operations. */
2510 vt_initialize (void)
2514 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def
));
2519 HOST_WIDE_INT pre
, post
;
2521 /* Count the number of micro operations. */
2522 VTI (bb
)->n_mos
= 0;
2523 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
2524 insn
= NEXT_INSN (insn
))
2528 if (!frame_pointer_needed
)
2530 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
2536 note_uses (&PATTERN (insn
), count_uses_1
, insn
);
2537 note_stores (PATTERN (insn
), count_stores
, insn
);
2543 /* Add the micro-operations to the array. */
2544 VTI (bb
)->mos
= xmalloc (VTI (bb
)->n_mos
2545 * sizeof (struct micro_operation_def
));
2546 VTI (bb
)->n_mos
= 0;
2547 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
2548 insn
= NEXT_INSN (insn
))
2554 if (!frame_pointer_needed
)
2556 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
2559 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2561 mo
->type
= MO_ADJUST
;
2567 n1
= VTI (bb
)->n_mos
;
2568 note_uses (&PATTERN (insn
), add_uses_1
, insn
);
2569 n2
= VTI (bb
)->n_mos
- 1;
2571 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
2574 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_USE
)
2576 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_USE_NO_VAR
)
2582 sw
= VTI (bb
)->mos
[n1
];
2583 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
2584 VTI (bb
)->mos
[n2
] = sw
;
2590 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2596 n1
= VTI (bb
)->n_mos
;
2597 note_stores (PATTERN (insn
), add_stores
, insn
);
2598 n2
= VTI (bb
)->n_mos
- 1;
2600 /* Order the MO_SETs to be before MO_CLOBBERs. */
2603 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_SET
)
2605 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_CLOBBER
)
2611 sw
= VTI (bb
)->mos
[n1
];
2612 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
2613 VTI (bb
)->mos
[n2
] = sw
;
2617 if (!frame_pointer_needed
&& post
)
2619 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2621 mo
->type
= MO_ADJUST
;
2622 mo
->u
.adjust
= post
;
2629 /* Init the IN and OUT sets. */
2632 VTI (bb
)->visited
= false;
2633 dataflow_set_init (&VTI (bb
)->in
, 7);
2634 dataflow_set_init (&VTI (bb
)->out
, 7);
2637 attrs_pool
= create_alloc_pool ("attrs_def pool",
2638 sizeof (struct attrs_def
), 1024);
2639 var_pool
= create_alloc_pool ("variable_def pool",
2640 sizeof (struct variable_def
), 64);
2641 loc_chain_pool
= create_alloc_pool ("location_chain_def pool",
2642 sizeof (struct location_chain_def
),
2644 changed_variables
= htab_create (10, variable_htab_hash
, variable_htab_eq
,
2646 vt_add_function_parameters ();
2649 /* Free the data structures needed for variable tracking. */
2658 free (VTI (bb
)->mos
);
2663 dataflow_set_destroy (&VTI (bb
)->in
);
2664 dataflow_set_destroy (&VTI (bb
)->out
);
2666 free_aux_for_blocks ();
2667 free_alloc_pool (attrs_pool
);
2668 free_alloc_pool (var_pool
);
2669 free_alloc_pool (loc_chain_pool
);
2670 htab_delete (changed_variables
);
2673 /* The entry point to variable tracking pass. */
2676 variable_tracking_main (void)
2678 if (n_basic_blocks
> 500 && n_edges
/ n_basic_blocks
>= 20)
2681 mark_dfs_back_edges ();
2683 if (!frame_pointer_needed
)
2685 if (!vt_stack_adjustments ())
2692 vt_find_locations ();
2697 dump_dataflow_sets ();
2698 dump_flow_info (dump_file
);
2705 gate_handle_var_tracking (void)
2707 return (flag_var_tracking
);
2712 struct tree_opt_pass pass_variable_tracking
=
2714 "vartrack", /* name */
2715 gate_handle_var_tracking
, /* gate */
2716 variable_tracking_main
, /* execute */
2719 0, /* static_pass_number */
2720 TV_VAR_TRACKING
, /* tv_id */
2721 0, /* properties_required */
2722 0, /* properties_provided */
2723 0, /* properties_destroyed */
2724 0, /* todo_flags_start */
2725 TODO_dump_func
, /* todo_flags_finish */