1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This file contains the variable tracking pass. It computes where
21 variables are located (which registers or where in memory) at each position
22 in instruction stream and emits notes describing the locations.
23 Debug information (DWARF2 location lists) is finally generated from
25 With this debug information, it is possible to show variables
26 even when debugging optimized code.
28 How does the variable tracking pass work?
30 First, it scans RTL code for uses, stores and clobbers (register/memory
31 references in instructions), for call insns and for stack adjustments
32 separately for each basic block and saves them to an array of micro
34 The micro operations of one instruction are ordered so that
35 pre-modifying stack adjustment < use < use with no var < call insn <
36 < set < clobber < post-modifying stack adjustment
38 Then, a forward dataflow analysis is performed to find out how locations
39 of variables change through code and to propagate the variable locations
40 along control flow graph.
41 The IN set for basic block BB is computed as a union of OUT sets of BB's
42 predecessors, the OUT set for BB is copied from the IN set for BB and
43 is changed according to micro operations in BB.
45 The IN and OUT sets for basic blocks consist of a current stack adjustment
46 (used for adjusting offset of variables addressed using stack pointer),
47 the table of structures describing the locations of parts of a variable
48 and for each physical register a linked list for each physical register.
49 The linked list is a list of variable parts stored in the register,
50 i.e. it is a list of triplets (reg, decl, offset) where decl is
51 REG_EXPR (reg) and offset is REG_OFFSET (reg). The linked list is used for
52 effective deleting appropriate variable parts when we set or clobber the
55 There may be more than one variable part in a register. The linked lists
56 should be pretty short so it is a good data structure here.
57 For example in the following code, register allocator may assign same
58 register to variables A and B, and both of them are stored in the same
71 Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
72 are emitted to appropriate positions in RTL code. Each such a note describes
73 the location of one variable at the point in instruction stream where the
74 note is. There is no need to emit a note for each variable before each
75 instruction, we only emit these notes where the location of variable changes
76 (this means that we also emit notes for changes between the OUT set of the
77 previous block and the IN set of the current block).
79 The notes consist of two parts:
80 1. the declaration (from REG_EXPR or MEM_EXPR)
81 2. the location of a variable - it is either a simple register/memory
82 reference (for simple variables, for example int),
83 or a parallel of register/memory references (for a large variables
84 which consist of several parts, for example long long).
90 #include "coretypes.h"
94 #include "hard-reg-set.h"
95 #include "basic-block.h"
98 #include "insn-config.h"
101 #include "alloc-pool.h"
107 #include "tree-pass.h"
109 /* Type of micro operation. */
110 enum micro_operation_type
112 MO_USE
, /* Use location (REG or MEM). */
113 MO_USE_NO_VAR
,/* Use location which is not associated with a variable
114 or the variable is not trackable. */
115 MO_SET
, /* Set location. */
116 MO_COPY
, /* Copy the same portion of a variable from one
117 location to another. */
118 MO_CLOBBER
, /* Clobber location. */
119 MO_CALL
, /* Call insn. */
120 MO_ADJUST
/* Adjust stack pointer. */
123 /* Where shall the note be emitted? BEFORE or AFTER the instruction. */
126 EMIT_NOTE_BEFORE_INSN
,
130 /* Structure holding information about micro operation. */
131 typedef struct micro_operation_def
133 /* Type of micro operation. */
134 enum micro_operation_type type
;
140 /* Stack adjustment. */
141 HOST_WIDE_INT adjust
;
144 /* The instruction which the micro operation is in, for MO_USE,
145 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
146 instruction or note in the original flow (before any var-tracking
147 notes are inserted, to simplify emission of notes), for MO_SET
152 /* Structure for passing some other parameters to function
153 emit_note_insn_var_location. */
154 typedef struct emit_note_data_def
156 /* The instruction which the note will be emitted before/after. */
159 /* Where the note will be emitted (before/after insn)? */
160 enum emit_note_where where
;
163 /* Description of location of a part of a variable. The content of a physical
164 register is described by a chain of these structures.
165 The chains are pretty short (usually 1 or 2 elements) and thus
166 chain is the best data structure. */
167 typedef struct attrs_def
169 /* Pointer to next member of the list. */
170 struct attrs_def
*next
;
172 /* The rtx of register. */
175 /* The declaration corresponding to LOC. */
178 /* Offset from start of DECL. */
179 HOST_WIDE_INT offset
;
182 /* Structure holding the IN or OUT set for a basic block. */
183 typedef struct dataflow_set_def
185 /* Adjustment of stack offset. */
186 HOST_WIDE_INT stack_adjust
;
188 /* Attributes for registers (lists of attrs). */
189 attrs regs
[FIRST_PSEUDO_REGISTER
];
191 /* Variable locations. */
195 /* The structure (one for each basic block) containing the information
196 needed for variable tracking. */
197 typedef struct variable_tracking_info_def
199 /* Number of micro operations stored in the MOS array. */
202 /* The array of micro operations. */
203 micro_operation
*mos
;
205 /* The IN and OUT set for dataflow analysis. */
209 /* Has the block been visited in DFS? */
211 } *variable_tracking_info
;
213 /* Structure for chaining the locations. */
214 typedef struct location_chain_def
216 /* Next element in the chain. */
217 struct location_chain_def
*next
;
219 /* The location (REG or MEM). */
223 /* Structure describing one part of variable. */
224 typedef struct variable_part_def
226 /* Chain of locations of the part. */
227 location_chain loc_chain
;
229 /* Location which was last emitted to location list. */
232 /* The offset in the variable. */
233 HOST_WIDE_INT offset
;
236 /* Maximum number of location parts. */
237 #define MAX_VAR_PARTS 16
239 /* Structure describing where the variable is located. */
240 typedef struct variable_def
242 /* The declaration of the variable. */
245 /* Reference count. */
248 /* Number of variable parts. */
251 /* The variable parts. */
252 variable_part var_part
[MAX_VAR_PARTS
];
255 /* Hash function for DECL for VARIABLE_HTAB. */
256 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
258 /* Pointer to the BB's information specific to variable tracking pass. */
259 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
261 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
262 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
264 /* Alloc pool for struct attrs_def. */
265 static alloc_pool attrs_pool
;
267 /* Alloc pool for struct variable_def. */
268 static alloc_pool var_pool
;
270 /* Alloc pool for struct location_chain_def. */
271 static alloc_pool loc_chain_pool
;
273 /* Changed variables, notes will be emitted for them. */
274 static htab_t changed_variables
;
276 /* Shall notes be emitted? */
277 static bool emit_notes
;
279 /* Local function prototypes. */
280 static void stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
282 static void insn_stack_adjust_offset_pre_post (rtx
, HOST_WIDE_INT
*,
284 static void bb_stack_adjust_offset (basic_block
);
285 static bool vt_stack_adjustments (void);
286 static rtx
adjust_stack_reference (rtx
, HOST_WIDE_INT
);
287 static hashval_t
variable_htab_hash (const void *);
288 static int variable_htab_eq (const void *, const void *);
289 static void variable_htab_free (void *);
291 static void init_attrs_list_set (attrs
*);
292 static void attrs_list_clear (attrs
*);
293 static attrs
attrs_list_member (attrs
, tree
, HOST_WIDE_INT
);
294 static void attrs_list_insert (attrs
*, tree
, HOST_WIDE_INT
, rtx
);
295 static void attrs_list_copy (attrs
*, attrs
);
296 static void attrs_list_union (attrs
*, attrs
);
298 static void vars_clear (htab_t
);
299 static variable
unshare_variable (dataflow_set
*set
, variable var
);
300 static int vars_copy_1 (void **, void *);
301 static void vars_copy (htab_t
, htab_t
);
302 static tree
var_debug_decl (tree
);
303 static void var_reg_set (dataflow_set
*, rtx
);
304 static void var_reg_delete_and_set (dataflow_set
*, rtx
, bool);
305 static void var_reg_delete (dataflow_set
*, rtx
, bool);
306 static void var_regno_delete (dataflow_set
*, int);
307 static void var_mem_set (dataflow_set
*, rtx
);
308 static void var_mem_delete_and_set (dataflow_set
*, rtx
, bool);
309 static void var_mem_delete (dataflow_set
*, rtx
, bool);
311 static void dataflow_set_init (dataflow_set
*, int);
312 static void dataflow_set_clear (dataflow_set
*);
313 static void dataflow_set_copy (dataflow_set
*, dataflow_set
*);
314 static int variable_union_info_cmp_pos (const void *, const void *);
315 static int variable_union (void **, void *);
316 static void dataflow_set_union (dataflow_set
*, dataflow_set
*);
317 static bool variable_part_different_p (variable_part
*, variable_part
*);
318 static bool variable_different_p (variable
, variable
, bool);
319 static int dataflow_set_different_1 (void **, void *);
320 static int dataflow_set_different_2 (void **, void *);
321 static bool dataflow_set_different (dataflow_set
*, dataflow_set
*);
322 static void dataflow_set_destroy (dataflow_set
*);
324 static bool contains_symbol_ref (rtx
);
325 static bool track_expr_p (tree
);
326 static bool same_variable_part_p (rtx
, tree
, HOST_WIDE_INT
);
327 static int count_uses (rtx
*, void *);
328 static void count_uses_1 (rtx
*, void *);
329 static void count_stores (rtx
, rtx
, void *);
330 static int add_uses (rtx
*, void *);
331 static void add_uses_1 (rtx
*, void *);
332 static void add_stores (rtx
, rtx
, void *);
333 static bool compute_bb_dataflow (basic_block
);
334 static void vt_find_locations (void);
336 static void dump_attrs_list (attrs
);
337 static int dump_variable (void **, void *);
338 static void dump_vars (htab_t
);
339 static void dump_dataflow_set (dataflow_set
*);
340 static void dump_dataflow_sets (void);
342 static void variable_was_changed (variable
, htab_t
);
343 static void set_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
344 static void clobber_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
345 static void delete_variable_part (dataflow_set
*, rtx
, tree
, HOST_WIDE_INT
);
346 static int emit_note_insn_var_location (void **, void *);
347 static void emit_notes_for_changes (rtx
, enum emit_note_where
);
348 static int emit_notes_for_differences_1 (void **, void *);
349 static int emit_notes_for_differences_2 (void **, void *);
350 static void emit_notes_for_differences (rtx
, dataflow_set
*, dataflow_set
*);
351 static void emit_notes_in_bb (basic_block
);
352 static void vt_emit_notes (void);
354 static bool vt_get_decl_and_offset (rtx
, tree
*, HOST_WIDE_INT
*);
355 static void vt_add_function_parameters (void);
356 static void vt_initialize (void);
357 static void vt_finalize (void);
359 /* Given a SET, calculate the amount of stack adjustment it contains
360 PRE- and POST-modifying stack pointer.
361 This function is similar to stack_adjust_offset. */
364 stack_adjust_offset_pre_post (rtx pattern
, HOST_WIDE_INT
*pre
,
367 rtx src
= SET_SRC (pattern
);
368 rtx dest
= SET_DEST (pattern
);
371 if (dest
== stack_pointer_rtx
)
373 /* (set (reg sp) (plus (reg sp) (const_int))) */
374 code
= GET_CODE (src
);
375 if (! (code
== PLUS
|| code
== MINUS
)
376 || XEXP (src
, 0) != stack_pointer_rtx
377 || GET_CODE (XEXP (src
, 1)) != CONST_INT
)
381 *post
+= INTVAL (XEXP (src
, 1));
383 *post
-= INTVAL (XEXP (src
, 1));
385 else if (MEM_P (dest
))
387 /* (set (mem (pre_dec (reg sp))) (foo)) */
388 src
= XEXP (dest
, 0);
389 code
= GET_CODE (src
);
395 if (XEXP (src
, 0) == stack_pointer_rtx
)
397 rtx val
= XEXP (XEXP (src
, 1), 1);
398 /* We handle only adjustments by constant amount. */
399 gcc_assert (GET_CODE (XEXP (src
, 1)) == PLUS
&&
400 GET_CODE (val
) == CONST_INT
);
402 if (code
== PRE_MODIFY
)
403 *pre
-= INTVAL (val
);
405 *post
-= INTVAL (val
);
411 if (XEXP (src
, 0) == stack_pointer_rtx
)
413 *pre
+= GET_MODE_SIZE (GET_MODE (dest
));
419 if (XEXP (src
, 0) == stack_pointer_rtx
)
421 *post
+= GET_MODE_SIZE (GET_MODE (dest
));
427 if (XEXP (src
, 0) == stack_pointer_rtx
)
429 *pre
-= GET_MODE_SIZE (GET_MODE (dest
));
435 if (XEXP (src
, 0) == stack_pointer_rtx
)
437 *post
-= GET_MODE_SIZE (GET_MODE (dest
));
448 /* Given an INSN, calculate the amount of stack adjustment it contains
449 PRE- and POST-modifying stack pointer. */
452 insn_stack_adjust_offset_pre_post (rtx insn
, HOST_WIDE_INT
*pre
,
458 if (GET_CODE (PATTERN (insn
)) == SET
)
459 stack_adjust_offset_pre_post (PATTERN (insn
), pre
, post
);
460 else if (GET_CODE (PATTERN (insn
)) == PARALLEL
461 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
465 /* There may be stack adjustments inside compound insns. Search
467 for ( i
= XVECLEN (PATTERN (insn
), 0) - 1; i
>= 0; i
--)
468 if (GET_CODE (XVECEXP (PATTERN (insn
), 0, i
)) == SET
)
469 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn
), 0, i
),
474 /* Compute stack adjustment in basic block BB. */
477 bb_stack_adjust_offset (basic_block bb
)
479 HOST_WIDE_INT offset
;
482 offset
= VTI (bb
)->in
.stack_adjust
;
483 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
485 if (VTI (bb
)->mos
[i
].type
== MO_ADJUST
)
486 offset
+= VTI (bb
)->mos
[i
].u
.adjust
;
487 else if (VTI (bb
)->mos
[i
].type
!= MO_CALL
)
489 if (MEM_P (VTI (bb
)->mos
[i
].u
.loc
))
491 VTI (bb
)->mos
[i
].u
.loc
492 = adjust_stack_reference (VTI (bb
)->mos
[i
].u
.loc
, -offset
);
496 VTI (bb
)->out
.stack_adjust
= offset
;
499 /* Compute stack adjustments for all blocks by traversing DFS tree.
500 Return true when the adjustments on all incoming edges are consistent.
501 Heavily borrowed from pre_and_rev_post_order_compute. */
504 vt_stack_adjustments (void)
506 edge_iterator
*stack
;
509 /* Initialize entry block. */
510 VTI (ENTRY_BLOCK_PTR
)->visited
= true;
511 VTI (ENTRY_BLOCK_PTR
)->out
.stack_adjust
= INCOMING_FRAME_SP_OFFSET
;
513 /* Allocate stack for back-tracking up CFG. */
514 stack
= XNEWVEC (edge_iterator
, n_basic_blocks
+ 1);
517 /* Push the first edge on to the stack. */
518 stack
[sp
++] = ei_start (ENTRY_BLOCK_PTR
->succs
);
526 /* Look at the edge on the top of the stack. */
528 src
= ei_edge (ei
)->src
;
529 dest
= ei_edge (ei
)->dest
;
531 /* Check if the edge destination has been visited yet. */
532 if (!VTI (dest
)->visited
)
534 VTI (dest
)->visited
= true;
535 VTI (dest
)->in
.stack_adjust
= VTI (src
)->out
.stack_adjust
;
536 bb_stack_adjust_offset (dest
);
538 if (EDGE_COUNT (dest
->succs
) > 0)
539 /* Since the DEST node has been visited for the first
540 time, check its successors. */
541 stack
[sp
++] = ei_start (dest
->succs
);
545 /* Check whether the adjustments on the edges are the same. */
546 if (VTI (dest
)->in
.stack_adjust
!= VTI (src
)->out
.stack_adjust
)
552 if (! ei_one_before_end_p (ei
))
553 /* Go to the next edge. */
554 ei_next (&stack
[sp
- 1]);
556 /* Return to previous level if there are no more edges. */
565 /* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative
566 to the argument pointer. Return the new rtx. */
569 adjust_stack_reference (rtx mem
, HOST_WIDE_INT adjustment
)
573 #ifdef FRAME_POINTER_CFA_OFFSET
574 adjustment
-= FRAME_POINTER_CFA_OFFSET (current_function_decl
);
575 cfa
= plus_constant (frame_pointer_rtx
, adjustment
);
577 adjustment
-= ARG_POINTER_CFA_OFFSET (current_function_decl
);
578 cfa
= plus_constant (arg_pointer_rtx
, adjustment
);
581 addr
= replace_rtx (copy_rtx (XEXP (mem
, 0)), stack_pointer_rtx
, cfa
);
582 tmp
= simplify_rtx (addr
);
586 return replace_equiv_address_nv (mem
, addr
);
589 /* The hash function for variable_htab, computes the hash value
590 from the declaration of variable X. */
593 variable_htab_hash (const void *x
)
595 const variable v
= (const variable
) x
;
597 return (VARIABLE_HASH_VAL (v
->decl
));
600 /* Compare the declaration of variable X with declaration Y. */
603 variable_htab_eq (const void *x
, const void *y
)
605 const variable v
= (const variable
) x
;
606 const tree decl
= (const tree
) y
;
608 return (VARIABLE_HASH_VAL (v
->decl
) == VARIABLE_HASH_VAL (decl
));
611 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
614 variable_htab_free (void *elem
)
617 variable var
= (variable
) elem
;
618 location_chain node
, next
;
620 gcc_assert (var
->refcount
> 0);
623 if (var
->refcount
> 0)
626 for (i
= 0; i
< var
->n_var_parts
; i
++)
628 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= next
)
631 pool_free (loc_chain_pool
, node
);
633 var
->var_part
[i
].loc_chain
= NULL
;
635 pool_free (var_pool
, var
);
638 /* Initialize the set (array) SET of attrs to empty lists. */
641 init_attrs_list_set (attrs
*set
)
645 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
649 /* Make the list *LISTP empty. */
652 attrs_list_clear (attrs
*listp
)
656 for (list
= *listp
; list
; list
= next
)
659 pool_free (attrs_pool
, list
);
664 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
667 attrs_list_member (attrs list
, tree decl
, HOST_WIDE_INT offset
)
669 for (; list
; list
= list
->next
)
670 if (list
->decl
== decl
&& list
->offset
== offset
)
675 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
678 attrs_list_insert (attrs
*listp
, tree decl
, HOST_WIDE_INT offset
, rtx loc
)
682 list
= pool_alloc (attrs_pool
);
685 list
->offset
= offset
;
690 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
693 attrs_list_copy (attrs
*dstp
, attrs src
)
697 attrs_list_clear (dstp
);
698 for (; src
; src
= src
->next
)
700 n
= pool_alloc (attrs_pool
);
703 n
->offset
= src
->offset
;
709 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
712 attrs_list_union (attrs
*dstp
, attrs src
)
714 for (; src
; src
= src
->next
)
716 if (!attrs_list_member (*dstp
, src
->decl
, src
->offset
))
717 attrs_list_insert (dstp
, src
->decl
, src
->offset
, src
->loc
);
721 /* Delete all variables from hash table VARS. */
724 vars_clear (htab_t vars
)
729 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
732 unshare_variable (dataflow_set
*set
, variable var
)
738 new_var
= pool_alloc (var_pool
);
739 new_var
->decl
= var
->decl
;
740 new_var
->refcount
= 1;
742 new_var
->n_var_parts
= var
->n_var_parts
;
744 for (i
= 0; i
< var
->n_var_parts
; i
++)
747 location_chain
*nextp
;
749 new_var
->var_part
[i
].offset
= var
->var_part
[i
].offset
;
750 nextp
= &new_var
->var_part
[i
].loc_chain
;
751 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
753 location_chain new_lc
;
755 new_lc
= pool_alloc (loc_chain_pool
);
757 new_lc
->loc
= node
->loc
;
760 nextp
= &new_lc
->next
;
763 /* We are at the basic block boundary when copying variable description
764 so set the CUR_LOC to be the first element of the chain. */
765 if (new_var
->var_part
[i
].loc_chain
)
766 new_var
->var_part
[i
].cur_loc
= new_var
->var_part
[i
].loc_chain
->loc
;
768 new_var
->var_part
[i
].cur_loc
= NULL
;
771 slot
= htab_find_slot_with_hash (set
->vars
, new_var
->decl
,
772 VARIABLE_HASH_VAL (new_var
->decl
),
778 /* Add a variable from *SLOT to hash table DATA and increase its reference
782 vars_copy_1 (void **slot
, void *data
)
784 htab_t dst
= (htab_t
) data
;
787 src
= *(variable
*) slot
;
790 dstp
= (variable
*) htab_find_slot_with_hash (dst
, src
->decl
,
791 VARIABLE_HASH_VAL (src
->decl
),
795 /* Continue traversing the hash table. */
799 /* Copy all variables from hash table SRC to hash table DST. */
802 vars_copy (htab_t dst
, htab_t src
)
805 htab_traverse (src
, vars_copy_1
, dst
);
808 /* Map a decl to its main debug decl. */
811 var_debug_decl (tree decl
)
813 if (decl
&& DECL_P (decl
)
814 && DECL_DEBUG_EXPR_IS_FROM (decl
) && DECL_DEBUG_EXPR (decl
)
815 && DECL_P (DECL_DEBUG_EXPR (decl
)))
816 decl
= DECL_DEBUG_EXPR (decl
);
821 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
824 var_reg_set (dataflow_set
*set
, rtx loc
)
826 tree decl
= REG_EXPR (loc
);
827 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
830 decl
= var_debug_decl (decl
);
832 for (node
= set
->regs
[REGNO (loc
)]; node
; node
= node
->next
)
833 if (node
->decl
== decl
&& node
->offset
== offset
)
836 attrs_list_insert (&set
->regs
[REGNO (loc
)], decl
, offset
, loc
);
837 set_variable_part (set
, loc
, decl
, offset
);
840 /* Delete current content of register LOC in dataflow set SET and set
841 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
842 MODIFY is true, any other live copies of the same variable part are
843 also deleted from the dataflow set, otherwise the variable part is
844 assumed to be copied from another location holding the same
848 var_reg_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
)
850 tree decl
= REG_EXPR (loc
);
851 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
855 decl
= var_debug_decl (decl
);
857 nextp
= &set
->regs
[REGNO (loc
)];
858 for (node
= *nextp
; node
; node
= next
)
861 if (node
->decl
!= decl
|| node
->offset
!= offset
)
863 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
864 pool_free (attrs_pool
, node
);
874 clobber_variable_part (set
, loc
, decl
, offset
);
875 var_reg_set (set
, loc
);
878 /* Delete current content of register LOC in dataflow set SET. If
879 CLOBBER is true, also delete any other live copies of the same
883 var_reg_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
885 attrs
*reg
= &set
->regs
[REGNO (loc
)];
890 tree decl
= REG_EXPR (loc
);
891 HOST_WIDE_INT offset
= REG_OFFSET (loc
);
893 decl
= var_debug_decl (decl
);
895 clobber_variable_part (set
, NULL
, decl
, offset
);
898 for (node
= *reg
; node
; node
= next
)
901 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
902 pool_free (attrs_pool
, node
);
907 /* Delete content of register with number REGNO in dataflow set SET. */
910 var_regno_delete (dataflow_set
*set
, int regno
)
912 attrs
*reg
= &set
->regs
[regno
];
915 for (node
= *reg
; node
; node
= next
)
918 delete_variable_part (set
, node
->loc
, node
->decl
, node
->offset
);
919 pool_free (attrs_pool
, node
);
924 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
926 Adjust the address first if it is stack pointer based. */
929 var_mem_set (dataflow_set
*set
, rtx loc
)
931 tree decl
= MEM_EXPR (loc
);
932 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
934 decl
= var_debug_decl (decl
);
936 set_variable_part (set
, loc
, decl
, offset
);
939 /* Delete and set the location part of variable MEM_EXPR (LOC) in
940 dataflow set SET to LOC. If MODIFY is true, any other live copies
941 of the same variable part are also deleted from the dataflow set,
942 otherwise the variable part is assumed to be copied from another
943 location holding the same part.
944 Adjust the address first if it is stack pointer based. */
947 var_mem_delete_and_set (dataflow_set
*set
, rtx loc
, bool modify
)
949 tree decl
= MEM_EXPR (loc
);
950 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
952 decl
= var_debug_decl (decl
);
955 clobber_variable_part (set
, NULL
, decl
, offset
);
956 var_mem_set (set
, loc
);
959 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
960 true, also delete any other live copies of the same variable part.
961 Adjust the address first if it is stack pointer based. */
964 var_mem_delete (dataflow_set
*set
, rtx loc
, bool clobber
)
966 tree decl
= MEM_EXPR (loc
);
967 HOST_WIDE_INT offset
= INT_MEM_OFFSET (loc
);
969 decl
= var_debug_decl (decl
);
971 clobber_variable_part (set
, NULL
, decl
, offset
);
972 delete_variable_part (set
, loc
, decl
, offset
);
975 /* Initialize dataflow set SET to be empty.
976 VARS_SIZE is the initial size of hash table VARS. */
979 dataflow_set_init (dataflow_set
*set
, int vars_size
)
981 init_attrs_list_set (set
->regs
);
982 set
->vars
= htab_create (vars_size
, variable_htab_hash
, variable_htab_eq
,
984 set
->stack_adjust
= 0;
987 /* Delete the contents of dataflow set SET. */
990 dataflow_set_clear (dataflow_set
*set
)
994 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
995 attrs_list_clear (&set
->regs
[i
]);
997 vars_clear (set
->vars
);
1000 /* Copy the contents of dataflow set SRC to DST. */
1003 dataflow_set_copy (dataflow_set
*dst
, dataflow_set
*src
)
1007 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1008 attrs_list_copy (&dst
->regs
[i
], src
->regs
[i
]);
1010 vars_copy (dst
->vars
, src
->vars
);
1011 dst
->stack_adjust
= src
->stack_adjust
;
1014 /* Information for merging lists of locations for a given offset of variable.
1016 struct variable_union_info
1018 /* Node of the location chain. */
1021 /* The sum of positions in the input chains. */
1024 /* The position in the chains of SRC and DST dataflow sets. */
1029 /* Compare function for qsort, order the structures by POS element. */
1032 variable_union_info_cmp_pos (const void *n1
, const void *n2
)
1034 const struct variable_union_info
*i1
= n1
;
1035 const struct variable_union_info
*i2
= n2
;
1037 if (i1
->pos
!= i2
->pos
)
1038 return i1
->pos
- i2
->pos
;
1040 return (i1
->pos_dst
- i2
->pos_dst
);
1043 /* Compute union of location parts of variable *SLOT and the same variable
1044 from hash table DATA. Compute "sorted" union of the location chains
1045 for common offsets, i.e. the locations of a variable part are sorted by
1046 a priority where the priority is the sum of the positions in the 2 chains
1047 (if a location is only in one list the position in the second list is
1048 defined to be larger than the length of the chains).
1049 When we are updating the location parts the newest location is in the
1050 beginning of the chain, so when we do the described "sorted" union
1051 we keep the newest locations in the beginning. */
1054 variable_union (void **slot
, void *data
)
1056 variable src
, dst
, *dstp
;
1057 dataflow_set
*set
= (dataflow_set
*) data
;
1060 src
= *(variable
*) slot
;
1061 dstp
= (variable
*) htab_find_slot_with_hash (set
->vars
, src
->decl
,
1062 VARIABLE_HASH_VAL (src
->decl
),
1068 /* If CUR_LOC of some variable part is not the first element of
1069 the location chain we are going to change it so we have to make
1070 a copy of the variable. */
1071 for (k
= 0; k
< src
->n_var_parts
; k
++)
1073 gcc_assert (!src
->var_part
[k
].loc_chain
1074 == !src
->var_part
[k
].cur_loc
);
1075 if (src
->var_part
[k
].loc_chain
)
1077 gcc_assert (src
->var_part
[k
].cur_loc
);
1078 if (src
->var_part
[k
].cur_loc
!= src
->var_part
[k
].loc_chain
->loc
)
1082 if (k
< src
->n_var_parts
)
1083 unshare_variable (set
, src
);
1087 /* Continue traversing the hash table. */
1093 gcc_assert (src
->n_var_parts
);
1095 /* Count the number of location parts, result is K. */
1096 for (i
= 0, j
= 0, k
= 0;
1097 i
< src
->n_var_parts
&& j
< dst
->n_var_parts
; k
++)
1099 if (src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1104 else if (src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1109 k
+= src
->n_var_parts
- i
;
1110 k
+= dst
->n_var_parts
- j
;
1112 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
1113 thus there are at most MAX_VAR_PARTS different offsets. */
1114 gcc_assert (k
<= MAX_VAR_PARTS
);
1116 if (dst
->refcount
> 1 && dst
->n_var_parts
!= k
)
1117 dst
= unshare_variable (set
, dst
);
1119 i
= src
->n_var_parts
- 1;
1120 j
= dst
->n_var_parts
- 1;
1121 dst
->n_var_parts
= k
;
1123 for (k
--; k
>= 0; k
--)
1125 location_chain node
, node2
;
1127 if (i
>= 0 && j
>= 0
1128 && src
->var_part
[i
].offset
== dst
->var_part
[j
].offset
)
1130 /* Compute the "sorted" union of the chains, i.e. the locations which
1131 are in both chains go first, they are sorted by the sum of
1132 positions in the chains. */
1135 struct variable_union_info
*vui
;
1137 /* If DST is shared compare the location chains.
1138 If they are different we will modify the chain in DST with
1139 high probability so make a copy of DST. */
1140 if (dst
->refcount
> 1)
1142 for (node
= src
->var_part
[i
].loc_chain
,
1143 node2
= dst
->var_part
[j
].loc_chain
; node
&& node2
;
1144 node
= node
->next
, node2
= node2
->next
)
1146 if (!((REG_P (node2
->loc
)
1147 && REG_P (node
->loc
)
1148 && REGNO (node2
->loc
) == REGNO (node
->loc
))
1149 || rtx_equal_p (node2
->loc
, node
->loc
)))
1153 dst
= unshare_variable (set
, dst
);
1157 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1160 for (node
= dst
->var_part
[j
].loc_chain
; node
; node
= node
->next
)
1162 vui
= XCNEWVEC (struct variable_union_info
, src_l
+ dst_l
);
1164 /* Fill in the locations from DST. */
1165 for (node
= dst
->var_part
[j
].loc_chain
, jj
= 0; node
;
1166 node
= node
->next
, jj
++)
1169 vui
[jj
].pos_dst
= jj
;
1171 /* Value larger than a sum of 2 valid positions. */
1172 vui
[jj
].pos_src
= src_l
+ dst_l
;
1175 /* Fill in the locations from SRC. */
1177 for (node
= src
->var_part
[i
].loc_chain
, ii
= 0; node
;
1178 node
= node
->next
, ii
++)
1180 /* Find location from NODE. */
1181 for (jj
= 0; jj
< dst_l
; jj
++)
1183 if ((REG_P (vui
[jj
].lc
->loc
)
1184 && REG_P (node
->loc
)
1185 && REGNO (vui
[jj
].lc
->loc
) == REGNO (node
->loc
))
1186 || rtx_equal_p (vui
[jj
].lc
->loc
, node
->loc
))
1188 vui
[jj
].pos_src
= ii
;
1192 if (jj
>= dst_l
) /* The location has not been found. */
1194 location_chain new_node
;
1196 /* Copy the location from SRC. */
1197 new_node
= pool_alloc (loc_chain_pool
);
1198 new_node
->loc
= node
->loc
;
1199 vui
[n
].lc
= new_node
;
1200 vui
[n
].pos_src
= ii
;
1201 vui
[n
].pos_dst
= src_l
+ dst_l
;
1206 for (ii
= 0; ii
< src_l
+ dst_l
; ii
++)
1207 vui
[ii
].pos
= vui
[ii
].pos_src
+ vui
[ii
].pos_dst
;
1209 qsort (vui
, n
, sizeof (struct variable_union_info
),
1210 variable_union_info_cmp_pos
);
1212 /* Reconnect the nodes in sorted order. */
1213 for (ii
= 1; ii
< n
; ii
++)
1214 vui
[ii
- 1].lc
->next
= vui
[ii
].lc
;
1215 vui
[n
- 1].lc
->next
= NULL
;
1217 dst
->var_part
[k
].loc_chain
= vui
[0].lc
;
1218 dst
->var_part
[k
].offset
= dst
->var_part
[j
].offset
;
1224 else if ((i
>= 0 && j
>= 0
1225 && src
->var_part
[i
].offset
< dst
->var_part
[j
].offset
)
1228 dst
->var_part
[k
] = dst
->var_part
[j
];
1231 else if ((i
>= 0 && j
>= 0
1232 && src
->var_part
[i
].offset
> dst
->var_part
[j
].offset
)
1235 location_chain
*nextp
;
1237 /* Copy the chain from SRC. */
1238 nextp
= &dst
->var_part
[k
].loc_chain
;
1239 for (node
= src
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1241 location_chain new_lc
;
1243 new_lc
= pool_alloc (loc_chain_pool
);
1244 new_lc
->next
= NULL
;
1245 new_lc
->loc
= node
->loc
;
1248 nextp
= &new_lc
->next
;
1251 dst
->var_part
[k
].offset
= src
->var_part
[i
].offset
;
1255 /* We are at the basic block boundary when computing union
1256 so set the CUR_LOC to be the first element of the chain. */
1257 if (dst
->var_part
[k
].loc_chain
)
1258 dst
->var_part
[k
].cur_loc
= dst
->var_part
[k
].loc_chain
->loc
;
1260 dst
->var_part
[k
].cur_loc
= NULL
;
1263 /* Continue traversing the hash table. */
1267 /* Compute union of dataflow sets SRC and DST and store it to DST. */
1270 dataflow_set_union (dataflow_set
*dst
, dataflow_set
*src
)
1274 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1275 attrs_list_union (&dst
->regs
[i
], src
->regs
[i
]);
1277 htab_traverse (src
->vars
, variable_union
, dst
);
1280 /* Flag whether two dataflow sets being compared contain different data. */
1282 dataflow_set_different_value
;
1285 variable_part_different_p (variable_part
*vp1
, variable_part
*vp2
)
1287 location_chain lc1
, lc2
;
1289 for (lc1
= vp1
->loc_chain
; lc1
; lc1
= lc1
->next
)
1291 for (lc2
= vp2
->loc_chain
; lc2
; lc2
= lc2
->next
)
1293 if (REG_P (lc1
->loc
) && REG_P (lc2
->loc
))
1295 if (REGNO (lc1
->loc
) == REGNO (lc2
->loc
))
1298 if (rtx_equal_p (lc1
->loc
, lc2
->loc
))
1307 /* Return true if variables VAR1 and VAR2 are different.
1308 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each
1312 variable_different_p (variable var1
, variable var2
,
1313 bool compare_current_location
)
1320 if (var1
->n_var_parts
!= var2
->n_var_parts
)
1323 for (i
= 0; i
< var1
->n_var_parts
; i
++)
1325 if (var1
->var_part
[i
].offset
!= var2
->var_part
[i
].offset
)
1327 if (compare_current_location
)
1329 if (!((REG_P (var1
->var_part
[i
].cur_loc
)
1330 && REG_P (var2
->var_part
[i
].cur_loc
)
1331 && (REGNO (var1
->var_part
[i
].cur_loc
)
1332 == REGNO (var2
->var_part
[i
].cur_loc
)))
1333 || rtx_equal_p (var1
->var_part
[i
].cur_loc
,
1334 var2
->var_part
[i
].cur_loc
)))
1337 if (variable_part_different_p (&var1
->var_part
[i
], &var2
->var_part
[i
]))
1339 if (variable_part_different_p (&var2
->var_part
[i
], &var1
->var_part
[i
]))
1345 /* Compare variable *SLOT with the same variable in hash table DATA
1346 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1349 dataflow_set_different_1 (void **slot
, void *data
)
1351 htab_t htab
= (htab_t
) data
;
1352 variable var1
, var2
;
1354 var1
= *(variable
*) slot
;
1355 var2
= htab_find_with_hash (htab
, var1
->decl
,
1356 VARIABLE_HASH_VAL (var1
->decl
));
1359 dataflow_set_different_value
= true;
1361 /* Stop traversing the hash table. */
1365 if (variable_different_p (var1
, var2
, false))
1367 dataflow_set_different_value
= true;
1369 /* Stop traversing the hash table. */
1373 /* Continue traversing the hash table. */
1377 /* Compare variable *SLOT with the same variable in hash table DATA
1378 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */
1381 dataflow_set_different_2 (void **slot
, void *data
)
1383 htab_t htab
= (htab_t
) data
;
1384 variable var1
, var2
;
1386 var1
= *(variable
*) slot
;
1387 var2
= htab_find_with_hash (htab
, var1
->decl
,
1388 VARIABLE_HASH_VAL (var1
->decl
));
1391 dataflow_set_different_value
= true;
1393 /* Stop traversing the hash table. */
1397 /* If both variables are defined they have been already checked for
1399 gcc_assert (!variable_different_p (var1
, var2
, false));
1401 /* Continue traversing the hash table. */
1405 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
1408 dataflow_set_different (dataflow_set
*old_set
, dataflow_set
*new_set
)
1410 dataflow_set_different_value
= false;
1412 htab_traverse (old_set
->vars
, dataflow_set_different_1
, new_set
->vars
);
1413 if (!dataflow_set_different_value
)
1415 /* We have compared the variables which are in both hash tables
1416 so now only check whether there are some variables in NEW_SET->VARS
1417 which are not in OLD_SET->VARS. */
1418 htab_traverse (new_set
->vars
, dataflow_set_different_2
, old_set
->vars
);
1420 return dataflow_set_different_value
;
1423 /* Free the contents of dataflow set SET. */
1426 dataflow_set_destroy (dataflow_set
*set
)
1430 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1431 attrs_list_clear (&set
->regs
[i
]);
1433 htab_delete (set
->vars
);
1437 /* Return true if RTL X contains a SYMBOL_REF. */
1440 contains_symbol_ref (rtx x
)
1449 code
= GET_CODE (x
);
1450 if (code
== SYMBOL_REF
)
1453 fmt
= GET_RTX_FORMAT (code
);
1454 for (i
= GET_RTX_LENGTH (code
) - 1; i
>= 0; i
--)
1458 if (contains_symbol_ref (XEXP (x
, i
)))
1461 else if (fmt
[i
] == 'E')
1464 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1465 if (contains_symbol_ref (XVECEXP (x
, i
, j
)))
1473 /* Shall EXPR be tracked? */
1476 track_expr_p (tree expr
)
1481 /* If EXPR is not a parameter or a variable do not track it. */
1482 if (TREE_CODE (expr
) != VAR_DECL
&& TREE_CODE (expr
) != PARM_DECL
)
1485 /* It also must have a name... */
1486 if (!DECL_NAME (expr
))
1489 /* ... and a RTL assigned to it. */
1490 decl_rtl
= DECL_RTL_IF_SET (expr
);
1494 /* If this expression is really a debug alias of some other declaration, we
1495 don't need to track this expression if the ultimate declaration is
1498 if (DECL_DEBUG_EXPR_IS_FROM (realdecl
) && DECL_DEBUG_EXPR (realdecl
))
1500 realdecl
= DECL_DEBUG_EXPR (realdecl
);
1501 /* ??? We don't yet know how to emit DW_OP_piece for variable
1502 that has been SRA'ed. */
1503 if (!DECL_P (realdecl
))
1507 /* Do not track EXPR if REALDECL it should be ignored for debugging
1509 if (DECL_IGNORED_P (realdecl
))
1512 /* Do not track global variables until we are able to emit correct location
1514 if (TREE_STATIC (realdecl
))
1517 /* When the EXPR is a DECL for alias of some variable (see example)
1518 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
1519 DECL_RTL contains SYMBOL_REF.
1522 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
1525 if (MEM_P (decl_rtl
)
1526 && contains_symbol_ref (XEXP (decl_rtl
, 0)))
1529 /* If RTX is a memory it should not be very large (because it would be
1530 an array or struct). */
1531 if (MEM_P (decl_rtl
))
1533 /* Do not track structures and arrays. */
1534 if (GET_MODE (decl_rtl
) == BLKmode
1535 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl
)))
1537 if (MEM_SIZE (decl_rtl
)
1538 && INTVAL (MEM_SIZE (decl_rtl
)) > MAX_VAR_PARTS
)
1545 /* Return true if OFFSET is a valid offset for a register or memory
1546 access we want to track. This is used to reject out-of-bounds
1547 accesses that can cause assertions to fail later. Note that we
1548 don't reject negative offsets because they can be generated for
1549 paradoxical subregs on big-endian architectures. */
1552 offset_valid_for_tracked_p (HOST_WIDE_INT offset
)
1554 return (-MAX_VAR_PARTS
< offset
) && (offset
< MAX_VAR_PARTS
);
1557 /* Determine whether a given LOC refers to the same variable part as
1561 same_variable_part_p (rtx loc
, tree expr
, HOST_WIDE_INT offset
)
1564 HOST_WIDE_INT offset2
;
1566 if (! DECL_P (expr
))
1571 expr2
= REG_EXPR (loc
);
1572 offset2
= REG_OFFSET (loc
);
1574 else if (MEM_P (loc
))
1576 expr2
= MEM_EXPR (loc
);
1577 offset2
= INT_MEM_OFFSET (loc
);
1582 if (! expr2
|| ! DECL_P (expr2
))
1585 expr
= var_debug_decl (expr
);
1586 expr2
= var_debug_decl (expr2
);
1588 return (expr
== expr2
&& offset
== offset2
);
1592 /* Count uses (register and memory references) LOC which will be tracked.
1593 INSN is instruction which the LOC is part of. */
1596 count_uses (rtx
*loc
, void *insn
)
1598 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1602 gcc_assert (REGNO (*loc
) < FIRST_PSEUDO_REGISTER
);
1605 else if (MEM_P (*loc
)
1607 && track_expr_p (MEM_EXPR (*loc
))
1608 && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc
)))
1616 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1619 count_uses_1 (rtx
*x
, void *insn
)
1621 for_each_rtx (x
, count_uses
, insn
);
1624 /* Count stores (register and memory references) LOC which will be tracked.
1625 INSN is instruction which the LOC is part of. */
1628 count_stores (rtx loc
, rtx expr ATTRIBUTE_UNUSED
, void *insn
)
1630 count_uses (&loc
, insn
);
1633 /* Add uses (register and memory references) LOC which will be tracked
1634 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
1637 add_uses (rtx
*loc
, void *insn
)
1641 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1642 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1645 && track_expr_p (REG_EXPR (*loc
))
1646 && offset_valid_for_tracked_p (REG_OFFSET (*loc
)))
1649 mo
->type
= MO_USE_NO_VAR
;
1651 mo
->insn
= (rtx
) insn
;
1653 else if (MEM_P (*loc
)
1655 && track_expr_p (MEM_EXPR (*loc
))
1656 && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc
)))
1658 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1659 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1663 mo
->insn
= (rtx
) insn
;
1669 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
1672 add_uses_1 (rtx
*x
, void *insn
)
1674 for_each_rtx (x
, add_uses
, insn
);
1677 /* Add stores (register and memory references) LOC which will be tracked
1678 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
1679 INSN is instruction which the LOC is part of. */
1682 add_stores (rtx loc
, rtx expr
, void *insn
)
1686 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1687 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1689 if (GET_CODE (expr
) == CLOBBER
1691 && track_expr_p (REG_EXPR (loc
))
1692 && offset_valid_for_tracked_p (REG_OFFSET (loc
))))
1693 mo
->type
= MO_CLOBBER
;
1694 else if (GET_CODE (expr
) == SET
1695 && SET_DEST (expr
) == loc
1696 && same_variable_part_p (SET_SRC (expr
),
1703 mo
->insn
= NEXT_INSN ((rtx
) insn
);
1705 else if (MEM_P (loc
)
1707 && track_expr_p (MEM_EXPR (loc
))
1708 && offset_valid_for_tracked_p (INT_MEM_OFFSET (loc
)))
1710 basic_block bb
= BLOCK_FOR_INSN ((rtx
) insn
);
1711 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
1713 if (GET_CODE (expr
) == CLOBBER
)
1714 mo
->type
= MO_CLOBBER
;
1715 else if (GET_CODE (expr
) == SET
1716 && SET_DEST (expr
) == loc
1717 && same_variable_part_p (SET_SRC (expr
),
1719 INT_MEM_OFFSET (loc
)))
1724 mo
->insn
= NEXT_INSN ((rtx
) insn
);
1728 /* Compute the changes of variable locations in the basic block BB. */
1731 compute_bb_dataflow (basic_block bb
)
1735 dataflow_set old_out
;
1736 dataflow_set
*in
= &VTI (bb
)->in
;
1737 dataflow_set
*out
= &VTI (bb
)->out
;
1739 dataflow_set_init (&old_out
, htab_elements (VTI (bb
)->out
.vars
) + 3);
1740 dataflow_set_copy (&old_out
, out
);
1741 dataflow_set_copy (out
, in
);
1743 n
= VTI (bb
)->n_mos
;
1744 for (i
= 0; i
< n
; i
++)
1746 switch (VTI (bb
)->mos
[i
].type
)
1749 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
1750 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
1751 var_regno_delete (out
, r
);
1756 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1758 if (GET_CODE (loc
) == REG
)
1759 var_reg_set (out
, loc
);
1760 else if (GET_CODE (loc
) == MEM
)
1761 var_mem_set (out
, loc
);
1767 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1770 var_reg_delete_and_set (out
, loc
, true);
1771 else if (MEM_P (loc
))
1772 var_mem_delete_and_set (out
, loc
, true);
1778 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1781 var_reg_delete_and_set (out
, loc
, false);
1782 else if (MEM_P (loc
))
1783 var_mem_delete_and_set (out
, loc
, false);
1789 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1792 var_reg_delete (out
, loc
, false);
1793 else if (MEM_P (loc
))
1794 var_mem_delete (out
, loc
, false);
1800 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
1803 var_reg_delete (out
, loc
, true);
1804 else if (MEM_P (loc
))
1805 var_mem_delete (out
, loc
, true);
1810 out
->stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
1815 changed
= dataflow_set_different (&old_out
, out
);
1816 dataflow_set_destroy (&old_out
);
1820 /* Find the locations of variables in the whole function. */
1823 vt_find_locations (void)
1825 fibheap_t worklist
, pending
, fibheap_swap
;
1826 sbitmap visited
, in_worklist
, in_pending
, sbitmap_swap
;
1833 /* Compute reverse completion order of depth first search of the CFG
1834 so that the data-flow runs faster. */
1835 rc_order
= XNEWVEC (int, n_basic_blocks
- NUM_FIXED_BLOCKS
);
1836 bb_order
= XNEWVEC (int, last_basic_block
);
1837 pre_and_rev_post_order_compute (NULL
, rc_order
, false);
1838 for (i
= 0; i
< n_basic_blocks
- NUM_FIXED_BLOCKS
; i
++)
1839 bb_order
[rc_order
[i
]] = i
;
1842 worklist
= fibheap_new ();
1843 pending
= fibheap_new ();
1844 visited
= sbitmap_alloc (last_basic_block
);
1845 in_worklist
= sbitmap_alloc (last_basic_block
);
1846 in_pending
= sbitmap_alloc (last_basic_block
);
1847 sbitmap_zero (in_worklist
);
1850 fibheap_insert (pending
, bb_order
[bb
->index
], bb
);
1851 sbitmap_ones (in_pending
);
1853 while (!fibheap_empty (pending
))
1855 fibheap_swap
= pending
;
1857 worklist
= fibheap_swap
;
1858 sbitmap_swap
= in_pending
;
1859 in_pending
= in_worklist
;
1860 in_worklist
= sbitmap_swap
;
1862 sbitmap_zero (visited
);
1864 while (!fibheap_empty (worklist
))
1866 bb
= fibheap_extract_min (worklist
);
1867 RESET_BIT (in_worklist
, bb
->index
);
1868 if (!TEST_BIT (visited
, bb
->index
))
1873 SET_BIT (visited
, bb
->index
);
1875 /* Calculate the IN set as union of predecessor OUT sets. */
1876 dataflow_set_clear (&VTI (bb
)->in
);
1877 FOR_EACH_EDGE (e
, ei
, bb
->preds
)
1879 dataflow_set_union (&VTI (bb
)->in
, &VTI (e
->src
)->out
);
1882 changed
= compute_bb_dataflow (bb
);
1885 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1887 if (e
->dest
== EXIT_BLOCK_PTR
)
1893 if (TEST_BIT (visited
, e
->dest
->index
))
1895 if (!TEST_BIT (in_pending
, e
->dest
->index
))
1897 /* Send E->DEST to next round. */
1898 SET_BIT (in_pending
, e
->dest
->index
);
1899 fibheap_insert (pending
,
1900 bb_order
[e
->dest
->index
],
1904 else if (!TEST_BIT (in_worklist
, e
->dest
->index
))
1906 /* Add E->DEST to current round. */
1907 SET_BIT (in_worklist
, e
->dest
->index
);
1908 fibheap_insert (worklist
, bb_order
[e
->dest
->index
],
1918 fibheap_delete (worklist
);
1919 fibheap_delete (pending
);
1920 sbitmap_free (visited
);
1921 sbitmap_free (in_worklist
);
1922 sbitmap_free (in_pending
);
1925 /* Print the content of the LIST to dump file. */
1928 dump_attrs_list (attrs list
)
1930 for (; list
; list
= list
->next
)
1932 print_mem_expr (dump_file
, list
->decl
);
1933 fprintf (dump_file
, "+" HOST_WIDE_INT_PRINT_DEC
, list
->offset
);
1935 fprintf (dump_file
, "\n");
1938 /* Print the information about variable *SLOT to dump file. */
1941 dump_variable (void **slot
, void *data ATTRIBUTE_UNUSED
)
1943 variable var
= *(variable
*) slot
;
1945 location_chain node
;
1947 fprintf (dump_file
, " name: %s\n",
1948 IDENTIFIER_POINTER (DECL_NAME (var
->decl
)));
1949 for (i
= 0; i
< var
->n_var_parts
; i
++)
1951 fprintf (dump_file
, " offset %ld\n",
1952 (long) var
->var_part
[i
].offset
);
1953 for (node
= var
->var_part
[i
].loc_chain
; node
; node
= node
->next
)
1955 fprintf (dump_file
, " ");
1956 print_rtl_single (dump_file
, node
->loc
);
1960 /* Continue traversing the hash table. */
1964 /* Print the information about variables from hash table VARS to dump file. */
1967 dump_vars (htab_t vars
)
1969 if (htab_elements (vars
) > 0)
1971 fprintf (dump_file
, "Variables:\n");
1972 htab_traverse (vars
, dump_variable
, NULL
);
1976 /* Print the dataflow set SET to dump file. */
1979 dump_dataflow_set (dataflow_set
*set
)
1983 fprintf (dump_file
, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC
"\n",
1985 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1989 fprintf (dump_file
, "Reg %d:", i
);
1990 dump_attrs_list (set
->regs
[i
]);
1993 dump_vars (set
->vars
);
1994 fprintf (dump_file
, "\n");
1997 /* Print the IN and OUT sets for each basic block to dump file. */
2000 dump_dataflow_sets (void)
2006 fprintf (dump_file
, "\nBasic block %d:\n", bb
->index
);
2007 fprintf (dump_file
, "IN:\n");
2008 dump_dataflow_set (&VTI (bb
)->in
);
2009 fprintf (dump_file
, "OUT:\n");
2010 dump_dataflow_set (&VTI (bb
)->out
);
2014 /* Add variable VAR to the hash table of changed variables and
2015 if it has no locations delete it from hash table HTAB. */
2018 variable_was_changed (variable var
, htab_t htab
)
2020 hashval_t hash
= VARIABLE_HASH_VAL (var
->decl
);
2026 slot
= (variable
*) htab_find_slot_with_hash (changed_variables
,
2027 var
->decl
, hash
, INSERT
);
2029 if (htab
&& var
->n_var_parts
== 0)
2034 empty_var
= pool_alloc (var_pool
);
2035 empty_var
->decl
= var
->decl
;
2036 empty_var
->refcount
= 1;
2037 empty_var
->n_var_parts
= 0;
2040 old
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
2043 htab_clear_slot (htab
, old
);
2053 if (var
->n_var_parts
== 0)
2055 void **slot
= htab_find_slot_with_hash (htab
, var
->decl
, hash
,
2058 htab_clear_slot (htab
, slot
);
2063 /* Look for the index in VAR->var_part corresponding to OFFSET.
2064 Return -1 if not found. If INSERTION_POINT is non-NULL, the
2065 referenced int will be set to the index that the part has or should
2066 have, if it should be inserted. */
2069 find_variable_location_part (variable var
, HOST_WIDE_INT offset
,
2070 int *insertion_point
)
2074 /* Find the location part. */
2076 high
= var
->n_var_parts
;
2079 pos
= (low
+ high
) / 2;
2080 if (var
->var_part
[pos
].offset
< offset
)
2087 if (insertion_point
)
2088 *insertion_point
= pos
;
2090 if (pos
< var
->n_var_parts
&& var
->var_part
[pos
].offset
== offset
)
2096 /* Set the part of variable's location in the dataflow set SET. The variable
2097 part is specified by variable's declaration DECL and offset OFFSET and the
2098 part's location by LOC. */
2101 set_variable_part (dataflow_set
*set
, rtx loc
, tree decl
, HOST_WIDE_INT offset
)
2104 location_chain node
, next
;
2105 location_chain
*nextp
;
2109 slot
= htab_find_slot_with_hash (set
->vars
, decl
,
2110 VARIABLE_HASH_VAL (decl
), INSERT
);
2113 /* Create new variable information. */
2114 var
= pool_alloc (var_pool
);
2117 var
->n_var_parts
= 1;
2118 var
->var_part
[0].offset
= offset
;
2119 var
->var_part
[0].loc_chain
= NULL
;
2120 var
->var_part
[0].cur_loc
= NULL
;
2128 var
= (variable
) *slot
;
2130 pos
= find_variable_location_part (var
, offset
, &inspos
);
2134 node
= var
->var_part
[pos
].loc_chain
;
2137 && ((REG_P (node
->loc
) && REG_P (loc
)
2138 && REGNO (node
->loc
) == REGNO (loc
))
2139 || rtx_equal_p (node
->loc
, loc
)))
2141 /* LOC is in the beginning of the chain so we have nothing
2147 /* We have to make a copy of a shared variable. */
2148 if (var
->refcount
> 1)
2149 var
= unshare_variable (set
, var
);
2154 /* We have not found the location part, new one will be created. */
2156 /* We have to make a copy of the shared variable. */
2157 if (var
->refcount
> 1)
2158 var
= unshare_variable (set
, var
);
2160 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2161 thus there are at most MAX_VAR_PARTS different offsets. */
2162 gcc_assert (var
->n_var_parts
< MAX_VAR_PARTS
);
2164 /* We have to move the elements of array starting at index
2165 inspos to the next position. */
2166 for (pos
= var
->n_var_parts
; pos
> inspos
; pos
--)
2167 var
->var_part
[pos
] = var
->var_part
[pos
- 1];
2170 var
->var_part
[pos
].offset
= offset
;
2171 var
->var_part
[pos
].loc_chain
= NULL
;
2172 var
->var_part
[pos
].cur_loc
= NULL
;
2176 /* Delete the location from the list. */
2177 nextp
= &var
->var_part
[pos
].loc_chain
;
2178 for (node
= var
->var_part
[pos
].loc_chain
; node
; node
= next
)
2181 if ((REG_P (node
->loc
) && REG_P (loc
)
2182 && REGNO (node
->loc
) == REGNO (loc
))
2183 || rtx_equal_p (node
->loc
, loc
))
2185 pool_free (loc_chain_pool
, node
);
2190 nextp
= &node
->next
;
2193 /* Add the location to the beginning. */
2194 node
= pool_alloc (loc_chain_pool
);
2196 node
->next
= var
->var_part
[pos
].loc_chain
;
2197 var
->var_part
[pos
].loc_chain
= node
;
2199 /* If no location was emitted do so. */
2200 if (var
->var_part
[pos
].cur_loc
== NULL
)
2202 var
->var_part
[pos
].cur_loc
= loc
;
2203 variable_was_changed (var
, set
->vars
);
2207 /* Remove all recorded register locations for the given variable part
2208 from dataflow set SET, except for those that are identical to loc.
2209 The variable part is specified by variable's declaration DECL and
2213 clobber_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2214 HOST_WIDE_INT offset
)
2218 if (! decl
|| ! DECL_P (decl
))
2221 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2225 variable var
= (variable
) *slot
;
2226 int pos
= find_variable_location_part (var
, offset
, NULL
);
2230 location_chain node
, next
;
2232 /* Remove the register locations from the dataflow set. */
2233 next
= var
->var_part
[pos
].loc_chain
;
2234 for (node
= next
; node
; node
= next
)
2237 if (node
->loc
!= loc
)
2239 if (REG_P (node
->loc
))
2244 /* Remove the variable part from the register's
2245 list, but preserve any other variable parts
2246 that might be regarded as live in that same
2248 anextp
= &set
->regs
[REGNO (node
->loc
)];
2249 for (anode
= *anextp
; anode
; anode
= anext
)
2251 anext
= anode
->next
;
2252 if (anode
->decl
== decl
2253 && anode
->offset
== offset
)
2255 pool_free (attrs_pool
, anode
);
2261 delete_variable_part (set
, node
->loc
, decl
, offset
);
2268 /* Delete the part of variable's location from dataflow set SET. The variable
2269 part is specified by variable's declaration DECL and offset OFFSET and the
2270 part's location by LOC. */
2273 delete_variable_part (dataflow_set
*set
, rtx loc
, tree decl
,
2274 HOST_WIDE_INT offset
)
2278 slot
= htab_find_slot_with_hash (set
->vars
, decl
, VARIABLE_HASH_VAL (decl
),
2282 variable var
= (variable
) *slot
;
2283 int pos
= find_variable_location_part (var
, offset
, NULL
);
2287 location_chain node
, next
;
2288 location_chain
*nextp
;
2291 if (var
->refcount
> 1)
2293 /* If the variable contains the location part we have to
2294 make a copy of the variable. */
2295 for (node
= var
->var_part
[pos
].loc_chain
; node
;
2298 if ((REG_P (node
->loc
) && REG_P (loc
)
2299 && REGNO (node
->loc
) == REGNO (loc
))
2300 || rtx_equal_p (node
->loc
, loc
))
2302 var
= unshare_variable (set
, var
);
2308 /* Delete the location part. */
2309 nextp
= &var
->var_part
[pos
].loc_chain
;
2310 for (node
= *nextp
; node
; node
= next
)
2313 if ((REG_P (node
->loc
) && REG_P (loc
)
2314 && REGNO (node
->loc
) == REGNO (loc
))
2315 || rtx_equal_p (node
->loc
, loc
))
2317 pool_free (loc_chain_pool
, node
);
2322 nextp
= &node
->next
;
2325 /* If we have deleted the location which was last emitted
2326 we have to emit new location so add the variable to set
2327 of changed variables. */
2328 if (var
->var_part
[pos
].cur_loc
2330 && REG_P (var
->var_part
[pos
].cur_loc
)
2331 && REGNO (loc
) == REGNO (var
->var_part
[pos
].cur_loc
))
2332 || rtx_equal_p (loc
, var
->var_part
[pos
].cur_loc
)))
2335 if (var
->var_part
[pos
].loc_chain
)
2336 var
->var_part
[pos
].cur_loc
= var
->var_part
[pos
].loc_chain
->loc
;
2341 if (var
->var_part
[pos
].loc_chain
== NULL
)
2344 while (pos
< var
->n_var_parts
)
2346 var
->var_part
[pos
] = var
->var_part
[pos
+ 1];
2351 variable_was_changed (var
, set
->vars
);
2356 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
2357 additional parameters: WHERE specifies whether the note shall be emitted
2358 before of after instruction INSN. */
2361 emit_note_insn_var_location (void **varp
, void *data
)
2363 variable var
= *(variable
*) varp
;
2364 rtx insn
= ((emit_note_data
*)data
)->insn
;
2365 enum emit_note_where where
= ((emit_note_data
*)data
)->where
;
2367 int i
, j
, n_var_parts
;
2369 HOST_WIDE_INT last_limit
;
2370 tree type_size_unit
;
2371 HOST_WIDE_INT offsets
[MAX_VAR_PARTS
];
2372 rtx loc
[MAX_VAR_PARTS
];
2374 gcc_assert (var
->decl
);
2379 for (i
= 0; i
< var
->n_var_parts
; i
++)
2381 enum machine_mode mode
, wider_mode
;
2383 if (last_limit
< var
->var_part
[i
].offset
)
2388 else if (last_limit
> var
->var_part
[i
].offset
)
2390 offsets
[n_var_parts
] = var
->var_part
[i
].offset
;
2391 loc
[n_var_parts
] = var
->var_part
[i
].loc_chain
->loc
;
2392 mode
= GET_MODE (loc
[n_var_parts
]);
2393 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2395 /* Attempt to merge adjacent registers or memory. */
2396 wider_mode
= GET_MODE_WIDER_MODE (mode
);
2397 for (j
= i
+ 1; j
< var
->n_var_parts
; j
++)
2398 if (last_limit
<= var
->var_part
[j
].offset
)
2400 if (j
< var
->n_var_parts
2401 && wider_mode
!= VOIDmode
2402 && GET_CODE (loc
[n_var_parts
])
2403 == GET_CODE (var
->var_part
[j
].loc_chain
->loc
)
2404 && mode
== GET_MODE (var
->var_part
[j
].loc_chain
->loc
)
2405 && last_limit
== var
->var_part
[j
].offset
)
2408 rtx loc2
= var
->var_part
[j
].loc_chain
->loc
;
2410 if (REG_P (loc
[n_var_parts
])
2411 && hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
] * 2
2412 == hard_regno_nregs
[REGNO (loc
[n_var_parts
])][wider_mode
]
2413 && REGNO (loc
[n_var_parts
])
2414 + hard_regno_nregs
[REGNO (loc
[n_var_parts
])][mode
]
2417 if (! WORDS_BIG_ENDIAN
&& ! BYTES_BIG_ENDIAN
)
2418 new_loc
= simplify_subreg (wider_mode
, loc
[n_var_parts
],
2420 else if (WORDS_BIG_ENDIAN
&& BYTES_BIG_ENDIAN
)
2421 new_loc
= simplify_subreg (wider_mode
, loc2
, mode
, 0);
2424 if (!REG_P (new_loc
)
2425 || REGNO (new_loc
) != REGNO (loc
[n_var_parts
]))
2428 REG_ATTRS (new_loc
) = REG_ATTRS (loc
[n_var_parts
]);
2431 else if (MEM_P (loc
[n_var_parts
])
2432 && GET_CODE (XEXP (loc2
, 0)) == PLUS
2433 && GET_CODE (XEXP (XEXP (loc2
, 0), 0)) == REG
2434 && GET_CODE (XEXP (XEXP (loc2
, 0), 1)) == CONST_INT
)
2436 if ((GET_CODE (XEXP (loc
[n_var_parts
], 0)) == REG
2437 && rtx_equal_p (XEXP (loc
[n_var_parts
], 0),
2438 XEXP (XEXP (loc2
, 0), 0))
2439 && INTVAL (XEXP (XEXP (loc2
, 0), 1))
2440 == GET_MODE_SIZE (mode
))
2441 || (GET_CODE (XEXP (loc
[n_var_parts
], 0)) == PLUS
2442 && GET_CODE (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2444 && rtx_equal_p (XEXP (XEXP (loc
[n_var_parts
], 0), 0),
2445 XEXP (XEXP (loc2
, 0), 0))
2446 && INTVAL (XEXP (XEXP (loc
[n_var_parts
], 0), 1))
2447 + GET_MODE_SIZE (mode
)
2448 == INTVAL (XEXP (XEXP (loc2
, 0), 1))))
2449 new_loc
= adjust_address_nv (loc
[n_var_parts
],
2455 loc
[n_var_parts
] = new_loc
;
2457 last_limit
= offsets
[n_var_parts
] + GET_MODE_SIZE (mode
);
2463 type_size_unit
= TYPE_SIZE_UNIT (TREE_TYPE (var
->decl
));
2464 if ((unsigned HOST_WIDE_INT
) last_limit
< TREE_INT_CST_LOW (type_size_unit
))
2467 if (where
== EMIT_NOTE_AFTER_INSN
)
2468 note
= emit_note_after (NOTE_INSN_VAR_LOCATION
, insn
);
2470 note
= emit_note_before (NOTE_INSN_VAR_LOCATION
, insn
);
2474 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2477 else if (n_var_parts
== 1)
2480 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[0], GEN_INT (offsets
[0]));
2482 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2485 else if (n_var_parts
)
2489 for (i
= 0; i
< n_var_parts
; i
++)
2491 = gen_rtx_EXPR_LIST (VOIDmode
, loc
[i
], GEN_INT (offsets
[i
]));
2493 parallel
= gen_rtx_PARALLEL (VOIDmode
,
2494 gen_rtvec_v (n_var_parts
, loc
));
2495 NOTE_VAR_LOCATION (note
) = gen_rtx_VAR_LOCATION (VOIDmode
, var
->decl
,
2499 htab_clear_slot (changed_variables
, varp
);
2501 /* When there are no location parts the variable has been already
2502 removed from hash table and a new empty variable was created.
2503 Free the empty variable. */
2504 if (var
->n_var_parts
== 0)
2506 pool_free (var_pool
, var
);
2509 /* Continue traversing the hash table. */
2513 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
2514 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
2515 shall be emitted before of after instruction INSN. */
2518 emit_notes_for_changes (rtx insn
, enum emit_note_where where
)
2520 emit_note_data data
;
2524 htab_traverse (changed_variables
, emit_note_insn_var_location
, &data
);
2527 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
2528 same variable in hash table DATA or is not there at all. */
2531 emit_notes_for_differences_1 (void **slot
, void *data
)
2533 htab_t new_vars
= (htab_t
) data
;
2534 variable old_var
, new_var
;
2536 old_var
= *(variable
*) slot
;
2537 new_var
= htab_find_with_hash (new_vars
, old_var
->decl
,
2538 VARIABLE_HASH_VAL (old_var
->decl
));
2542 /* Variable has disappeared. */
2545 empty_var
= pool_alloc (var_pool
);
2546 empty_var
->decl
= old_var
->decl
;
2547 empty_var
->refcount
= 1;
2548 empty_var
->n_var_parts
= 0;
2549 variable_was_changed (empty_var
, NULL
);
2551 else if (variable_different_p (old_var
, new_var
, true))
2553 variable_was_changed (new_var
, NULL
);
2556 /* Continue traversing the hash table. */
2560 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
2564 emit_notes_for_differences_2 (void **slot
, void *data
)
2566 htab_t old_vars
= (htab_t
) data
;
2567 variable old_var
, new_var
;
2569 new_var
= *(variable
*) slot
;
2570 old_var
= htab_find_with_hash (old_vars
, new_var
->decl
,
2571 VARIABLE_HASH_VAL (new_var
->decl
));
2574 /* Variable has appeared. */
2575 variable_was_changed (new_var
, NULL
);
2578 /* Continue traversing the hash table. */
2582 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
2586 emit_notes_for_differences (rtx insn
, dataflow_set
*old_set
,
2587 dataflow_set
*new_set
)
2589 htab_traverse (old_set
->vars
, emit_notes_for_differences_1
, new_set
->vars
);
2590 htab_traverse (new_set
->vars
, emit_notes_for_differences_2
, old_set
->vars
);
2591 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2594 /* Emit the notes for changes of location parts in the basic block BB. */
2597 emit_notes_in_bb (basic_block bb
)
2602 dataflow_set_init (&set
, htab_elements (VTI (bb
)->in
.vars
) + 3);
2603 dataflow_set_copy (&set
, &VTI (bb
)->in
);
2605 for (i
= 0; i
< VTI (bb
)->n_mos
; i
++)
2607 rtx insn
= VTI (bb
)->mos
[i
].insn
;
2609 switch (VTI (bb
)->mos
[i
].type
)
2615 for (r
= 0; r
< FIRST_PSEUDO_REGISTER
; r
++)
2616 if (TEST_HARD_REG_BIT (call_used_reg_set
, r
))
2618 var_regno_delete (&set
, r
);
2620 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2626 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2628 if (GET_CODE (loc
) == REG
)
2629 var_reg_set (&set
, loc
);
2631 var_mem_set (&set
, loc
);
2633 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2639 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2642 var_reg_delete_and_set (&set
, loc
, true);
2644 var_mem_delete_and_set (&set
, loc
, true);
2646 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2652 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2655 var_reg_delete_and_set (&set
, loc
, false);
2657 var_mem_delete_and_set (&set
, loc
, false);
2659 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2665 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2668 var_reg_delete (&set
, loc
, false);
2670 var_mem_delete (&set
, loc
, false);
2672 emit_notes_for_changes (insn
, EMIT_NOTE_AFTER_INSN
);
2678 rtx loc
= VTI (bb
)->mos
[i
].u
.loc
;
2681 var_reg_delete (&set
, loc
, true);
2683 var_mem_delete (&set
, loc
, true);
2685 emit_notes_for_changes (insn
, EMIT_NOTE_BEFORE_INSN
);
2690 set
.stack_adjust
+= VTI (bb
)->mos
[i
].u
.adjust
;
2694 dataflow_set_destroy (&set
);
2697 /* Emit notes for the whole function. */
2700 vt_emit_notes (void)
2703 dataflow_set
*last_out
;
2706 gcc_assert (!htab_elements (changed_variables
));
2708 /* Enable emitting notes by functions (mainly by set_variable_part and
2709 delete_variable_part). */
2712 dataflow_set_init (&empty
, 7);
2717 /* Emit the notes for changes of variable locations between two
2718 subsequent basic blocks. */
2719 emit_notes_for_differences (BB_HEAD (bb
), last_out
, &VTI (bb
)->in
);
2721 /* Emit the notes for the changes in the basic block itself. */
2722 emit_notes_in_bb (bb
);
2724 last_out
= &VTI (bb
)->out
;
2726 dataflow_set_destroy (&empty
);
2730 /* If there is a declaration and offset associated with register/memory RTL
2731 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
2734 vt_get_decl_and_offset (rtx rtl
, tree
*declp
, HOST_WIDE_INT
*offsetp
)
2738 if (REG_ATTRS (rtl
))
2740 *declp
= REG_EXPR (rtl
);
2741 *offsetp
= REG_OFFSET (rtl
);
2745 else if (MEM_P (rtl
))
2747 if (MEM_ATTRS (rtl
))
2749 *declp
= MEM_EXPR (rtl
);
2750 *offsetp
= INT_MEM_OFFSET (rtl
);
2757 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
2760 vt_add_function_parameters (void)
2764 for (parm
= DECL_ARGUMENTS (current_function_decl
);
2765 parm
; parm
= TREE_CHAIN (parm
))
2767 rtx decl_rtl
= DECL_RTL_IF_SET (parm
);
2768 rtx incoming
= DECL_INCOMING_RTL (parm
);
2770 HOST_WIDE_INT offset
;
2773 if (TREE_CODE (parm
) != PARM_DECL
)
2776 if (!DECL_NAME (parm
))
2779 if (!decl_rtl
|| !incoming
)
2782 if (GET_MODE (decl_rtl
) == BLKmode
|| GET_MODE (incoming
) == BLKmode
)
2785 if (!vt_get_decl_and_offset (incoming
, &decl
, &offset
))
2786 if (!vt_get_decl_and_offset (decl_rtl
, &decl
, &offset
))
2792 gcc_assert (parm
== decl
);
2794 out
= &VTI (ENTRY_BLOCK_PTR
)->out
;
2796 if (REG_P (incoming
))
2798 gcc_assert (REGNO (incoming
) < FIRST_PSEUDO_REGISTER
);
2799 attrs_list_insert (&out
->regs
[REGNO (incoming
)],
2800 parm
, offset
, incoming
);
2801 set_variable_part (out
, incoming
, parm
, offset
);
2803 else if (MEM_P (incoming
))
2804 set_variable_part (out
, incoming
, parm
, offset
);
2808 /* Allocate and initialize the data structures for variable tracking
2809 and parse the RTL to get the micro operations. */
2812 vt_initialize (void)
2816 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def
));
2821 HOST_WIDE_INT pre
, post
= 0;
2823 /* Count the number of micro operations. */
2824 VTI (bb
)->n_mos
= 0;
2825 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
2826 insn
= NEXT_INSN (insn
))
2830 if (!frame_pointer_needed
)
2832 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
2838 note_uses (&PATTERN (insn
), count_uses_1
, insn
);
2839 note_stores (PATTERN (insn
), count_stores
, insn
);
2845 /* Add the micro-operations to the array. */
2846 VTI (bb
)->mos
= XNEWVEC (micro_operation
, VTI (bb
)->n_mos
);
2847 VTI (bb
)->n_mos
= 0;
2848 for (insn
= BB_HEAD (bb
); insn
!= NEXT_INSN (BB_END (bb
));
2849 insn
= NEXT_INSN (insn
))
2855 if (!frame_pointer_needed
)
2857 insn_stack_adjust_offset_pre_post (insn
, &pre
, &post
);
2860 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2862 mo
->type
= MO_ADJUST
;
2868 n1
= VTI (bb
)->n_mos
;
2869 note_uses (&PATTERN (insn
), add_uses_1
, insn
);
2870 n2
= VTI (bb
)->n_mos
- 1;
2872 /* Order the MO_USEs to be before MO_USE_NO_VARs. */
2875 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_USE
)
2877 while (n1
< n2
&& VTI (bb
)->mos
[n2
].type
== MO_USE_NO_VAR
)
2883 sw
= VTI (bb
)->mos
[n1
];
2884 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
2885 VTI (bb
)->mos
[n2
] = sw
;
2891 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2897 n1
= VTI (bb
)->n_mos
;
2898 /* This will record NEXT_INSN (insn), such that we can
2899 insert notes before it without worrying about any
2900 notes that MO_USEs might emit after the insn. */
2901 note_stores (PATTERN (insn
), add_stores
, insn
);
2902 n2
= VTI (bb
)->n_mos
- 1;
2904 /* Order the MO_CLOBBERs to be before MO_SETs. */
2907 while (n1
< n2
&& VTI (bb
)->mos
[n1
].type
== MO_CLOBBER
)
2909 while (n1
< n2
&& (VTI (bb
)->mos
[n2
].type
== MO_SET
2910 || VTI (bb
)->mos
[n2
].type
== MO_COPY
))
2916 sw
= VTI (bb
)->mos
[n1
];
2917 VTI (bb
)->mos
[n1
] = VTI (bb
)->mos
[n2
];
2918 VTI (bb
)->mos
[n2
] = sw
;
2922 if (!frame_pointer_needed
&& post
)
2924 micro_operation
*mo
= VTI (bb
)->mos
+ VTI (bb
)->n_mos
++;
2926 mo
->type
= MO_ADJUST
;
2927 mo
->u
.adjust
= post
;
2934 /* Init the IN and OUT sets. */
2937 VTI (bb
)->visited
= false;
2938 dataflow_set_init (&VTI (bb
)->in
, 7);
2939 dataflow_set_init (&VTI (bb
)->out
, 7);
2942 attrs_pool
= create_alloc_pool ("attrs_def pool",
2943 sizeof (struct attrs_def
), 1024);
2944 var_pool
= create_alloc_pool ("variable_def pool",
2945 sizeof (struct variable_def
), 64);
2946 loc_chain_pool
= create_alloc_pool ("location_chain_def pool",
2947 sizeof (struct location_chain_def
),
2949 changed_variables
= htab_create (10, variable_htab_hash
, variable_htab_eq
,
2951 vt_add_function_parameters ();
2954 /* Free the data structures needed for variable tracking. */
2963 free (VTI (bb
)->mos
);
2968 dataflow_set_destroy (&VTI (bb
)->in
);
2969 dataflow_set_destroy (&VTI (bb
)->out
);
2971 free_aux_for_blocks ();
2972 free_alloc_pool (attrs_pool
);
2973 free_alloc_pool (var_pool
);
2974 free_alloc_pool (loc_chain_pool
);
2975 htab_delete (changed_variables
);
2978 /* The entry point to variable tracking pass. */
2981 variable_tracking_main (void)
2983 if (n_basic_blocks
> 500 && n_edges
/ n_basic_blocks
>= 20)
2986 mark_dfs_back_edges ();
2988 if (!frame_pointer_needed
)
2990 if (!vt_stack_adjustments ())
2997 vt_find_locations ();
3000 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
3002 dump_dataflow_sets ();
3003 dump_flow_info (dump_file
, dump_flags
);
3011 gate_handle_var_tracking (void)
3013 return (flag_var_tracking
);
3018 struct tree_opt_pass pass_variable_tracking
=
3020 "vartrack", /* name */
3021 gate_handle_var_tracking
, /* gate */
3022 variable_tracking_main
, /* execute */
3025 0, /* static_pass_number */
3026 TV_VAR_TRACKING
, /* tv_id */
3027 0, /* properties_required */
3028 0, /* properties_provided */
3029 0, /* properties_destroyed */
3030 0, /* todo_flags_start */
3031 TODO_dump_func
, /* todo_flags_finish */