Mark ChangeLog
[official-gcc.git] / gcc / var-tracking.c
blob7b221cec7403d1c70f46ecd6499a79b06872c5c4
1 /* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file contains the variable tracking pass. It computes where
22 variables are located (which registers or where in memory) at each position
23 in instruction stream and emits notes describing the locations.
24 Debug information (DWARF2 location lists) is finally generated from
25 these notes.
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
34 operations.
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
54 register.
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
60 register in CODE:
62 if (cond)
63 set A;
64 else
65 set B;
66 CODE;
67 if (cond)
68 use A;
69 else
70 use B;
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).
89 #include "config.h"
90 #include "system.h"
91 #include "coretypes.h"
92 #include "tm.h"
93 #include "rtl.h"
94 #include "tree.h"
95 #include "hard-reg-set.h"
96 #include "basic-block.h"
97 #include "flags.h"
98 #include "output.h"
99 #include "insn-config.h"
100 #include "reload.h"
101 #include "sbitmap.h"
102 #include "alloc-pool.h"
103 #include "fibheap.h"
104 #include "hashtab.h"
105 #include "regs.h"
106 #include "expr.h"
107 #include "timevar.h"
108 #include "tree-pass.h"
109 #include "tree-flow.h"
110 #include "cselib.h"
111 #include "target.h"
112 #include "toplev.h"
113 #include "params.h"
114 #include "diagnostic.h"
115 #include "pointer-set.h"
116 #include "recog.h"
118 /* var-tracking.c assumes that tree code with the same value as VALUE rtx code
119 has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
120 Currently the value is the same as IDENTIFIER_NODE, which has such
121 a property. If this compile time assertion ever fails, make sure that
122 the new tree code that equals (int) VALUE has the same property. */
123 extern char check_value_val[(int) VALUE == (int) IDENTIFIER_NODE ? 1 : -1];
125 /* Type of micro operation. */
126 enum micro_operation_type
128 MO_USE, /* Use location (REG or MEM). */
129 MO_USE_NO_VAR,/* Use location which is not associated with a variable
130 or the variable is not trackable. */
131 MO_VAL_USE, /* Use location which is associated with a value. */
132 MO_VAL_LOC, /* Use location which appears in a debug insn. */
133 MO_VAL_SET, /* Set location associated with a value. */
134 MO_SET, /* Set location. */
135 MO_COPY, /* Copy the same portion of a variable from one
136 location to another. */
137 MO_CLOBBER, /* Clobber location. */
138 MO_CALL, /* Call insn. */
139 MO_ADJUST /* Adjust stack pointer. */
143 static const char * const ATTRIBUTE_UNUSED
144 micro_operation_type_name[] = {
145 "MO_USE",
146 "MO_USE_NO_VAR",
147 "MO_VAL_USE",
148 "MO_VAL_LOC",
149 "MO_VAL_SET",
150 "MO_SET",
151 "MO_COPY",
152 "MO_CLOBBER",
153 "MO_CALL",
154 "MO_ADJUST"
157 /* Where shall the note be emitted? BEFORE or AFTER the instruction.
158 Notes emitted as AFTER_CALL are to take effect during the call,
159 rather than after the call. */
160 enum emit_note_where
162 EMIT_NOTE_BEFORE_INSN,
163 EMIT_NOTE_AFTER_INSN,
164 EMIT_NOTE_AFTER_CALL_INSN
167 /* Structure holding information about micro operation. */
168 typedef struct micro_operation_def
170 /* Type of micro operation. */
171 enum micro_operation_type type;
173 /* The instruction which the micro operation is in, for MO_USE,
174 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
175 instruction or note in the original flow (before any var-tracking
176 notes are inserted, to simplify emission of notes), for MO_SET
177 and MO_CLOBBER. */
178 rtx insn;
180 union {
181 /* Location. For MO_SET and MO_COPY, this is the SET that
182 performs the assignment, if known, otherwise it is the target
183 of the assignment. For MO_VAL_USE and MO_VAL_SET, it is a
184 CONCAT of the VALUE and the LOC associated with it. For
185 MO_VAL_LOC, it is a CONCAT of the VALUE and the VAR_LOCATION
186 associated with it. */
187 rtx loc;
189 /* Stack adjustment. */
190 HOST_WIDE_INT adjust;
191 } u;
192 } micro_operation;
194 DEF_VEC_O(micro_operation);
195 DEF_VEC_ALLOC_O(micro_operation,heap);
197 /* A declaration of a variable, or an RTL value being handled like a
198 declaration. */
199 typedef void *decl_or_value;
201 /* Structure for passing some other parameters to function
202 emit_note_insn_var_location. */
203 typedef struct emit_note_data_def
205 /* The instruction which the note will be emitted before/after. */
206 rtx insn;
208 /* Where the note will be emitted (before/after insn)? */
209 enum emit_note_where where;
211 /* The variables and values active at this point. */
212 htab_t vars;
213 } emit_note_data;
215 /* Description of location of a part of a variable. The content of a physical
216 register is described by a chain of these structures.
217 The chains are pretty short (usually 1 or 2 elements) and thus
218 chain is the best data structure. */
219 typedef struct attrs_def
221 /* Pointer to next member of the list. */
222 struct attrs_def *next;
224 /* The rtx of register. */
225 rtx loc;
227 /* The declaration corresponding to LOC. */
228 decl_or_value dv;
230 /* Offset from start of DECL. */
231 HOST_WIDE_INT offset;
232 } *attrs;
234 /* Structure holding a refcounted hash table. If refcount > 1,
235 it must be first unshared before modified. */
236 typedef struct shared_hash_def
238 /* Reference count. */
239 int refcount;
241 /* Actual hash table. */
242 htab_t htab;
243 } *shared_hash;
245 /* Structure holding the IN or OUT set for a basic block. */
246 typedef struct dataflow_set_def
248 /* Adjustment of stack offset. */
249 HOST_WIDE_INT stack_adjust;
251 /* Attributes for registers (lists of attrs). */
252 attrs regs[FIRST_PSEUDO_REGISTER];
254 /* Variable locations. */
255 shared_hash vars;
257 /* Vars that is being traversed. */
258 shared_hash traversed_vars;
259 } dataflow_set;
261 /* The structure (one for each basic block) containing the information
262 needed for variable tracking. */
263 typedef struct variable_tracking_info_def
265 /* The vector of micro operations. */
266 VEC(micro_operation, heap) *mos;
268 /* The IN and OUT set for dataflow analysis. */
269 dataflow_set in;
270 dataflow_set out;
272 /* The permanent-in dataflow set for this block. This is used to
273 hold values for which we had to compute entry values. ??? This
274 should probably be dynamically allocated, to avoid using more
275 memory in non-debug builds. */
276 dataflow_set *permp;
278 /* Has the block been visited in DFS? */
279 bool visited;
281 /* Has the block been flooded in VTA? */
282 bool flooded;
284 } *variable_tracking_info;
286 /* Structure for chaining the locations. */
287 typedef struct location_chain_def
289 /* Next element in the chain. */
290 struct location_chain_def *next;
292 /* The location (REG, MEM or VALUE). */
293 rtx loc;
295 /* The "value" stored in this location. */
296 rtx set_src;
298 /* Initialized? */
299 enum var_init_status init;
300 } *location_chain;
302 /* Structure describing one part of variable. */
303 typedef struct variable_part_def
305 /* Chain of locations of the part. */
306 location_chain loc_chain;
308 /* Location which was last emitted to location list. */
309 rtx cur_loc;
311 /* The offset in the variable. */
312 HOST_WIDE_INT offset;
313 } variable_part;
315 /* Maximum number of location parts. */
316 #define MAX_VAR_PARTS 16
318 /* Structure describing where the variable is located. */
319 typedef struct variable_def
321 /* The declaration of the variable, or an RTL value being handled
322 like a declaration. */
323 decl_or_value dv;
325 /* Reference count. */
326 int refcount;
328 /* Number of variable parts. */
329 char n_var_parts;
331 /* True if this variable changed (any of its) cur_loc fields
332 during the current emit_notes_for_changes resp.
333 emit_notes_for_differences call. */
334 bool cur_loc_changed;
336 /* True if this variable_def struct is currently in the
337 changed_variables hash table. */
338 bool in_changed_variables;
340 /* The variable parts. */
341 variable_part var_part[1];
342 } *variable;
343 typedef const struct variable_def *const_variable;
345 /* Structure for chaining backlinks from referenced VALUEs to
346 DVs that are referencing them. */
347 typedef struct value_chain_def
349 /* Next value_chain entry. */
350 struct value_chain_def *next;
352 /* The declaration of the variable, or an RTL value
353 being handled like a declaration, whose var_parts[0].loc_chain
354 references the VALUE owning this value_chain. */
355 decl_or_value dv;
357 /* Reference count. */
358 int refcount;
359 } *value_chain;
360 typedef const struct value_chain_def *const_value_chain;
362 /* Pointer to the BB's information specific to variable tracking pass. */
363 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
365 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
366 #define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
368 /* Alloc pool for struct attrs_def. */
369 static alloc_pool attrs_pool;
371 /* Alloc pool for struct variable_def with MAX_VAR_PARTS entries. */
372 static alloc_pool var_pool;
374 /* Alloc pool for struct variable_def with a single var_part entry. */
375 static alloc_pool valvar_pool;
377 /* Alloc pool for struct location_chain_def. */
378 static alloc_pool loc_chain_pool;
380 /* Alloc pool for struct shared_hash_def. */
381 static alloc_pool shared_hash_pool;
383 /* Alloc pool for struct value_chain_def. */
384 static alloc_pool value_chain_pool;
386 /* Changed variables, notes will be emitted for them. */
387 static htab_t changed_variables;
389 /* Links from VALUEs to DVs referencing them in their current loc_chains. */
390 static htab_t value_chains;
392 /* Shall notes be emitted? */
393 static bool emit_notes;
395 /* Empty shared hashtable. */
396 static shared_hash empty_shared_hash;
398 /* Scratch register bitmap used by cselib_expand_value_rtx. */
399 static bitmap scratch_regs = NULL;
401 /* Variable used to tell whether cselib_process_insn called our hook. */
402 static bool cselib_hook_called;
404 /* Local function prototypes. */
405 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
406 HOST_WIDE_INT *);
407 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
408 HOST_WIDE_INT *);
409 static bool vt_stack_adjustments (void);
410 static rtx compute_cfa_pointer (HOST_WIDE_INT);
411 static hashval_t variable_htab_hash (const void *);
412 static int variable_htab_eq (const void *, const void *);
413 static void variable_htab_free (void *);
415 static void init_attrs_list_set (attrs *);
416 static void attrs_list_clear (attrs *);
417 static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
418 static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
419 static void attrs_list_copy (attrs *, attrs);
420 static void attrs_list_union (attrs *, attrs);
422 static void **unshare_variable (dataflow_set *set, void **slot, variable var,
423 enum var_init_status);
424 static void vars_copy (htab_t, htab_t);
425 static tree var_debug_decl (tree);
426 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
427 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
428 enum var_init_status, rtx);
429 static void var_reg_delete (dataflow_set *, rtx, bool);
430 static void var_regno_delete (dataflow_set *, int);
431 static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
432 static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
433 enum var_init_status, rtx);
434 static void var_mem_delete (dataflow_set *, rtx, bool);
436 static void dataflow_set_init (dataflow_set *);
437 static void dataflow_set_clear (dataflow_set *);
438 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
439 static int variable_union_info_cmp_pos (const void *, const void *);
440 static void dataflow_set_union (dataflow_set *, dataflow_set *);
441 static location_chain find_loc_in_1pdv (rtx, variable, htab_t);
442 static bool canon_value_cmp (rtx, rtx);
443 static int loc_cmp (rtx, rtx);
444 static bool variable_part_different_p (variable_part *, variable_part *);
445 static bool onepart_variable_different_p (variable, variable);
446 static bool variable_different_p (variable, variable);
447 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
448 static void dataflow_set_destroy (dataflow_set *);
450 static bool contains_symbol_ref (rtx);
451 static bool track_expr_p (tree, bool);
452 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
453 static int add_uses (rtx *, void *);
454 static void add_uses_1 (rtx *, void *);
455 static void add_stores (rtx, const_rtx, void *);
456 static bool compute_bb_dataflow (basic_block);
457 static bool vt_find_locations (void);
459 static void dump_attrs_list (attrs);
460 static int dump_var_slot (void **, void *);
461 static void dump_var (variable);
462 static void dump_vars (htab_t);
463 static void dump_dataflow_set (dataflow_set *);
464 static void dump_dataflow_sets (void);
466 static void variable_was_changed (variable, dataflow_set *);
467 static void **set_slot_part (dataflow_set *, rtx, void **,
468 decl_or_value, HOST_WIDE_INT,
469 enum var_init_status, rtx);
470 static void set_variable_part (dataflow_set *, rtx,
471 decl_or_value, HOST_WIDE_INT,
472 enum var_init_status, rtx, enum insert_option);
473 static void **clobber_slot_part (dataflow_set *, rtx,
474 void **, HOST_WIDE_INT, rtx);
475 static void clobber_variable_part (dataflow_set *, rtx,
476 decl_or_value, HOST_WIDE_INT, rtx);
477 static void **delete_slot_part (dataflow_set *, rtx, void **, HOST_WIDE_INT);
478 static void delete_variable_part (dataflow_set *, rtx,
479 decl_or_value, HOST_WIDE_INT);
480 static int emit_note_insn_var_location (void **, void *);
481 static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash);
482 static int emit_notes_for_differences_1 (void **, void *);
483 static int emit_notes_for_differences_2 (void **, void *);
484 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
485 static void emit_notes_in_bb (basic_block, dataflow_set *);
486 static void vt_emit_notes (void);
488 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
489 static void vt_add_function_parameters (void);
490 static bool vt_initialize (void);
491 static void vt_finalize (void);
493 /* Given a SET, calculate the amount of stack adjustment it contains
494 PRE- and POST-modifying stack pointer.
495 This function is similar to stack_adjust_offset. */
497 static void
498 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
499 HOST_WIDE_INT *post)
501 rtx src = SET_SRC (pattern);
502 rtx dest = SET_DEST (pattern);
503 enum rtx_code code;
505 if (dest == stack_pointer_rtx)
507 /* (set (reg sp) (plus (reg sp) (const_int))) */
508 code = GET_CODE (src);
509 if (! (code == PLUS || code == MINUS)
510 || XEXP (src, 0) != stack_pointer_rtx
511 || !CONST_INT_P (XEXP (src, 1)))
512 return;
514 if (code == MINUS)
515 *post += INTVAL (XEXP (src, 1));
516 else
517 *post -= INTVAL (XEXP (src, 1));
519 else if (MEM_P (dest))
521 /* (set (mem (pre_dec (reg sp))) (foo)) */
522 src = XEXP (dest, 0);
523 code = GET_CODE (src);
525 switch (code)
527 case PRE_MODIFY:
528 case POST_MODIFY:
529 if (XEXP (src, 0) == stack_pointer_rtx)
531 rtx val = XEXP (XEXP (src, 1), 1);
532 /* We handle only adjustments by constant amount. */
533 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
534 CONST_INT_P (val));
536 if (code == PRE_MODIFY)
537 *pre -= INTVAL (val);
538 else
539 *post -= INTVAL (val);
540 break;
542 return;
544 case PRE_DEC:
545 if (XEXP (src, 0) == stack_pointer_rtx)
547 *pre += GET_MODE_SIZE (GET_MODE (dest));
548 break;
550 return;
552 case POST_DEC:
553 if (XEXP (src, 0) == stack_pointer_rtx)
555 *post += GET_MODE_SIZE (GET_MODE (dest));
556 break;
558 return;
560 case PRE_INC:
561 if (XEXP (src, 0) == stack_pointer_rtx)
563 *pre -= GET_MODE_SIZE (GET_MODE (dest));
564 break;
566 return;
568 case POST_INC:
569 if (XEXP (src, 0) == stack_pointer_rtx)
571 *post -= GET_MODE_SIZE (GET_MODE (dest));
572 break;
574 return;
576 default:
577 return;
582 /* Given an INSN, calculate the amount of stack adjustment it contains
583 PRE- and POST-modifying stack pointer. */
585 static void
586 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
587 HOST_WIDE_INT *post)
589 rtx pattern;
591 *pre = 0;
592 *post = 0;
594 pattern = PATTERN (insn);
595 if (RTX_FRAME_RELATED_P (insn))
597 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
598 if (expr)
599 pattern = XEXP (expr, 0);
602 if (GET_CODE (pattern) == SET)
603 stack_adjust_offset_pre_post (pattern, pre, post);
604 else if (GET_CODE (pattern) == PARALLEL
605 || GET_CODE (pattern) == SEQUENCE)
607 int i;
609 /* There may be stack adjustments inside compound insns. Search
610 for them. */
611 for ( i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
612 if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
613 stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i), pre, post);
617 /* Compute stack adjustments for all blocks by traversing DFS tree.
618 Return true when the adjustments on all incoming edges are consistent.
619 Heavily borrowed from pre_and_rev_post_order_compute. */
621 static bool
622 vt_stack_adjustments (void)
624 edge_iterator *stack;
625 int sp;
627 /* Initialize entry block. */
628 VTI (ENTRY_BLOCK_PTR)->visited = true;
629 VTI (ENTRY_BLOCK_PTR)->in.stack_adjust = INCOMING_FRAME_SP_OFFSET;
630 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
632 /* Allocate stack for back-tracking up CFG. */
633 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
634 sp = 0;
636 /* Push the first edge on to the stack. */
637 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
639 while (sp)
641 edge_iterator ei;
642 basic_block src;
643 basic_block dest;
645 /* Look at the edge on the top of the stack. */
646 ei = stack[sp - 1];
647 src = ei_edge (ei)->src;
648 dest = ei_edge (ei)->dest;
650 /* Check if the edge destination has been visited yet. */
651 if (!VTI (dest)->visited)
653 rtx insn;
654 HOST_WIDE_INT pre, post, offset;
655 VTI (dest)->visited = true;
656 VTI (dest)->in.stack_adjust = offset = VTI (src)->out.stack_adjust;
658 if (dest != EXIT_BLOCK_PTR)
659 for (insn = BB_HEAD (dest);
660 insn != NEXT_INSN (BB_END (dest));
661 insn = NEXT_INSN (insn))
662 if (INSN_P (insn))
664 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
665 offset += pre + post;
668 VTI (dest)->out.stack_adjust = offset;
670 if (EDGE_COUNT (dest->succs) > 0)
671 /* Since the DEST node has been visited for the first
672 time, check its successors. */
673 stack[sp++] = ei_start (dest->succs);
675 else
677 /* Check whether the adjustments on the edges are the same. */
678 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
680 free (stack);
681 return false;
684 if (! ei_one_before_end_p (ei))
685 /* Go to the next edge. */
686 ei_next (&stack[sp - 1]);
687 else
688 /* Return to previous level if there are no more edges. */
689 sp--;
693 free (stack);
694 return true;
697 /* Compute a CFA-based value for the stack pointer. */
699 static rtx
700 compute_cfa_pointer (HOST_WIDE_INT adjustment)
702 rtx cfa;
704 #ifdef FRAME_POINTER_CFA_OFFSET
705 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
706 cfa = plus_constant (frame_pointer_rtx, adjustment);
707 #else
708 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
709 cfa = plus_constant (arg_pointer_rtx, adjustment);
710 #endif
712 return cfa;
715 /* Adjustment for hard_frame_pointer_rtx to cfa base reg,
716 or -1 if the replacement shouldn't be done. */
717 static HOST_WIDE_INT hard_frame_pointer_adjustment = -1;
719 /* Data for adjust_mems callback. */
721 struct adjust_mem_data
723 bool store;
724 enum machine_mode mem_mode;
725 HOST_WIDE_INT stack_adjust;
726 rtx side_effects;
729 /* Helper for adjust_mems. Return 1 if *loc is unsuitable for
730 transformation of wider mode arithmetics to narrower mode,
731 -1 if it is suitable and subexpressions shouldn't be
732 traversed and 0 if it is suitable and subexpressions should
733 be traversed. Called through for_each_rtx. */
735 static int
736 use_narrower_mode_test (rtx *loc, void *data)
738 rtx subreg = (rtx) data;
740 if (CONSTANT_P (*loc))
741 return -1;
742 switch (GET_CODE (*loc))
744 case REG:
745 if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0))
746 return 1;
747 return -1;
748 case PLUS:
749 case MINUS:
750 case MULT:
751 return 0;
752 case ASHIFT:
753 if (for_each_rtx (&XEXP (*loc, 0), use_narrower_mode_test, data))
754 return 1;
755 else
756 return -1;
757 default:
758 return 1;
762 /* Transform X into narrower mode MODE from wider mode WMODE. */
764 static rtx
765 use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode)
767 rtx op0, op1;
768 if (CONSTANT_P (x))
769 return lowpart_subreg (mode, x, wmode);
770 switch (GET_CODE (x))
772 case REG:
773 return lowpart_subreg (mode, x, wmode);
774 case PLUS:
775 case MINUS:
776 case MULT:
777 op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
778 op1 = use_narrower_mode (XEXP (x, 1), mode, wmode);
779 return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
780 case ASHIFT:
781 op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
782 return simplify_gen_binary (ASHIFT, mode, op0, XEXP (x, 1));
783 default:
784 gcc_unreachable ();
788 /* Helper function for adjusting used MEMs. */
790 static rtx
791 adjust_mems (rtx loc, const_rtx old_rtx, void *data)
793 struct adjust_mem_data *amd = (struct adjust_mem_data *) data;
794 rtx mem, addr = loc, tem;
795 enum machine_mode mem_mode_save;
796 bool store_save;
797 switch (GET_CODE (loc))
799 case REG:
800 /* Don't do any sp or fp replacements outside of MEM addresses
801 on the LHS. */
802 if (amd->mem_mode == VOIDmode && amd->store)
803 return loc;
804 if (loc == stack_pointer_rtx
805 && !frame_pointer_needed)
806 return compute_cfa_pointer (amd->stack_adjust);
807 else if (loc == hard_frame_pointer_rtx
808 && frame_pointer_needed
809 && hard_frame_pointer_adjustment != -1)
810 return compute_cfa_pointer (hard_frame_pointer_adjustment);
811 return loc;
812 case MEM:
813 mem = loc;
814 if (!amd->store)
816 mem = targetm.delegitimize_address (mem);
817 if (mem != loc && !MEM_P (mem))
818 return simplify_replace_fn_rtx (mem, old_rtx, adjust_mems, data);
821 addr = XEXP (mem, 0);
822 mem_mode_save = amd->mem_mode;
823 amd->mem_mode = GET_MODE (mem);
824 store_save = amd->store;
825 amd->store = false;
826 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
827 amd->store = store_save;
828 amd->mem_mode = mem_mode_save;
829 if (mem == loc)
830 addr = targetm.delegitimize_address (addr);
831 if (addr != XEXP (mem, 0))
832 mem = replace_equiv_address_nv (mem, addr);
833 if (!amd->store)
834 mem = avoid_constant_pool_reference (mem);
835 return mem;
836 case PRE_INC:
837 case PRE_DEC:
838 addr = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
839 GEN_INT (GET_CODE (loc) == PRE_INC
840 ? GET_MODE_SIZE (amd->mem_mode)
841 : -GET_MODE_SIZE (amd->mem_mode)));
842 case POST_INC:
843 case POST_DEC:
844 if (addr == loc)
845 addr = XEXP (loc, 0);
846 gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
847 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
848 tem = gen_rtx_PLUS (GET_MODE (loc), XEXP (loc, 0),
849 GEN_INT ((GET_CODE (loc) == PRE_INC
850 || GET_CODE (loc) == POST_INC)
851 ? GET_MODE_SIZE (amd->mem_mode)
852 : -GET_MODE_SIZE (amd->mem_mode)));
853 amd->side_effects = alloc_EXPR_LIST (0,
854 gen_rtx_SET (VOIDmode,
855 XEXP (loc, 0),
856 tem),
857 amd->side_effects);
858 return addr;
859 case PRE_MODIFY:
860 addr = XEXP (loc, 1);
861 case POST_MODIFY:
862 if (addr == loc)
863 addr = XEXP (loc, 0);
864 gcc_assert (amd->mem_mode != VOIDmode);
865 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
866 amd->side_effects = alloc_EXPR_LIST (0,
867 gen_rtx_SET (VOIDmode,
868 XEXP (loc, 0),
869 XEXP (loc, 1)),
870 amd->side_effects);
871 return addr;
872 case SUBREG:
873 /* First try without delegitimization of whole MEMs and
874 avoid_constant_pool_reference, which is more likely to succeed. */
875 store_save = amd->store;
876 amd->store = true;
877 addr = simplify_replace_fn_rtx (SUBREG_REG (loc), old_rtx, adjust_mems,
878 data);
879 amd->store = store_save;
880 mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
881 if (mem == SUBREG_REG (loc))
883 tem = loc;
884 goto finish_subreg;
886 tem = simplify_gen_subreg (GET_MODE (loc), mem,
887 GET_MODE (SUBREG_REG (loc)),
888 SUBREG_BYTE (loc));
889 if (tem)
890 goto finish_subreg;
891 tem = simplify_gen_subreg (GET_MODE (loc), addr,
892 GET_MODE (SUBREG_REG (loc)),
893 SUBREG_BYTE (loc));
894 if (tem == NULL_RTX)
895 tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
896 finish_subreg:
897 if (MAY_HAVE_DEBUG_INSNS
898 && GET_CODE (tem) == SUBREG
899 && (GET_CODE (SUBREG_REG (tem)) == PLUS
900 || GET_CODE (SUBREG_REG (tem)) == MINUS
901 || GET_CODE (SUBREG_REG (tem)) == MULT
902 || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
903 && GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
904 && GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
905 && GET_MODE_SIZE (GET_MODE (tem))
906 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tem)))
907 && subreg_lowpart_p (tem)
908 && !for_each_rtx (&SUBREG_REG (tem), use_narrower_mode_test, tem))
909 return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
910 GET_MODE (SUBREG_REG (tem)));
911 return tem;
912 case ASM_OPERANDS:
913 /* Don't do any replacements in second and following
914 ASM_OPERANDS of inline-asm with multiple sets.
915 ASM_OPERANDS_INPUT_VEC, ASM_OPERANDS_INPUT_CONSTRAINT_VEC
916 and ASM_OPERANDS_LABEL_VEC need to be equal between
917 all the ASM_OPERANDs in the insn and adjust_insn will
918 fix this up. */
919 if (ASM_OPERANDS_OUTPUT_IDX (loc) != 0)
920 return loc;
921 break;
922 default:
923 break;
925 return NULL_RTX;
928 /* Helper function for replacement of uses. */
930 static void
931 adjust_mem_uses (rtx *x, void *data)
933 rtx new_x = simplify_replace_fn_rtx (*x, NULL_RTX, adjust_mems, data);
934 if (new_x != *x)
935 validate_change (NULL_RTX, x, new_x, true);
938 /* Helper function for replacement of stores. */
940 static void
941 adjust_mem_stores (rtx loc, const_rtx expr, void *data)
943 if (MEM_P (loc))
945 rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr), NULL_RTX,
946 adjust_mems, data);
947 if (new_dest != SET_DEST (expr))
949 rtx xexpr = CONST_CAST_RTX (expr);
950 validate_change (NULL_RTX, &SET_DEST (xexpr), new_dest, true);
955 /* Simplify INSN. Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes,
956 replace them with their value in the insn and add the side-effects
957 as other sets to the insn. */
959 static void
960 adjust_insn (basic_block bb, rtx insn)
962 struct adjust_mem_data amd;
963 rtx set;
964 amd.mem_mode = VOIDmode;
965 amd.stack_adjust = -VTI (bb)->out.stack_adjust;
966 amd.side_effects = NULL_RTX;
968 amd.store = true;
969 note_stores (PATTERN (insn), adjust_mem_stores, &amd);
971 amd.store = false;
972 if (GET_CODE (PATTERN (insn)) == PARALLEL
973 && asm_noperands (PATTERN (insn)) > 0
974 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
976 rtx body, set0;
977 int i;
979 /* inline-asm with multiple sets is tiny bit more complicated,
980 because the 3 vectors in ASM_OPERANDS need to be shared between
981 all ASM_OPERANDS in the instruction. adjust_mems will
982 not touch ASM_OPERANDS other than the first one, asm_noperands
983 test above needs to be called before that (otherwise it would fail)
984 and afterwards this code fixes it up. */
985 note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
986 body = PATTERN (insn);
987 set0 = XVECEXP (body, 0, 0);
988 #ifdef ENABLE_CHECKING
989 gcc_assert (GET_CODE (set0) == SET
990 && GET_CODE (SET_SRC (set0)) == ASM_OPERANDS
991 && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set0)) == 0);
992 #endif
993 for (i = 1; i < XVECLEN (body, 0); i++)
994 if (GET_CODE (XVECEXP (body, 0, i)) != SET)
995 break;
996 else
998 set = XVECEXP (body, 0, i);
999 #ifdef ENABLE_CHECKING
1000 gcc_assert (GET_CODE (SET_SRC (set)) == ASM_OPERANDS
1001 && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set)) == i);
1002 #endif
1003 if (ASM_OPERANDS_INPUT_VEC (SET_SRC (set))
1004 != ASM_OPERANDS_INPUT_VEC (SET_SRC (set0))
1005 || ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set))
1006 != ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0))
1007 || ASM_OPERANDS_LABEL_VEC (SET_SRC (set))
1008 != ASM_OPERANDS_LABEL_VEC (SET_SRC (set0)))
1010 rtx newsrc = shallow_copy_rtx (SET_SRC (set));
1011 ASM_OPERANDS_INPUT_VEC (newsrc)
1012 = ASM_OPERANDS_INPUT_VEC (SET_SRC (set0));
1013 ASM_OPERANDS_INPUT_CONSTRAINT_VEC (newsrc)
1014 = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0));
1015 ASM_OPERANDS_LABEL_VEC (newsrc)
1016 = ASM_OPERANDS_LABEL_VEC (SET_SRC (set0));
1017 validate_change (NULL_RTX, &SET_SRC (set), newsrc, true);
1021 else
1022 note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
1024 /* For read-only MEMs containing some constant, prefer those
1025 constants. */
1026 set = single_set (insn);
1027 if (set && MEM_P (SET_SRC (set)) && MEM_READONLY_P (SET_SRC (set)))
1029 rtx note = find_reg_equal_equiv_note (insn);
1031 if (note && CONSTANT_P (XEXP (note, 0)))
1032 validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true);
1035 if (amd.side_effects)
1037 rtx *pat, new_pat, s;
1038 int i, oldn, newn;
1040 pat = &PATTERN (insn);
1041 if (GET_CODE (*pat) == COND_EXEC)
1042 pat = &COND_EXEC_CODE (*pat);
1043 if (GET_CODE (*pat) == PARALLEL)
1044 oldn = XVECLEN (*pat, 0);
1045 else
1046 oldn = 1;
1047 for (s = amd.side_effects, newn = 0; s; newn++)
1048 s = XEXP (s, 1);
1049 new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn));
1050 if (GET_CODE (*pat) == PARALLEL)
1051 for (i = 0; i < oldn; i++)
1052 XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i);
1053 else
1054 XVECEXP (new_pat, 0, 0) = *pat;
1055 for (s = amd.side_effects, i = oldn; i < oldn + newn; i++, s = XEXP (s, 1))
1056 XVECEXP (new_pat, 0, i) = XEXP (s, 0);
1057 free_EXPR_LIST_list (&amd.side_effects);
1058 validate_change (NULL_RTX, pat, new_pat, true);
1062 /* Return true if a decl_or_value DV is a DECL or NULL. */
1063 static inline bool
1064 dv_is_decl_p (decl_or_value dv)
1066 return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE;
1069 /* Return true if a decl_or_value is a VALUE rtl. */
1070 static inline bool
1071 dv_is_value_p (decl_or_value dv)
1073 return dv && !dv_is_decl_p (dv);
1076 /* Return the decl in the decl_or_value. */
1077 static inline tree
1078 dv_as_decl (decl_or_value dv)
1080 #ifdef ENABLE_CHECKING
1081 gcc_assert (dv_is_decl_p (dv));
1082 #endif
1083 return (tree) dv;
1086 /* Return the value in the decl_or_value. */
1087 static inline rtx
1088 dv_as_value (decl_or_value dv)
1090 #ifdef ENABLE_CHECKING
1091 gcc_assert (dv_is_value_p (dv));
1092 #endif
1093 return (rtx)dv;
1096 /* Return the opaque pointer in the decl_or_value. */
1097 static inline void *
1098 dv_as_opaque (decl_or_value dv)
1100 return dv;
1103 /* Return true if a decl_or_value must not have more than one variable
1104 part. */
1105 static inline bool
1106 dv_onepart_p (decl_or_value dv)
1108 tree decl;
1110 if (!MAY_HAVE_DEBUG_INSNS)
1111 return false;
1113 if (dv_is_value_p (dv))
1114 return true;
1116 decl = dv_as_decl (dv);
1118 if (!decl)
1119 return true;
1121 if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
1122 return true;
1124 return (target_for_debug_bind (decl) != NULL_TREE);
1127 /* Return the variable pool to be used for dv, depending on whether it
1128 can have multiple parts or not. */
1129 static inline alloc_pool
1130 dv_pool (decl_or_value dv)
1132 return dv_onepart_p (dv) ? valvar_pool : var_pool;
1135 /* Build a decl_or_value out of a decl. */
1136 static inline decl_or_value
1137 dv_from_decl (tree decl)
1139 decl_or_value dv;
1140 dv = decl;
1141 #ifdef ENABLE_CHECKING
1142 gcc_assert (dv_is_decl_p (dv));
1143 #endif
1144 return dv;
1147 /* Build a decl_or_value out of a value. */
1148 static inline decl_or_value
1149 dv_from_value (rtx value)
1151 decl_or_value dv;
1152 dv = value;
1153 #ifdef ENABLE_CHECKING
1154 gcc_assert (dv_is_value_p (dv));
1155 #endif
1156 return dv;
1159 extern void debug_dv (decl_or_value dv);
1161 void
1162 debug_dv (decl_or_value dv)
1164 if (dv_is_value_p (dv))
1165 debug_rtx (dv_as_value (dv));
1166 else
1167 debug_generic_stmt (dv_as_decl (dv));
1170 typedef unsigned int dvuid;
1172 /* Return the uid of DV. */
1174 static inline dvuid
1175 dv_uid (decl_or_value dv)
1177 if (dv_is_value_p (dv))
1178 return CSELIB_VAL_PTR (dv_as_value (dv))->uid;
1179 else
1180 return DECL_UID (dv_as_decl (dv));
1183 /* Compute the hash from the uid. */
1185 static inline hashval_t
1186 dv_uid2hash (dvuid uid)
1188 return uid;
1191 /* The hash function for a mask table in a shared_htab chain. */
1193 static inline hashval_t
1194 dv_htab_hash (decl_or_value dv)
1196 return dv_uid2hash (dv_uid (dv));
1199 /* The hash function for variable_htab, computes the hash value
1200 from the declaration of variable X. */
1202 static hashval_t
1203 variable_htab_hash (const void *x)
1205 const_variable const v = (const_variable) x;
1207 return dv_htab_hash (v->dv);
1210 /* Compare the declaration of variable X with declaration Y. */
1212 static int
1213 variable_htab_eq (const void *x, const void *y)
1215 const_variable const v = (const_variable) x;
1216 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
1218 return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
1221 /* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
1223 static void
1224 variable_htab_free (void *elem)
1226 int i;
1227 variable var = (variable) elem;
1228 location_chain node, next;
1230 gcc_assert (var->refcount > 0);
1232 var->refcount--;
1233 if (var->refcount > 0)
1234 return;
1236 for (i = 0; i < var->n_var_parts; i++)
1238 for (node = var->var_part[i].loc_chain; node; node = next)
1240 next = node->next;
1241 pool_free (loc_chain_pool, node);
1243 var->var_part[i].loc_chain = NULL;
1245 pool_free (dv_pool (var->dv), var);
1248 /* The hash function for value_chains htab, computes the hash value
1249 from the VALUE. */
1251 static hashval_t
1252 value_chain_htab_hash (const void *x)
1254 const_value_chain const v = (const_value_chain) x;
1256 return dv_htab_hash (v->dv);
1259 /* Compare the VALUE X with VALUE Y. */
1261 static int
1262 value_chain_htab_eq (const void *x, const void *y)
1264 const_value_chain const v = (const_value_chain) x;
1265 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
1267 return dv_as_opaque (v->dv) == dv_as_opaque (dv);
1270 /* Initialize the set (array) SET of attrs to empty lists. */
1272 static void
1273 init_attrs_list_set (attrs *set)
1275 int i;
1277 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1278 set[i] = NULL;
1281 /* Make the list *LISTP empty. */
1283 static void
1284 attrs_list_clear (attrs *listp)
1286 attrs list, next;
1288 for (list = *listp; list; list = next)
1290 next = list->next;
1291 pool_free (attrs_pool, list);
1293 *listp = NULL;
1296 /* Return true if the pair of DECL and OFFSET is the member of the LIST. */
1298 static attrs
1299 attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
1301 for (; list; list = list->next)
1302 if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
1303 return list;
1304 return NULL;
1307 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
1309 static void
1310 attrs_list_insert (attrs *listp, decl_or_value dv,
1311 HOST_WIDE_INT offset, rtx loc)
1313 attrs list;
1315 list = (attrs) pool_alloc (attrs_pool);
1316 list->loc = loc;
1317 list->dv = dv;
1318 list->offset = offset;
1319 list->next = *listp;
1320 *listp = list;
1323 /* Copy all nodes from SRC and create a list *DSTP of the copies. */
1325 static void
1326 attrs_list_copy (attrs *dstp, attrs src)
1328 attrs n;
1330 attrs_list_clear (dstp);
1331 for (; src; src = src->next)
1333 n = (attrs) pool_alloc (attrs_pool);
1334 n->loc = src->loc;
1335 n->dv = src->dv;
1336 n->offset = src->offset;
1337 n->next = *dstp;
1338 *dstp = n;
1342 /* Add all nodes from SRC which are not in *DSTP to *DSTP. */
1344 static void
1345 attrs_list_union (attrs *dstp, attrs src)
1347 for (; src; src = src->next)
1349 if (!attrs_list_member (*dstp, src->dv, src->offset))
1350 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1354 /* Combine nodes that are not onepart nodes from SRC and SRC2 into
1355 *DSTP. */
1357 static void
1358 attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
1360 gcc_assert (!*dstp);
1361 for (; src; src = src->next)
1363 if (!dv_onepart_p (src->dv))
1364 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1366 for (src = src2; src; src = src->next)
1368 if (!dv_onepart_p (src->dv)
1369 && !attrs_list_member (*dstp, src->dv, src->offset))
1370 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1374 /* Shared hashtable support. */
1376 /* Return true if VARS is shared. */
1378 static inline bool
1379 shared_hash_shared (shared_hash vars)
1381 return vars->refcount > 1;
1384 /* Return the hash table for VARS. */
1386 static inline htab_t
1387 shared_hash_htab (shared_hash vars)
1389 return vars->htab;
1392 /* Return true if VAR is shared, or maybe because VARS is shared. */
1394 static inline bool
1395 shared_var_p (variable var, shared_hash vars)
1397 /* Don't count an entry in the changed_variables table as a duplicate. */
1398 return ((var->refcount > 1 + (int) var->in_changed_variables)
1399 || shared_hash_shared (vars));
1402 /* Copy variables into a new hash table. */
1404 static shared_hash
1405 shared_hash_unshare (shared_hash vars)
1407 shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
1408 gcc_assert (vars->refcount > 1);
1409 new_vars->refcount = 1;
1410 new_vars->htab
1411 = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
1412 variable_htab_eq, variable_htab_free);
1413 vars_copy (new_vars->htab, vars->htab);
1414 vars->refcount--;
1415 return new_vars;
1418 /* Increment reference counter on VARS and return it. */
1420 static inline shared_hash
1421 shared_hash_copy (shared_hash vars)
1423 vars->refcount++;
1424 return vars;
1427 /* Decrement reference counter and destroy hash table if not shared
1428 anymore. */
1430 static void
1431 shared_hash_destroy (shared_hash vars)
1433 gcc_assert (vars->refcount > 0);
1434 if (--vars->refcount == 0)
1436 htab_delete (vars->htab);
1437 pool_free (shared_hash_pool, vars);
1441 /* Unshare *PVARS if shared and return slot for DV. If INS is
1442 INSERT, insert it if not already present. */
1444 static inline void **
1445 shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
1446 hashval_t dvhash, enum insert_option ins)
1448 if (shared_hash_shared (*pvars))
1449 *pvars = shared_hash_unshare (*pvars);
1450 return htab_find_slot_with_hash (shared_hash_htab (*pvars), dv, dvhash, ins);
1453 static inline void **
1454 shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
1455 enum insert_option ins)
1457 return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
1460 /* Return slot for DV, if it is already present in the hash table.
1461 If it is not present, insert it only VARS is not shared, otherwise
1462 return NULL. */
1464 static inline void **
1465 shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
1467 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
1468 shared_hash_shared (vars)
1469 ? NO_INSERT : INSERT);
1472 static inline void **
1473 shared_hash_find_slot (shared_hash vars, decl_or_value dv)
1475 return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
1478 /* Return slot for DV only if it is already present in the hash table. */
1480 static inline void **
1481 shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
1482 hashval_t dvhash)
1484 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash,
1485 NO_INSERT);
1488 static inline void **
1489 shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
1491 return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
1494 /* Return variable for DV or NULL if not already present in the hash
1495 table. */
1497 static inline variable
1498 shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
1500 return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash);
1503 static inline variable
1504 shared_hash_find (shared_hash vars, decl_or_value dv)
1506 return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
1509 /* Return true if TVAL is better than CVAL as a canonival value. We
1510 choose lowest-numbered VALUEs, using the RTX address as a
1511 tie-breaker. The idea is to arrange them into a star topology,
1512 such that all of them are at most one step away from the canonical
1513 value, and the canonical value has backlinks to all of them, in
1514 addition to all the actual locations. We don't enforce this
1515 topology throughout the entire dataflow analysis, though.
1518 static inline bool
1519 canon_value_cmp (rtx tval, rtx cval)
1521 return !cval
1522 || CSELIB_VAL_PTR (tval)->uid < CSELIB_VAL_PTR (cval)->uid;
1525 static bool dst_can_be_shared;
1527 /* Return a copy of a variable VAR and insert it to dataflow set SET. */
1529 static void **
1530 unshare_variable (dataflow_set *set, void **slot, variable var,
1531 enum var_init_status initialized)
1533 variable new_var;
1534 int i;
1536 new_var = (variable) pool_alloc (dv_pool (var->dv));
1537 new_var->dv = var->dv;
1538 new_var->refcount = 1;
1539 var->refcount--;
1540 new_var->n_var_parts = var->n_var_parts;
1541 new_var->cur_loc_changed = var->cur_loc_changed;
1542 var->cur_loc_changed = false;
1543 new_var->in_changed_variables = false;
1545 if (! flag_var_tracking_uninit)
1546 initialized = VAR_INIT_STATUS_INITIALIZED;
1548 for (i = 0; i < var->n_var_parts; i++)
1550 location_chain node;
1551 location_chain *nextp;
1553 new_var->var_part[i].offset = var->var_part[i].offset;
1554 nextp = &new_var->var_part[i].loc_chain;
1555 for (node = var->var_part[i].loc_chain; node; node = node->next)
1557 location_chain new_lc;
1559 new_lc = (location_chain) pool_alloc (loc_chain_pool);
1560 new_lc->next = NULL;
1561 if (node->init > initialized)
1562 new_lc->init = node->init;
1563 else
1564 new_lc->init = initialized;
1565 if (node->set_src && !(MEM_P (node->set_src)))
1566 new_lc->set_src = node->set_src;
1567 else
1568 new_lc->set_src = NULL;
1569 new_lc->loc = node->loc;
1571 *nextp = new_lc;
1572 nextp = &new_lc->next;
1575 new_var->var_part[i].cur_loc = var->var_part[i].cur_loc;
1578 dst_can_be_shared = false;
1579 if (shared_hash_shared (set->vars))
1580 slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT);
1581 else if (set->traversed_vars && set->vars != set->traversed_vars)
1582 slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
1583 *slot = new_var;
1584 if (var->in_changed_variables)
1586 void **cslot
1587 = htab_find_slot_with_hash (changed_variables, var->dv,
1588 dv_htab_hash (var->dv), NO_INSERT);
1589 gcc_assert (*cslot == (void *) var);
1590 var->in_changed_variables = false;
1591 variable_htab_free (var);
1592 *cslot = new_var;
1593 new_var->in_changed_variables = true;
1595 return slot;
1598 /* Copy all variables from hash table SRC to hash table DST. */
1600 static void
1601 vars_copy (htab_t dst, htab_t src)
1603 htab_iterator hi;
1604 variable var;
1606 FOR_EACH_HTAB_ELEMENT (src, var, variable, hi)
1608 void **dstp;
1609 var->refcount++;
1610 dstp = htab_find_slot_with_hash (dst, var->dv,
1611 dv_htab_hash (var->dv),
1612 INSERT);
1613 *dstp = var;
1617 /* Map a decl to its main debug decl. */
1619 static inline tree
1620 var_debug_decl (tree decl)
1622 if (decl && DECL_P (decl)
1623 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
1624 && DECL_P (DECL_DEBUG_EXPR (decl)))
1625 decl = DECL_DEBUG_EXPR (decl);
1627 return decl;
1630 /* Set the register LOC to contain DV, OFFSET. */
1632 static void
1633 var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1634 decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1635 enum insert_option iopt)
1637 attrs node;
1638 bool decl_p = dv_is_decl_p (dv);
1640 if (decl_p)
1641 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1643 for (node = set->regs[REGNO (loc)]; node; node = node->next)
1644 if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
1645 && node->offset == offset)
1646 break;
1647 if (!node)
1648 attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc);
1649 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1652 /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
1654 static void
1655 var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1656 rtx set_src)
1658 tree decl = REG_EXPR (loc);
1659 HOST_WIDE_INT offset = REG_OFFSET (loc);
1661 var_reg_decl_set (set, loc, initialized,
1662 dv_from_decl (decl), offset, set_src, INSERT);
1665 static enum var_init_status
1666 get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
1668 variable var;
1669 int i;
1670 enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
1672 if (! flag_var_tracking_uninit)
1673 return VAR_INIT_STATUS_INITIALIZED;
1675 var = shared_hash_find (set->vars, dv);
1676 if (var)
1678 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
1680 location_chain nextp;
1681 for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1682 if (rtx_equal_p (nextp->loc, loc))
1684 ret_val = nextp->init;
1685 break;
1690 return ret_val;
1693 /* Delete current content of register LOC in dataflow set SET and set
1694 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
1695 MODIFY is true, any other live copies of the same variable part are
1696 also deleted from the dataflow set, otherwise the variable part is
1697 assumed to be copied from another location holding the same
1698 part. */
1700 static void
1701 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1702 enum var_init_status initialized, rtx set_src)
1704 tree decl = REG_EXPR (loc);
1705 HOST_WIDE_INT offset = REG_OFFSET (loc);
1706 attrs node, next;
1707 attrs *nextp;
1709 decl = var_debug_decl (decl);
1711 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1712 initialized = get_init_value (set, loc, dv_from_decl (decl));
1714 nextp = &set->regs[REGNO (loc)];
1715 for (node = *nextp; node; node = next)
1717 next = node->next;
1718 if (dv_as_opaque (node->dv) != decl || node->offset != offset)
1720 delete_variable_part (set, node->loc, node->dv, node->offset);
1721 pool_free (attrs_pool, node);
1722 *nextp = next;
1724 else
1726 node->loc = loc;
1727 nextp = &node->next;
1730 if (modify)
1731 clobber_variable_part (set, loc, dv_from_decl (decl), offset, set_src);
1732 var_reg_set (set, loc, initialized, set_src);
1735 /* Delete the association of register LOC in dataflow set SET with any
1736 variables that aren't onepart. If CLOBBER is true, also delete any
1737 other live copies of the same variable part, and delete the
1738 association with onepart dvs too. */
1740 static void
1741 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
1743 attrs *nextp = &set->regs[REGNO (loc)];
1744 attrs node, next;
1746 if (clobber)
1748 tree decl = REG_EXPR (loc);
1749 HOST_WIDE_INT offset = REG_OFFSET (loc);
1751 decl = var_debug_decl (decl);
1753 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
1756 for (node = *nextp; node; node = next)
1758 next = node->next;
1759 if (clobber || !dv_onepart_p (node->dv))
1761 delete_variable_part (set, node->loc, node->dv, node->offset);
1762 pool_free (attrs_pool, node);
1763 *nextp = next;
1765 else
1766 nextp = &node->next;
1770 /* Delete content of register with number REGNO in dataflow set SET. */
1772 static void
1773 var_regno_delete (dataflow_set *set, int regno)
1775 attrs *reg = &set->regs[regno];
1776 attrs node, next;
1778 for (node = *reg; node; node = next)
1780 next = node->next;
1781 delete_variable_part (set, node->loc, node->dv, node->offset);
1782 pool_free (attrs_pool, node);
1784 *reg = NULL;
1787 /* Set the location of DV, OFFSET as the MEM LOC. */
1789 static void
1790 var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1791 decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
1792 enum insert_option iopt)
1794 if (dv_is_decl_p (dv))
1795 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1797 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1800 /* Set the location part of variable MEM_EXPR (LOC) in dataflow set
1801 SET to LOC.
1802 Adjust the address first if it is stack pointer based. */
1804 static void
1805 var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1806 rtx set_src)
1808 tree decl = MEM_EXPR (loc);
1809 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1811 var_mem_decl_set (set, loc, initialized,
1812 dv_from_decl (decl), offset, set_src, INSERT);
1815 /* Delete and set the location part of variable MEM_EXPR (LOC) in
1816 dataflow set SET to LOC. If MODIFY is true, any other live copies
1817 of the same variable part are also deleted from the dataflow set,
1818 otherwise the variable part is assumed to be copied from another
1819 location holding the same part.
1820 Adjust the address first if it is stack pointer based. */
1822 static void
1823 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1824 enum var_init_status initialized, rtx set_src)
1826 tree decl = MEM_EXPR (loc);
1827 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1829 decl = var_debug_decl (decl);
1831 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1832 initialized = get_init_value (set, loc, dv_from_decl (decl));
1834 if (modify)
1835 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, set_src);
1836 var_mem_set (set, loc, initialized, set_src);
1839 /* Delete the location part LOC from dataflow set SET. If CLOBBER is
1840 true, also delete any other live copies of the same variable part.
1841 Adjust the address first if it is stack pointer based. */
1843 static void
1844 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
1846 tree decl = MEM_EXPR (loc);
1847 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
1849 decl = var_debug_decl (decl);
1850 if (clobber)
1851 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
1852 delete_variable_part (set, loc, dv_from_decl (decl), offset);
1855 /* Bind a value to a location it was just stored in. If MODIFIED
1856 holds, assume the location was modified, detaching it from any
1857 values bound to it. */
1859 static void
1860 val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
1862 cselib_val *v = CSELIB_VAL_PTR (val);
1864 gcc_assert (cselib_preserved_value_p (v));
1866 if (dump_file)
1868 fprintf (dump_file, "%i: ", INSN_UID (insn));
1869 print_inline_rtx (dump_file, val, 0);
1870 fprintf (dump_file, " stored in ");
1871 print_inline_rtx (dump_file, loc, 0);
1872 if (v->locs)
1874 struct elt_loc_list *l;
1875 for (l = v->locs; l; l = l->next)
1877 fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn));
1878 print_inline_rtx (dump_file, l->loc, 0);
1881 fprintf (dump_file, "\n");
1884 if (REG_P (loc))
1886 if (modified)
1887 var_regno_delete (set, REGNO (loc));
1888 var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1889 dv_from_value (val), 0, NULL_RTX, INSERT);
1891 else if (MEM_P (loc))
1892 var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
1893 dv_from_value (val), 0, NULL_RTX, INSERT);
1894 else
1895 set_variable_part (set, loc, dv_from_value (val), 0,
1896 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
1899 /* Reset this node, detaching all its equivalences. Return the slot
1900 in the variable hash table that holds dv, if there is one. */
1902 static void
1903 val_reset (dataflow_set *set, decl_or_value dv)
1905 variable var = shared_hash_find (set->vars, dv) ;
1906 location_chain node;
1907 rtx cval;
1909 if (!var || !var->n_var_parts)
1910 return;
1912 gcc_assert (var->n_var_parts == 1);
1914 cval = NULL;
1915 for (node = var->var_part[0].loc_chain; node; node = node->next)
1916 if (GET_CODE (node->loc) == VALUE
1917 && canon_value_cmp (node->loc, cval))
1918 cval = node->loc;
1920 for (node = var->var_part[0].loc_chain; node; node = node->next)
1921 if (GET_CODE (node->loc) == VALUE && cval != node->loc)
1923 /* Redirect the equivalence link to the new canonical
1924 value, or simply remove it if it would point at
1925 itself. */
1926 if (cval)
1927 set_variable_part (set, cval, dv_from_value (node->loc),
1928 0, node->init, node->set_src, NO_INSERT);
1929 delete_variable_part (set, dv_as_value (dv),
1930 dv_from_value (node->loc), 0);
1933 if (cval)
1935 decl_or_value cdv = dv_from_value (cval);
1937 /* Keep the remaining values connected, accummulating links
1938 in the canonical value. */
1939 for (node = var->var_part[0].loc_chain; node; node = node->next)
1941 if (node->loc == cval)
1942 continue;
1943 else if (GET_CODE (node->loc) == REG)
1944 var_reg_decl_set (set, node->loc, node->init, cdv, 0,
1945 node->set_src, NO_INSERT);
1946 else if (GET_CODE (node->loc) == MEM)
1947 var_mem_decl_set (set, node->loc, node->init, cdv, 0,
1948 node->set_src, NO_INSERT);
1949 else
1950 set_variable_part (set, node->loc, cdv, 0,
1951 node->init, node->set_src, NO_INSERT);
1955 /* We remove this last, to make sure that the canonical value is not
1956 removed to the point of requiring reinsertion. */
1957 if (cval)
1958 delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
1960 clobber_variable_part (set, NULL, dv, 0, NULL);
1962 /* ??? Should we make sure there aren't other available values or
1963 variables whose values involve this one other than by
1964 equivalence? E.g., at the very least we should reset MEMs, those
1965 shouldn't be too hard to find cselib-looking up the value as an
1966 address, then locating the resulting value in our own hash
1967 table. */
1970 /* Find the values in a given location and map the val to another
1971 value, if it is unique, or add the location as one holding the
1972 value. */
1974 static void
1975 val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
1977 decl_or_value dv = dv_from_value (val);
1979 if (dump_file && (dump_flags & TDF_DETAILS))
1981 if (insn)
1982 fprintf (dump_file, "%i: ", INSN_UID (insn));
1983 else
1984 fprintf (dump_file, "head: ");
1985 print_inline_rtx (dump_file, val, 0);
1986 fputs (" is at ", dump_file);
1987 print_inline_rtx (dump_file, loc, 0);
1988 fputc ('\n', dump_file);
1991 val_reset (set, dv);
1993 if (REG_P (loc))
1995 attrs node, found = NULL;
1997 for (node = set->regs[REGNO (loc)]; node; node = node->next)
1998 if (dv_is_value_p (node->dv)
1999 && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc))
2001 found = node;
2003 /* Map incoming equivalences. ??? Wouldn't it be nice if
2004 we just started sharing the location lists? Maybe a
2005 circular list ending at the value itself or some
2006 such. */
2007 set_variable_part (set, dv_as_value (node->dv),
2008 dv_from_value (val), node->offset,
2009 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2010 set_variable_part (set, val, node->dv, node->offset,
2011 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2014 /* If we didn't find any equivalence, we need to remember that
2015 this value is held in the named register. */
2016 if (!found)
2017 var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2018 dv_from_value (val), 0, NULL_RTX, INSERT);
2020 else if (MEM_P (loc))
2021 /* ??? Merge equivalent MEMs. */
2022 var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2023 dv_from_value (val), 0, NULL_RTX, INSERT);
2024 else
2025 /* ??? Merge equivalent expressions. */
2026 set_variable_part (set, loc, dv_from_value (val), 0,
2027 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
2030 /* Initialize dataflow set SET to be empty.
2031 VARS_SIZE is the initial size of hash table VARS. */
2033 static void
2034 dataflow_set_init (dataflow_set *set)
2036 init_attrs_list_set (set->regs);
2037 set->vars = shared_hash_copy (empty_shared_hash);
2038 set->stack_adjust = 0;
2039 set->traversed_vars = NULL;
2042 /* Delete the contents of dataflow set SET. */
2044 static void
2045 dataflow_set_clear (dataflow_set *set)
2047 int i;
2049 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2050 attrs_list_clear (&set->regs[i]);
2052 shared_hash_destroy (set->vars);
2053 set->vars = shared_hash_copy (empty_shared_hash);
2056 /* Copy the contents of dataflow set SRC to DST. */
2058 static void
2059 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
2061 int i;
2063 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2064 attrs_list_copy (&dst->regs[i], src->regs[i]);
2066 shared_hash_destroy (dst->vars);
2067 dst->vars = shared_hash_copy (src->vars);
2068 dst->stack_adjust = src->stack_adjust;
2071 /* Information for merging lists of locations for a given offset of variable.
2073 struct variable_union_info
2075 /* Node of the location chain. */
2076 location_chain lc;
2078 /* The sum of positions in the input chains. */
2079 int pos;
2081 /* The position in the chain of DST dataflow set. */
2082 int pos_dst;
2085 /* Buffer for location list sorting and its allocated size. */
2086 static struct variable_union_info *vui_vec;
2087 static int vui_allocated;
2089 /* Compare function for qsort, order the structures by POS element. */
2091 static int
2092 variable_union_info_cmp_pos (const void *n1, const void *n2)
2094 const struct variable_union_info *const i1 =
2095 (const struct variable_union_info *) n1;
2096 const struct variable_union_info *const i2 =
2097 ( const struct variable_union_info *) n2;
2099 if (i1->pos != i2->pos)
2100 return i1->pos - i2->pos;
2102 return (i1->pos_dst - i2->pos_dst);
2105 /* Compute union of location parts of variable *SLOT and the same variable
2106 from hash table DATA. Compute "sorted" union of the location chains
2107 for common offsets, i.e. the locations of a variable part are sorted by
2108 a priority where the priority is the sum of the positions in the 2 chains
2109 (if a location is only in one list the position in the second list is
2110 defined to be larger than the length of the chains).
2111 When we are updating the location parts the newest location is in the
2112 beginning of the chain, so when we do the described "sorted" union
2113 we keep the newest locations in the beginning. */
2115 static int
2116 variable_union (variable src, dataflow_set *set)
2118 variable dst;
2119 void **dstp;
2120 int i, j, k;
2122 dstp = shared_hash_find_slot (set->vars, src->dv);
2123 if (!dstp || !*dstp)
2125 src->refcount++;
2127 dst_can_be_shared = false;
2128 if (!dstp)
2129 dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT);
2131 *dstp = src;
2133 /* Continue traversing the hash table. */
2134 return 1;
2136 else
2137 dst = (variable) *dstp;
2139 gcc_assert (src->n_var_parts);
2141 /* We can combine one-part variables very efficiently, because their
2142 entries are in canonical order. */
2143 if (dv_onepart_p (src->dv))
2145 location_chain *nodep, dnode, snode;
2147 gcc_assert (src->n_var_parts == 1
2148 && dst->n_var_parts == 1);
2150 snode = src->var_part[0].loc_chain;
2151 gcc_assert (snode);
2153 restart_onepart_unshared:
2154 nodep = &dst->var_part[0].loc_chain;
2155 dnode = *nodep;
2156 gcc_assert (dnode);
2158 while (snode)
2160 int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1;
2162 if (r > 0)
2164 location_chain nnode;
2166 if (shared_var_p (dst, set->vars))
2168 dstp = unshare_variable (set, dstp, dst,
2169 VAR_INIT_STATUS_INITIALIZED);
2170 dst = (variable)*dstp;
2171 goto restart_onepart_unshared;
2174 *nodep = nnode = (location_chain) pool_alloc (loc_chain_pool);
2175 nnode->loc = snode->loc;
2176 nnode->init = snode->init;
2177 if (!snode->set_src || MEM_P (snode->set_src))
2178 nnode->set_src = NULL;
2179 else
2180 nnode->set_src = snode->set_src;
2181 nnode->next = dnode;
2182 dnode = nnode;
2184 #ifdef ENABLE_CHECKING
2185 else if (r == 0)
2186 gcc_assert (rtx_equal_p (dnode->loc, snode->loc));
2187 #endif
2189 if (r >= 0)
2190 snode = snode->next;
2192 nodep = &dnode->next;
2193 dnode = *nodep;
2196 return 1;
2199 /* Count the number of location parts, result is K. */
2200 for (i = 0, j = 0, k = 0;
2201 i < src->n_var_parts && j < dst->n_var_parts; k++)
2203 if (src->var_part[i].offset == dst->var_part[j].offset)
2205 i++;
2206 j++;
2208 else if (src->var_part[i].offset < dst->var_part[j].offset)
2209 i++;
2210 else
2211 j++;
2213 k += src->n_var_parts - i;
2214 k += dst->n_var_parts - j;
2216 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2217 thus there are at most MAX_VAR_PARTS different offsets. */
2218 gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS);
2220 if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
2222 dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
2223 dst = (variable)*dstp;
2226 i = src->n_var_parts - 1;
2227 j = dst->n_var_parts - 1;
2228 dst->n_var_parts = k;
2230 for (k--; k >= 0; k--)
2232 location_chain node, node2;
2234 if (i >= 0 && j >= 0
2235 && src->var_part[i].offset == dst->var_part[j].offset)
2237 /* Compute the "sorted" union of the chains, i.e. the locations which
2238 are in both chains go first, they are sorted by the sum of
2239 positions in the chains. */
2240 int dst_l, src_l;
2241 int ii, jj, n;
2242 struct variable_union_info *vui;
2244 /* If DST is shared compare the location chains.
2245 If they are different we will modify the chain in DST with
2246 high probability so make a copy of DST. */
2247 if (shared_var_p (dst, set->vars))
2249 for (node = src->var_part[i].loc_chain,
2250 node2 = dst->var_part[j].loc_chain; node && node2;
2251 node = node->next, node2 = node2->next)
2253 if (!((REG_P (node2->loc)
2254 && REG_P (node->loc)
2255 && REGNO (node2->loc) == REGNO (node->loc))
2256 || rtx_equal_p (node2->loc, node->loc)))
2258 if (node2->init < node->init)
2259 node2->init = node->init;
2260 break;
2263 if (node || node2)
2265 dstp = unshare_variable (set, dstp, dst,
2266 VAR_INIT_STATUS_UNKNOWN);
2267 dst = (variable)*dstp;
2271 src_l = 0;
2272 for (node = src->var_part[i].loc_chain; node; node = node->next)
2273 src_l++;
2274 dst_l = 0;
2275 for (node = dst->var_part[j].loc_chain; node; node = node->next)
2276 dst_l++;
2278 if (dst_l == 1)
2280 /* The most common case, much simpler, no qsort is needed. */
2281 location_chain dstnode = dst->var_part[j].loc_chain;
2282 dst->var_part[k].loc_chain = dstnode;
2283 dst->var_part[k].offset = dst->var_part[j].offset;
2284 node2 = dstnode;
2285 for (node = src->var_part[i].loc_chain; node; node = node->next)
2286 if (!((REG_P (dstnode->loc)
2287 && REG_P (node->loc)
2288 && REGNO (dstnode->loc) == REGNO (node->loc))
2289 || rtx_equal_p (dstnode->loc, node->loc)))
2291 location_chain new_node;
2293 /* Copy the location from SRC. */
2294 new_node = (location_chain) pool_alloc (loc_chain_pool);
2295 new_node->loc = node->loc;
2296 new_node->init = node->init;
2297 if (!node->set_src || MEM_P (node->set_src))
2298 new_node->set_src = NULL;
2299 else
2300 new_node->set_src = node->set_src;
2301 node2->next = new_node;
2302 node2 = new_node;
2304 node2->next = NULL;
2306 else
2308 if (src_l + dst_l > vui_allocated)
2310 vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
2311 vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
2312 vui_allocated);
2314 vui = vui_vec;
2316 /* Fill in the locations from DST. */
2317 for (node = dst->var_part[j].loc_chain, jj = 0; node;
2318 node = node->next, jj++)
2320 vui[jj].lc = node;
2321 vui[jj].pos_dst = jj;
2323 /* Pos plus value larger than a sum of 2 valid positions. */
2324 vui[jj].pos = jj + src_l + dst_l;
2327 /* Fill in the locations from SRC. */
2328 n = dst_l;
2329 for (node = src->var_part[i].loc_chain, ii = 0; node;
2330 node = node->next, ii++)
2332 /* Find location from NODE. */
2333 for (jj = 0; jj < dst_l; jj++)
2335 if ((REG_P (vui[jj].lc->loc)
2336 && REG_P (node->loc)
2337 && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
2338 || rtx_equal_p (vui[jj].lc->loc, node->loc))
2340 vui[jj].pos = jj + ii;
2341 break;
2344 if (jj >= dst_l) /* The location has not been found. */
2346 location_chain new_node;
2348 /* Copy the location from SRC. */
2349 new_node = (location_chain) pool_alloc (loc_chain_pool);
2350 new_node->loc = node->loc;
2351 new_node->init = node->init;
2352 if (!node->set_src || MEM_P (node->set_src))
2353 new_node->set_src = NULL;
2354 else
2355 new_node->set_src = node->set_src;
2356 vui[n].lc = new_node;
2357 vui[n].pos_dst = src_l + dst_l;
2358 vui[n].pos = ii + src_l + dst_l;
2359 n++;
2363 if (dst_l == 2)
2365 /* Special case still very common case. For dst_l == 2
2366 all entries dst_l ... n-1 are sorted, with for i >= dst_l
2367 vui[i].pos == i + src_l + dst_l. */
2368 if (vui[0].pos > vui[1].pos)
2370 /* Order should be 1, 0, 2... */
2371 dst->var_part[k].loc_chain = vui[1].lc;
2372 vui[1].lc->next = vui[0].lc;
2373 if (n >= 3)
2375 vui[0].lc->next = vui[2].lc;
2376 vui[n - 1].lc->next = NULL;
2378 else
2379 vui[0].lc->next = NULL;
2380 ii = 3;
2382 else
2384 dst->var_part[k].loc_chain = vui[0].lc;
2385 if (n >= 3 && vui[2].pos < vui[1].pos)
2387 /* Order should be 0, 2, 1, 3... */
2388 vui[0].lc->next = vui[2].lc;
2389 vui[2].lc->next = vui[1].lc;
2390 if (n >= 4)
2392 vui[1].lc->next = vui[3].lc;
2393 vui[n - 1].lc->next = NULL;
2395 else
2396 vui[1].lc->next = NULL;
2397 ii = 4;
2399 else
2401 /* Order should be 0, 1, 2... */
2402 ii = 1;
2403 vui[n - 1].lc->next = NULL;
2406 for (; ii < n; ii++)
2407 vui[ii - 1].lc->next = vui[ii].lc;
2409 else
2411 qsort (vui, n, sizeof (struct variable_union_info),
2412 variable_union_info_cmp_pos);
2414 /* Reconnect the nodes in sorted order. */
2415 for (ii = 1; ii < n; ii++)
2416 vui[ii - 1].lc->next = vui[ii].lc;
2417 vui[n - 1].lc->next = NULL;
2418 dst->var_part[k].loc_chain = vui[0].lc;
2421 dst->var_part[k].offset = dst->var_part[j].offset;
2423 i--;
2424 j--;
2426 else if ((i >= 0 && j >= 0
2427 && src->var_part[i].offset < dst->var_part[j].offset)
2428 || i < 0)
2430 dst->var_part[k] = dst->var_part[j];
2431 j--;
2433 else if ((i >= 0 && j >= 0
2434 && src->var_part[i].offset > dst->var_part[j].offset)
2435 || j < 0)
2437 location_chain *nextp;
2439 /* Copy the chain from SRC. */
2440 nextp = &dst->var_part[k].loc_chain;
2441 for (node = src->var_part[i].loc_chain; node; node = node->next)
2443 location_chain new_lc;
2445 new_lc = (location_chain) pool_alloc (loc_chain_pool);
2446 new_lc->next = NULL;
2447 new_lc->init = node->init;
2448 if (!node->set_src || MEM_P (node->set_src))
2449 new_lc->set_src = NULL;
2450 else
2451 new_lc->set_src = node->set_src;
2452 new_lc->loc = node->loc;
2454 *nextp = new_lc;
2455 nextp = &new_lc->next;
2458 dst->var_part[k].offset = src->var_part[i].offset;
2459 i--;
2461 dst->var_part[k].cur_loc = NULL;
2464 if (flag_var_tracking_uninit)
2465 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
2467 location_chain node, node2;
2468 for (node = src->var_part[i].loc_chain; node; node = node->next)
2469 for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
2470 if (rtx_equal_p (node->loc, node2->loc))
2472 if (node->init > node2->init)
2473 node2->init = node->init;
2477 /* Continue traversing the hash table. */
2478 return 1;
2481 /* Compute union of dataflow sets SRC and DST and store it to DST. */
2483 static void
2484 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
2486 int i;
2488 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2489 attrs_list_union (&dst->regs[i], src->regs[i]);
2491 if (dst->vars == empty_shared_hash)
2493 shared_hash_destroy (dst->vars);
2494 dst->vars = shared_hash_copy (src->vars);
2496 else
2498 htab_iterator hi;
2499 variable var;
2501 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (src->vars), var, variable, hi)
2502 variable_union (var, dst);
2506 /* Whether the value is currently being expanded. */
2507 #define VALUE_RECURSED_INTO(x) \
2508 (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
2509 /* Whether the value is in changed_variables hash table. */
2510 #define VALUE_CHANGED(x) \
2511 (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
2512 /* Whether the decl is in changed_variables hash table. */
2513 #define DECL_CHANGED(x) TREE_VISITED (x)
2515 /* Record that DV has been added into resp. removed from changed_variables
2516 hashtable. */
2518 static inline void
2519 set_dv_changed (decl_or_value dv, bool newv)
2521 if (dv_is_value_p (dv))
2522 VALUE_CHANGED (dv_as_value (dv)) = newv;
2523 else
2524 DECL_CHANGED (dv_as_decl (dv)) = newv;
2527 /* Return true if DV is present in changed_variables hash table. */
2529 static inline bool
2530 dv_changed_p (decl_or_value dv)
2532 return (dv_is_value_p (dv)
2533 ? VALUE_CHANGED (dv_as_value (dv))
2534 : DECL_CHANGED (dv_as_decl (dv)));
2537 /* Return a location list node whose loc is rtx_equal to LOC, in the
2538 location list of a one-part variable or value VAR, or in that of
2539 any values recursively mentioned in the location lists. VARS must
2540 be in star-canonical form. */
2542 static location_chain
2543 find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
2545 location_chain node;
2546 enum rtx_code loc_code;
2548 if (!var)
2549 return NULL;
2551 #ifdef ENABLE_CHECKING
2552 gcc_assert (dv_onepart_p (var->dv));
2553 #endif
2555 if (!var->n_var_parts)
2556 return NULL;
2558 #ifdef ENABLE_CHECKING
2559 gcc_assert (var->var_part[0].offset == 0);
2560 gcc_assert (loc != dv_as_opaque (var->dv));
2561 #endif
2563 loc_code = GET_CODE (loc);
2564 for (node = var->var_part[0].loc_chain; node; node = node->next)
2566 decl_or_value dv;
2567 variable rvar;
2569 if (GET_CODE (node->loc) != loc_code)
2571 if (GET_CODE (node->loc) != VALUE)
2572 continue;
2574 else if (loc == node->loc)
2575 return node;
2576 else if (loc_code != VALUE)
2578 if (rtx_equal_p (loc, node->loc))
2579 return node;
2580 continue;
2583 /* Since we're in star-canonical form, we don't need to visit
2584 non-canonical nodes: one-part variables and non-canonical
2585 values would only point back to the canonical node. */
2586 if (dv_is_value_p (var->dv)
2587 && !canon_value_cmp (node->loc, dv_as_value (var->dv)))
2589 /* Skip all subsequent VALUEs. */
2590 while (node->next && GET_CODE (node->next->loc) == VALUE)
2592 node = node->next;
2593 #ifdef ENABLE_CHECKING
2594 gcc_assert (!canon_value_cmp (node->loc,
2595 dv_as_value (var->dv)));
2596 #endif
2597 if (loc == node->loc)
2598 return node;
2600 continue;
2603 #ifdef ENABLE_CHECKING
2604 gcc_assert (node == var->var_part[0].loc_chain);
2605 gcc_assert (!node->next);
2606 #endif
2608 dv = dv_from_value (node->loc);
2609 rvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
2610 return find_loc_in_1pdv (loc, rvar, vars);
2613 return NULL;
2616 /* Hash table iteration argument passed to variable_merge. */
2617 struct dfset_merge
2619 /* The set in which the merge is to be inserted. */
2620 dataflow_set *dst;
2621 /* The set that we're iterating in. */
2622 dataflow_set *cur;
2623 /* The set that may contain the other dv we are to merge with. */
2624 dataflow_set *src;
2625 /* Number of onepart dvs in src. */
2626 int src_onepart_cnt;
2629 /* Insert LOC in *DNODE, if it's not there yet. The list must be in
2630 loc_cmp order, and it is maintained as such. */
2632 static void
2633 insert_into_intersection (location_chain *nodep, rtx loc,
2634 enum var_init_status status)
2636 location_chain node;
2637 int r;
2639 for (node = *nodep; node; nodep = &node->next, node = *nodep)
2640 if ((r = loc_cmp (node->loc, loc)) == 0)
2642 node->init = MIN (node->init, status);
2643 return;
2645 else if (r > 0)
2646 break;
2648 node = (location_chain) pool_alloc (loc_chain_pool);
2650 node->loc = loc;
2651 node->set_src = NULL;
2652 node->init = status;
2653 node->next = *nodep;
2654 *nodep = node;
2657 /* Insert in DEST the intersection the locations present in both
2658 S1NODE and S2VAR, directly or indirectly. S1NODE is from a
2659 variable in DSM->cur, whereas S2VAR is from DSM->src. dvar is in
2660 DSM->dst. */
2662 static void
2663 intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
2664 location_chain s1node, variable s2var)
2666 dataflow_set *s1set = dsm->cur;
2667 dataflow_set *s2set = dsm->src;
2668 location_chain found;
2670 if (s2var)
2672 location_chain s2node;
2674 #ifdef ENABLE_CHECKING
2675 gcc_assert (dv_onepart_p (s2var->dv));
2676 #endif
2678 if (s2var->n_var_parts)
2680 #ifdef ENABLE_CHECKING
2681 gcc_assert (s2var->var_part[0].offset == 0);
2682 #endif
2683 s2node = s2var->var_part[0].loc_chain;
2685 for (; s1node && s2node;
2686 s1node = s1node->next, s2node = s2node->next)
2687 if (s1node->loc != s2node->loc)
2688 break;
2689 else if (s1node->loc == val)
2690 continue;
2691 else
2692 insert_into_intersection (dest, s1node->loc,
2693 MIN (s1node->init, s2node->init));
2697 for (; s1node; s1node = s1node->next)
2699 if (s1node->loc == val)
2700 continue;
2702 if ((found = find_loc_in_1pdv (s1node->loc, s2var,
2703 shared_hash_htab (s2set->vars))))
2705 insert_into_intersection (dest, s1node->loc,
2706 MIN (s1node->init, found->init));
2707 continue;
2710 if (GET_CODE (s1node->loc) == VALUE
2711 && !VALUE_RECURSED_INTO (s1node->loc))
2713 decl_or_value dv = dv_from_value (s1node->loc);
2714 variable svar = shared_hash_find (s1set->vars, dv);
2715 if (svar)
2717 if (svar->n_var_parts == 1)
2719 VALUE_RECURSED_INTO (s1node->loc) = true;
2720 intersect_loc_chains (val, dest, dsm,
2721 svar->var_part[0].loc_chain,
2722 s2var);
2723 VALUE_RECURSED_INTO (s1node->loc) = false;
2728 /* ??? if the location is equivalent to any location in src,
2729 searched recursively
2731 add to dst the values needed to represent the equivalence
2733 telling whether locations S is equivalent to another dv's
2734 location list:
2736 for each location D in the list
2738 if S and D satisfy rtx_equal_p, then it is present
2740 else if D is a value, recurse without cycles
2742 else if S and D have the same CODE and MODE
2744 for each operand oS and the corresponding oD
2746 if oS and oD are not equivalent, then S an D are not equivalent
2748 else if they are RTX vectors
2750 if any vector oS element is not equivalent to its respective oD,
2751 then S and D are not equivalent
2759 /* Return -1 if X should be before Y in a location list for a 1-part
2760 variable, 1 if Y should be before X, and 0 if they're equivalent
2761 and should not appear in the list. */
2763 static int
2764 loc_cmp (rtx x, rtx y)
2766 int i, j, r;
2767 RTX_CODE code = GET_CODE (x);
2768 const char *fmt;
2770 if (x == y)
2771 return 0;
2773 if (REG_P (x))
2775 if (!REG_P (y))
2776 return -1;
2777 gcc_assert (GET_MODE (x) == GET_MODE (y));
2778 if (REGNO (x) == REGNO (y))
2779 return 0;
2780 else if (REGNO (x) < REGNO (y))
2781 return -1;
2782 else
2783 return 1;
2786 if (REG_P (y))
2787 return 1;
2789 if (MEM_P (x))
2791 if (!MEM_P (y))
2792 return -1;
2793 gcc_assert (GET_MODE (x) == GET_MODE (y));
2794 return loc_cmp (XEXP (x, 0), XEXP (y, 0));
2797 if (MEM_P (y))
2798 return 1;
2800 if (GET_CODE (x) == VALUE)
2802 if (GET_CODE (y) != VALUE)
2803 return -1;
2804 /* Don't assert the modes are the same, that is true only
2805 when not recursing. (subreg:QI (value:SI 1:1) 0)
2806 and (subreg:QI (value:DI 2:2) 0) can be compared,
2807 even when the modes are different. */
2808 if (canon_value_cmp (x, y))
2809 return -1;
2810 else
2811 return 1;
2814 if (GET_CODE (y) == VALUE)
2815 return 1;
2817 if (GET_CODE (x) == GET_CODE (y))
2818 /* Compare operands below. */;
2819 else if (GET_CODE (x) < GET_CODE (y))
2820 return -1;
2821 else
2822 return 1;
2824 gcc_assert (GET_MODE (x) == GET_MODE (y));
2826 if (GET_CODE (x) == DEBUG_EXPR)
2828 if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
2829 < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)))
2830 return -1;
2831 #ifdef ENABLE_CHECKING
2832 gcc_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))
2833 > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)));
2834 #endif
2835 return 1;
2838 fmt = GET_RTX_FORMAT (code);
2839 for (i = 0; i < GET_RTX_LENGTH (code); i++)
2840 switch (fmt[i])
2842 case 'w':
2843 if (XWINT (x, i) == XWINT (y, i))
2844 break;
2845 else if (XWINT (x, i) < XWINT (y, i))
2846 return -1;
2847 else
2848 return 1;
2850 case 'n':
2851 case 'i':
2852 if (XINT (x, i) == XINT (y, i))
2853 break;
2854 else if (XINT (x, i) < XINT (y, i))
2855 return -1;
2856 else
2857 return 1;
2859 case 'V':
2860 case 'E':
2861 /* Compare the vector length first. */
2862 if (XVECLEN (x, i) == XVECLEN (y, i))
2863 /* Compare the vectors elements. */;
2864 else if (XVECLEN (x, i) < XVECLEN (y, i))
2865 return -1;
2866 else
2867 return 1;
2869 for (j = 0; j < XVECLEN (x, i); j++)
2870 if ((r = loc_cmp (XVECEXP (x, i, j),
2871 XVECEXP (y, i, j))))
2872 return r;
2873 break;
2875 case 'e':
2876 if ((r = loc_cmp (XEXP (x, i), XEXP (y, i))))
2877 return r;
2878 break;
2880 case 'S':
2881 case 's':
2882 if (XSTR (x, i) == XSTR (y, i))
2883 break;
2884 if (!XSTR (x, i))
2885 return -1;
2886 if (!XSTR (y, i))
2887 return 1;
2888 if ((r = strcmp (XSTR (x, i), XSTR (y, i))) == 0)
2889 break;
2890 else if (r < 0)
2891 return -1;
2892 else
2893 return 1;
2895 case 'u':
2896 /* These are just backpointers, so they don't matter. */
2897 break;
2899 case '0':
2900 case 't':
2901 break;
2903 /* It is believed that rtx's at this level will never
2904 contain anything but integers and other rtx's,
2905 except for within LABEL_REFs and SYMBOL_REFs. */
2906 default:
2907 gcc_unreachable ();
2910 return 0;
2913 /* If decl or value DVP refers to VALUE from *LOC, add backlinks
2914 from VALUE to DVP. */
2916 static int
2917 add_value_chain (rtx *loc, void *dvp)
2919 decl_or_value dv, ldv;
2920 value_chain vc, nvc;
2921 void **slot;
2923 if (GET_CODE (*loc) == VALUE)
2924 ldv = dv_from_value (*loc);
2925 else if (GET_CODE (*loc) == DEBUG_EXPR)
2926 ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
2927 else
2928 return 0;
2930 if (dv_as_opaque (ldv) == dvp)
2931 return 0;
2933 dv = (decl_or_value) dvp;
2934 slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
2935 INSERT);
2936 if (!*slot)
2938 vc = (value_chain) pool_alloc (value_chain_pool);
2939 vc->dv = ldv;
2940 vc->next = NULL;
2941 vc->refcount = 0;
2942 *slot = (void *) vc;
2944 else
2946 for (vc = ((value_chain) *slot)->next; vc; vc = vc->next)
2947 if (dv_as_opaque (vc->dv) == dv_as_opaque (dv))
2948 break;
2949 if (vc)
2951 vc->refcount++;
2952 return 0;
2955 vc = (value_chain) *slot;
2956 nvc = (value_chain) pool_alloc (value_chain_pool);
2957 nvc->dv = dv;
2958 nvc->next = vc->next;
2959 nvc->refcount = 1;
2960 vc->next = nvc;
2961 return 0;
2964 /* If decl or value DVP refers to VALUEs from within LOC, add backlinks
2965 from those VALUEs to DVP. */
2967 static void
2968 add_value_chains (decl_or_value dv, rtx loc)
2970 if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
2972 add_value_chain (&loc, dv_as_opaque (dv));
2973 return;
2975 if (REG_P (loc))
2976 return;
2977 if (MEM_P (loc))
2978 loc = XEXP (loc, 0);
2979 for_each_rtx (&loc, add_value_chain, dv_as_opaque (dv));
2982 /* If CSELIB_VAL_PTR of value DV refer to VALUEs, add backlinks from those
2983 VALUEs to DV. Add the same time get rid of ASM_OPERANDS from locs list,
2984 that is something we never can express in .debug_info and can prevent
2985 reverse ops from being used. */
2987 static void
2988 add_cselib_value_chains (decl_or_value dv)
2990 struct elt_loc_list **l;
2992 for (l = &CSELIB_VAL_PTR (dv_as_value (dv))->locs; *l;)
2993 if (GET_CODE ((*l)->loc) == ASM_OPERANDS)
2994 *l = (*l)->next;
2995 else
2997 for_each_rtx (&(*l)->loc, add_value_chain, dv_as_opaque (dv));
2998 l = &(*l)->next;
3002 /* If decl or value DVP refers to VALUE from *LOC, remove backlinks
3003 from VALUE to DVP. */
3005 static int
3006 remove_value_chain (rtx *loc, void *dvp)
3008 decl_or_value dv, ldv;
3009 value_chain vc;
3010 void **slot;
3012 if (GET_CODE (*loc) == VALUE)
3013 ldv = dv_from_value (*loc);
3014 else if (GET_CODE (*loc) == DEBUG_EXPR)
3015 ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
3016 else
3017 return 0;
3019 if (dv_as_opaque (ldv) == dvp)
3020 return 0;
3022 dv = (decl_or_value) dvp;
3023 slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
3024 NO_INSERT);
3025 for (vc = (value_chain) *slot; vc->next; vc = vc->next)
3026 if (dv_as_opaque (vc->next->dv) == dv_as_opaque (dv))
3028 value_chain dvc = vc->next;
3029 gcc_assert (dvc->refcount > 0);
3030 if (--dvc->refcount == 0)
3032 vc->next = dvc->next;
3033 pool_free (value_chain_pool, dvc);
3034 if (vc->next == NULL && vc == (value_chain) *slot)
3036 pool_free (value_chain_pool, vc);
3037 htab_clear_slot (value_chains, slot);
3040 return 0;
3042 gcc_unreachable ();
3045 /* If decl or value DVP refers to VALUEs from within LOC, remove backlinks
3046 from those VALUEs to DVP. */
3048 static void
3049 remove_value_chains (decl_or_value dv, rtx loc)
3051 if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
3053 remove_value_chain (&loc, dv_as_opaque (dv));
3054 return;
3056 if (REG_P (loc))
3057 return;
3058 if (MEM_P (loc))
3059 loc = XEXP (loc, 0);
3060 for_each_rtx (&loc, remove_value_chain, dv_as_opaque (dv));
3063 #if ENABLE_CHECKING
3064 /* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those
3065 VALUEs to DV. */
3067 static void
3068 remove_cselib_value_chains (decl_or_value dv)
3070 struct elt_loc_list *l;
3072 for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
3073 for_each_rtx (&l->loc, remove_value_chain, dv_as_opaque (dv));
3076 /* Check the order of entries in one-part variables. */
3078 static int
3079 canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
3081 variable var = (variable) *slot;
3082 decl_or_value dv = var->dv;
3083 location_chain node, next;
3085 #ifdef ENABLE_RTL_CHECKING
3086 int i;
3087 for (i = 0; i < var->n_var_parts; i++)
3088 gcc_assert (var->var_part[0].cur_loc == NULL);
3089 gcc_assert (!var->cur_loc_changed && !var->in_changed_variables);
3090 #endif
3092 if (!dv_onepart_p (dv))
3093 return 1;
3095 gcc_assert (var->n_var_parts == 1);
3096 node = var->var_part[0].loc_chain;
3097 gcc_assert (node);
3099 while ((next = node->next))
3101 gcc_assert (loc_cmp (node->loc, next->loc) < 0);
3102 node = next;
3105 return 1;
3107 #endif
3109 /* Mark with VALUE_RECURSED_INTO values that have neighbors that are
3110 more likely to be chosen as canonical for an equivalence set.
3111 Ensure less likely values can reach more likely neighbors, making
3112 the connections bidirectional. */
3114 static int
3115 canonicalize_values_mark (void **slot, void *data)
3117 dataflow_set *set = (dataflow_set *)data;
3118 variable var = (variable) *slot;
3119 decl_or_value dv = var->dv;
3120 rtx val;
3121 location_chain node;
3123 if (!dv_is_value_p (dv))
3124 return 1;
3126 gcc_assert (var->n_var_parts == 1);
3128 val = dv_as_value (dv);
3130 for (node = var->var_part[0].loc_chain; node; node = node->next)
3131 if (GET_CODE (node->loc) == VALUE)
3133 if (canon_value_cmp (node->loc, val))
3134 VALUE_RECURSED_INTO (val) = true;
3135 else
3137 decl_or_value odv = dv_from_value (node->loc);
3138 void **oslot = shared_hash_find_slot_noinsert (set->vars, odv);
3140 oslot = set_slot_part (set, val, oslot, odv, 0,
3141 node->init, NULL_RTX);
3143 VALUE_RECURSED_INTO (node->loc) = true;
3147 return 1;
3150 /* Remove redundant entries from equivalence lists in onepart
3151 variables, canonicalizing equivalence sets into star shapes. */
3153 static int
3154 canonicalize_values_star (void **slot, void *data)
3156 dataflow_set *set = (dataflow_set *)data;
3157 variable var = (variable) *slot;
3158 decl_or_value dv = var->dv;
3159 location_chain node;
3160 decl_or_value cdv;
3161 rtx val, cval;
3162 void **cslot;
3163 bool has_value;
3164 bool has_marks;
3166 if (!dv_onepart_p (dv))
3167 return 1;
3169 gcc_assert (var->n_var_parts == 1);
3171 if (dv_is_value_p (dv))
3173 cval = dv_as_value (dv);
3174 if (!VALUE_RECURSED_INTO (cval))
3175 return 1;
3176 VALUE_RECURSED_INTO (cval) = false;
3178 else
3179 cval = NULL_RTX;
3181 restart:
3182 val = cval;
3183 has_value = false;
3184 has_marks = false;
3186 gcc_assert (var->n_var_parts == 1);
3188 for (node = var->var_part[0].loc_chain; node; node = node->next)
3189 if (GET_CODE (node->loc) == VALUE)
3191 has_value = true;
3192 if (VALUE_RECURSED_INTO (node->loc))
3193 has_marks = true;
3194 if (canon_value_cmp (node->loc, cval))
3195 cval = node->loc;
3198 if (!has_value)
3199 return 1;
3201 if (cval == val)
3203 if (!has_marks || dv_is_decl_p (dv))
3204 return 1;
3206 /* Keep it marked so that we revisit it, either after visiting a
3207 child node, or after visiting a new parent that might be
3208 found out. */
3209 VALUE_RECURSED_INTO (val) = true;
3211 for (node = var->var_part[0].loc_chain; node; node = node->next)
3212 if (GET_CODE (node->loc) == VALUE
3213 && VALUE_RECURSED_INTO (node->loc))
3215 cval = node->loc;
3216 restart_with_cval:
3217 VALUE_RECURSED_INTO (cval) = false;
3218 dv = dv_from_value (cval);
3219 slot = shared_hash_find_slot_noinsert (set->vars, dv);
3220 if (!slot)
3222 gcc_assert (dv_is_decl_p (var->dv));
3223 /* The canonical value was reset and dropped.
3224 Remove it. */
3225 clobber_variable_part (set, NULL, var->dv, 0, NULL);
3226 return 1;
3228 var = (variable)*slot;
3229 gcc_assert (dv_is_value_p (var->dv));
3230 if (var->n_var_parts == 0)
3231 return 1;
3232 gcc_assert (var->n_var_parts == 1);
3233 goto restart;
3236 VALUE_RECURSED_INTO (val) = false;
3238 return 1;
3241 /* Push values to the canonical one. */
3242 cdv = dv_from_value (cval);
3243 cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3245 for (node = var->var_part[0].loc_chain; node; node = node->next)
3246 if (node->loc != cval)
3248 cslot = set_slot_part (set, node->loc, cslot, cdv, 0,
3249 node->init, NULL_RTX);
3250 if (GET_CODE (node->loc) == VALUE)
3252 decl_or_value ndv = dv_from_value (node->loc);
3254 set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX,
3255 NO_INSERT);
3257 if (canon_value_cmp (node->loc, val))
3259 /* If it could have been a local minimum, it's not any more,
3260 since it's now neighbor to cval, so it may have to push
3261 to it. Conversely, if it wouldn't have prevailed over
3262 val, then whatever mark it has is fine: if it was to
3263 push, it will now push to a more canonical node, but if
3264 it wasn't, then it has already pushed any values it might
3265 have to. */
3266 VALUE_RECURSED_INTO (node->loc) = true;
3267 /* Make sure we visit node->loc by ensuring we cval is
3268 visited too. */
3269 VALUE_RECURSED_INTO (cval) = true;
3271 else if (!VALUE_RECURSED_INTO (node->loc))
3272 /* If we have no need to "recurse" into this node, it's
3273 already "canonicalized", so drop the link to the old
3274 parent. */
3275 clobber_variable_part (set, cval, ndv, 0, NULL);
3277 else if (GET_CODE (node->loc) == REG)
3279 attrs list = set->regs[REGNO (node->loc)], *listp;
3281 /* Change an existing attribute referring to dv so that it
3282 refers to cdv, removing any duplicate this might
3283 introduce, and checking that no previous duplicates
3284 existed, all in a single pass. */
3286 while (list)
3288 if (list->offset == 0
3289 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3290 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3291 break;
3293 list = list->next;
3296 gcc_assert (list);
3297 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3299 list->dv = cdv;
3300 for (listp = &list->next; (list = *listp); listp = &list->next)
3302 if (list->offset)
3303 continue;
3305 if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3307 *listp = list->next;
3308 pool_free (attrs_pool, list);
3309 list = *listp;
3310 break;
3313 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv));
3316 else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3318 for (listp = &list->next; (list = *listp); listp = &list->next)
3320 if (list->offset)
3321 continue;
3323 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3325 *listp = list->next;
3326 pool_free (attrs_pool, list);
3327 list = *listp;
3328 break;
3331 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv));
3334 else
3335 gcc_unreachable ();
3337 #if ENABLE_CHECKING
3338 while (list)
3340 if (list->offset == 0
3341 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3342 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3343 gcc_unreachable ();
3345 list = list->next;
3347 #endif
3351 if (val)
3352 cslot = set_slot_part (set, val, cslot, cdv, 0,
3353 VAR_INIT_STATUS_INITIALIZED, NULL_RTX);
3355 slot = clobber_slot_part (set, cval, slot, 0, NULL);
3357 /* Variable may have been unshared. */
3358 var = (variable)*slot;
3359 gcc_assert (var->n_var_parts && var->var_part[0].loc_chain->loc == cval
3360 && var->var_part[0].loc_chain->next == NULL);
3362 if (VALUE_RECURSED_INTO (cval))
3363 goto restart_with_cval;
3365 return 1;
3368 /* Bind one-part variables to the canonical value in an equivalence
3369 set. Not doing this causes dataflow convergence failure in rare
3370 circumstances, see PR42873. Unfortunately we can't do this
3371 efficiently as part of canonicalize_values_star, since we may not
3372 have determined or even seen the canonical value of a set when we
3373 get to a variable that references another member of the set. */
3375 static int
3376 canonicalize_vars_star (void **slot, void *data)
3378 dataflow_set *set = (dataflow_set *)data;
3379 variable var = (variable) *slot;
3380 decl_or_value dv = var->dv;
3381 location_chain node;
3382 rtx cval;
3383 decl_or_value cdv;
3384 void **cslot;
3385 variable cvar;
3386 location_chain cnode;
3388 if (!dv_onepart_p (dv) || dv_is_value_p (dv))
3389 return 1;
3391 gcc_assert (var->n_var_parts == 1);
3393 node = var->var_part[0].loc_chain;
3395 if (GET_CODE (node->loc) != VALUE)
3396 return 1;
3398 gcc_assert (!node->next);
3399 cval = node->loc;
3401 /* Push values to the canonical one. */
3402 cdv = dv_from_value (cval);
3403 cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3404 if (!cslot)
3405 return 1;
3406 cvar = (variable)*cslot;
3407 gcc_assert (cvar->n_var_parts == 1);
3409 cnode = cvar->var_part[0].loc_chain;
3411 /* CVAL is canonical if its value list contains non-VALUEs or VALUEs
3412 that are not “more canonical” than it. */
3413 if (GET_CODE (cnode->loc) != VALUE
3414 || !canon_value_cmp (cnode->loc, cval))
3415 return 1;
3417 /* CVAL was found to be non-canonical. Change the variable to point
3418 to the canonical VALUE. */
3419 gcc_assert (!cnode->next);
3420 cval = cnode->loc;
3422 slot = set_slot_part (set, cval, slot, dv, 0,
3423 node->init, node->set_src);
3424 slot = clobber_slot_part (set, cval, slot, 0, node->set_src);
3426 return 1;
3429 /* Combine variable or value in *S1SLOT (in DSM->cur) with the
3430 corresponding entry in DSM->src. Multi-part variables are combined
3431 with variable_union, whereas onepart dvs are combined with
3432 intersection. */
3434 static int
3435 variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
3437 dataflow_set *dst = dsm->dst;
3438 void **dstslot;
3439 variable s2var, dvar = NULL;
3440 decl_or_value dv = s1var->dv;
3441 bool onepart = dv_onepart_p (dv);
3442 rtx val;
3443 hashval_t dvhash;
3444 location_chain node, *nodep;
3446 /* If the incoming onepart variable has an empty location list, then
3447 the intersection will be just as empty. For other variables,
3448 it's always union. */
3449 gcc_assert (s1var->n_var_parts
3450 && s1var->var_part[0].loc_chain);
3452 if (!onepart)
3453 return variable_union (s1var, dst);
3455 gcc_assert (s1var->n_var_parts == 1
3456 && s1var->var_part[0].offset == 0);
3458 dvhash = dv_htab_hash (dv);
3459 if (dv_is_value_p (dv))
3460 val = dv_as_value (dv);
3461 else
3462 val = NULL;
3464 s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash);
3465 if (!s2var)
3467 dst_can_be_shared = false;
3468 return 1;
3471 dsm->src_onepart_cnt--;
3472 gcc_assert (s2var->var_part[0].loc_chain
3473 && s2var->n_var_parts == 1
3474 && s2var->var_part[0].offset == 0);
3476 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3477 if (dstslot)
3479 dvar = (variable)*dstslot;
3480 gcc_assert (dvar->refcount == 1
3481 && dvar->n_var_parts == 1
3482 && dvar->var_part[0].offset == 0);
3483 nodep = &dvar->var_part[0].loc_chain;
3485 else
3487 nodep = &node;
3488 node = NULL;
3491 if (!dstslot && !onepart_variable_different_p (s1var, s2var))
3493 dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv,
3494 dvhash, INSERT);
3495 *dstslot = dvar = s2var;
3496 dvar->refcount++;
3498 else
3500 dst_can_be_shared = false;
3502 intersect_loc_chains (val, nodep, dsm,
3503 s1var->var_part[0].loc_chain, s2var);
3505 if (!dstslot)
3507 if (node)
3509 dvar = (variable) pool_alloc (dv_pool (dv));
3510 dvar->dv = dv;
3511 dvar->refcount = 1;
3512 dvar->n_var_parts = 1;
3513 dvar->cur_loc_changed = false;
3514 dvar->in_changed_variables = false;
3515 dvar->var_part[0].offset = 0;
3516 dvar->var_part[0].loc_chain = node;
3517 dvar->var_part[0].cur_loc = NULL;
3519 dstslot
3520 = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
3521 INSERT);
3522 gcc_assert (!*dstslot);
3523 *dstslot = dvar;
3525 else
3526 return 1;
3530 nodep = &dvar->var_part[0].loc_chain;
3531 while ((node = *nodep))
3533 location_chain *nextp = &node->next;
3535 if (GET_CODE (node->loc) == REG)
3537 attrs list;
3539 for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
3540 if (GET_MODE (node->loc) == GET_MODE (list->loc)
3541 && dv_is_value_p (list->dv))
3542 break;
3544 if (!list)
3545 attrs_list_insert (&dst->regs[REGNO (node->loc)],
3546 dv, 0, node->loc);
3547 /* If this value became canonical for another value that had
3548 this register, we want to leave it alone. */
3549 else if (dv_as_value (list->dv) != val)
3551 dstslot = set_slot_part (dst, dv_as_value (list->dv),
3552 dstslot, dv, 0,
3553 node->init, NULL_RTX);
3554 dstslot = delete_slot_part (dst, node->loc, dstslot, 0);
3556 /* Since nextp points into the removed node, we can't
3557 use it. The pointer to the next node moved to nodep.
3558 However, if the variable we're walking is unshared
3559 during our walk, we'll keep walking the location list
3560 of the previously-shared variable, in which case the
3561 node won't have been removed, and we'll want to skip
3562 it. That's why we test *nodep here. */
3563 if (*nodep != node)
3564 nextp = nodep;
3567 else
3568 /* Canonicalization puts registers first, so we don't have to
3569 walk it all. */
3570 break;
3571 nodep = nextp;
3574 if (dvar != (variable)*dstslot)
3575 dvar = (variable)*dstslot;
3576 nodep = &dvar->var_part[0].loc_chain;
3578 if (val)
3580 /* Mark all referenced nodes for canonicalization, and make sure
3581 we have mutual equivalence links. */
3582 VALUE_RECURSED_INTO (val) = true;
3583 for (node = *nodep; node; node = node->next)
3584 if (GET_CODE (node->loc) == VALUE)
3586 VALUE_RECURSED_INTO (node->loc) = true;
3587 set_variable_part (dst, val, dv_from_value (node->loc), 0,
3588 node->init, NULL, INSERT);
3591 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3592 gcc_assert (*dstslot == dvar);
3593 canonicalize_values_star (dstslot, dst);
3594 #ifdef ENABLE_CHECKING
3595 gcc_assert (dstslot
3596 == shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash));
3597 #endif
3598 dvar = (variable)*dstslot;
3600 else
3602 bool has_value = false, has_other = false;
3604 /* If we have one value and anything else, we're going to
3605 canonicalize this, so make sure all values have an entry in
3606 the table and are marked for canonicalization. */
3607 for (node = *nodep; node; node = node->next)
3609 if (GET_CODE (node->loc) == VALUE)
3611 /* If this was marked during register canonicalization,
3612 we know we have to canonicalize values. */
3613 if (has_value)
3614 has_other = true;
3615 has_value = true;
3616 if (has_other)
3617 break;
3619 else
3621 has_other = true;
3622 if (has_value)
3623 break;
3627 if (has_value && has_other)
3629 for (node = *nodep; node; node = node->next)
3631 if (GET_CODE (node->loc) == VALUE)
3633 decl_or_value dv = dv_from_value (node->loc);
3634 void **slot = NULL;
3636 if (shared_hash_shared (dst->vars))
3637 slot = shared_hash_find_slot_noinsert (dst->vars, dv);
3638 if (!slot)
3639 slot = shared_hash_find_slot_unshare (&dst->vars, dv,
3640 INSERT);
3641 if (!*slot)
3643 variable var = (variable) pool_alloc (dv_pool (dv));
3644 var->dv = dv;
3645 var->refcount = 1;
3646 var->n_var_parts = 1;
3647 var->cur_loc_changed = false;
3648 var->in_changed_variables = false;
3649 var->var_part[0].offset = 0;
3650 var->var_part[0].loc_chain = NULL;
3651 var->var_part[0].cur_loc = NULL;
3652 *slot = var;
3655 VALUE_RECURSED_INTO (node->loc) = true;
3659 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
3660 gcc_assert (*dstslot == dvar);
3661 canonicalize_values_star (dstslot, dst);
3662 #ifdef ENABLE_CHECKING
3663 gcc_assert (dstslot
3664 == shared_hash_find_slot_noinsert_1 (dst->vars,
3665 dv, dvhash));
3666 #endif
3667 dvar = (variable)*dstslot;
3671 if (!onepart_variable_different_p (dvar, s2var))
3673 variable_htab_free (dvar);
3674 *dstslot = dvar = s2var;
3675 dvar->refcount++;
3677 else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var))
3679 variable_htab_free (dvar);
3680 *dstslot = dvar = s1var;
3681 dvar->refcount++;
3682 dst_can_be_shared = false;
3684 else
3685 dst_can_be_shared = false;
3687 return 1;
3690 /* Copy s2slot (in DSM->src) to DSM->dst if the variable is a
3691 multi-part variable. Unions of multi-part variables and
3692 intersections of one-part ones will be handled in
3693 variable_merge_over_cur(). */
3695 static int
3696 variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
3698 dataflow_set *dst = dsm->dst;
3699 decl_or_value dv = s2var->dv;
3700 bool onepart = dv_onepart_p (dv);
3702 if (!onepart)
3704 void **dstp = shared_hash_find_slot (dst->vars, dv);
3705 *dstp = s2var;
3706 s2var->refcount++;
3707 return 1;
3710 dsm->src_onepart_cnt++;
3711 return 1;
3714 /* Combine dataflow set information from SRC2 into DST, using PDST
3715 to carry over information across passes. */
3717 static void
3718 dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
3720 dataflow_set cur = *dst;
3721 dataflow_set *src1 = &cur;
3722 struct dfset_merge dsm;
3723 int i;
3724 size_t src1_elems, src2_elems;
3725 htab_iterator hi;
3726 variable var;
3728 src1_elems = htab_elements (shared_hash_htab (src1->vars));
3729 src2_elems = htab_elements (shared_hash_htab (src2->vars));
3730 dataflow_set_init (dst);
3731 dst->stack_adjust = cur.stack_adjust;
3732 shared_hash_destroy (dst->vars);
3733 dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
3734 dst->vars->refcount = 1;
3735 dst->vars->htab
3736 = htab_create (MAX (src1_elems, src2_elems), variable_htab_hash,
3737 variable_htab_eq, variable_htab_free);
3739 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3740 attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
3742 dsm.dst = dst;
3743 dsm.src = src2;
3744 dsm.cur = src1;
3745 dsm.src_onepart_cnt = 0;
3747 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (dsm.src->vars), var, variable, hi)
3748 variable_merge_over_src (var, &dsm);
3749 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (dsm.cur->vars), var, variable, hi)
3750 variable_merge_over_cur (var, &dsm);
3752 if (dsm.src_onepart_cnt)
3753 dst_can_be_shared = false;
3755 dataflow_set_destroy (src1);
3758 /* Mark register equivalences. */
3760 static void
3761 dataflow_set_equiv_regs (dataflow_set *set)
3763 int i;
3764 attrs list, *listp;
3766 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3768 rtx canon[NUM_MACHINE_MODES];
3770 /* If the list is empty or one entry, no need to canonicalize
3771 anything. */
3772 if (set->regs[i] == NULL || set->regs[i]->next == NULL)
3773 continue;
3775 memset (canon, 0, sizeof (canon));
3777 for (list = set->regs[i]; list; list = list->next)
3778 if (list->offset == 0 && dv_is_value_p (list->dv))
3780 rtx val = dv_as_value (list->dv);
3781 rtx *cvalp = &canon[(int)GET_MODE (val)];
3782 rtx cval = *cvalp;
3784 if (canon_value_cmp (val, cval))
3785 *cvalp = val;
3788 for (list = set->regs[i]; list; list = list->next)
3789 if (list->offset == 0 && dv_onepart_p (list->dv))
3791 rtx cval = canon[(int)GET_MODE (list->loc)];
3793 if (!cval)
3794 continue;
3796 if (dv_is_value_p (list->dv))
3798 rtx val = dv_as_value (list->dv);
3800 if (val == cval)
3801 continue;
3803 VALUE_RECURSED_INTO (val) = true;
3804 set_variable_part (set, val, dv_from_value (cval), 0,
3805 VAR_INIT_STATUS_INITIALIZED,
3806 NULL, NO_INSERT);
3809 VALUE_RECURSED_INTO (cval) = true;
3810 set_variable_part (set, cval, list->dv, 0,
3811 VAR_INIT_STATUS_INITIALIZED, NULL, NO_INSERT);
3814 for (listp = &set->regs[i]; (list = *listp);
3815 listp = list ? &list->next : listp)
3816 if (list->offset == 0 && dv_onepart_p (list->dv))
3818 rtx cval = canon[(int)GET_MODE (list->loc)];
3819 void **slot;
3821 if (!cval)
3822 continue;
3824 if (dv_is_value_p (list->dv))
3826 rtx val = dv_as_value (list->dv);
3827 if (!VALUE_RECURSED_INTO (val))
3828 continue;
3831 slot = shared_hash_find_slot_noinsert (set->vars, list->dv);
3832 canonicalize_values_star (slot, set);
3833 if (*listp != list)
3834 list = NULL;
3839 /* Remove any redundant values in the location list of VAR, which must
3840 be unshared and 1-part. */
3842 static void
3843 remove_duplicate_values (variable var)
3845 location_chain node, *nodep;
3847 gcc_assert (dv_onepart_p (var->dv));
3848 gcc_assert (var->n_var_parts == 1);
3849 gcc_assert (var->refcount == 1);
3851 for (nodep = &var->var_part[0].loc_chain; (node = *nodep); )
3853 if (GET_CODE (node->loc) == VALUE)
3855 if (VALUE_RECURSED_INTO (node->loc))
3857 /* Remove duplicate value node. */
3858 *nodep = node->next;
3859 pool_free (loc_chain_pool, node);
3860 continue;
3862 else
3863 VALUE_RECURSED_INTO (node->loc) = true;
3865 nodep = &node->next;
3868 for (node = var->var_part[0].loc_chain; node; node = node->next)
3869 if (GET_CODE (node->loc) == VALUE)
3871 gcc_assert (VALUE_RECURSED_INTO (node->loc));
3872 VALUE_RECURSED_INTO (node->loc) = false;
3877 /* Hash table iteration argument passed to variable_post_merge. */
3878 struct dfset_post_merge
3880 /* The new input set for the current block. */
3881 dataflow_set *set;
3882 /* Pointer to the permanent input set for the current block, or
3883 NULL. */
3884 dataflow_set **permp;
3887 /* Create values for incoming expressions associated with one-part
3888 variables that don't have value numbers for them. */
3890 static int
3891 variable_post_merge_new_vals (void **slot, void *info)
3893 struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
3894 dataflow_set *set = dfpm->set;
3895 variable var = (variable)*slot;
3896 location_chain node;
3898 if (!dv_onepart_p (var->dv) || !var->n_var_parts)
3899 return 1;
3901 gcc_assert (var->n_var_parts == 1);
3903 if (dv_is_decl_p (var->dv))
3905 bool check_dupes = false;
3907 restart:
3908 for (node = var->var_part[0].loc_chain; node; node = node->next)
3910 if (GET_CODE (node->loc) == VALUE)
3911 gcc_assert (!VALUE_RECURSED_INTO (node->loc));
3912 else if (GET_CODE (node->loc) == REG)
3914 attrs att, *attp, *curp = NULL;
3916 if (var->refcount != 1)
3918 slot = unshare_variable (set, slot, var,
3919 VAR_INIT_STATUS_INITIALIZED);
3920 var = (variable)*slot;
3921 goto restart;
3924 for (attp = &set->regs[REGNO (node->loc)]; (att = *attp);
3925 attp = &att->next)
3926 if (att->offset == 0
3927 && GET_MODE (att->loc) == GET_MODE (node->loc))
3929 if (dv_is_value_p (att->dv))
3931 rtx cval = dv_as_value (att->dv);
3932 node->loc = cval;
3933 check_dupes = true;
3934 break;
3936 else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv))
3937 curp = attp;
3940 if (!curp)
3942 curp = attp;
3943 while (*curp)
3944 if ((*curp)->offset == 0
3945 && GET_MODE ((*curp)->loc) == GET_MODE (node->loc)
3946 && dv_as_opaque ((*curp)->dv) == dv_as_opaque (var->dv))
3947 break;
3948 else
3949 curp = &(*curp)->next;
3950 gcc_assert (*curp);
3953 if (!att)
3955 decl_or_value cdv;
3956 rtx cval;
3958 if (!*dfpm->permp)
3960 *dfpm->permp = XNEW (dataflow_set);
3961 dataflow_set_init (*dfpm->permp);
3964 for (att = (*dfpm->permp)->regs[REGNO (node->loc)];
3965 att; att = att->next)
3966 if (GET_MODE (att->loc) == GET_MODE (node->loc))
3968 gcc_assert (att->offset == 0
3969 && dv_is_value_p (att->dv));
3970 val_reset (set, att->dv);
3971 break;
3974 if (att)
3976 cdv = att->dv;
3977 cval = dv_as_value (cdv);
3979 else
3981 /* Create a unique value to hold this register,
3982 that ought to be found and reused in
3983 subsequent rounds. */
3984 cselib_val *v;
3985 gcc_assert (!cselib_lookup (node->loc,
3986 GET_MODE (node->loc), 0));
3987 v = cselib_lookup (node->loc, GET_MODE (node->loc), 1);
3988 cselib_preserve_value (v);
3989 cselib_invalidate_rtx (node->loc);
3990 cval = v->val_rtx;
3991 cdv = dv_from_value (cval);
3992 if (dump_file)
3993 fprintf (dump_file,
3994 "Created new value %u:%u for reg %i\n",
3995 v->uid, v->hash, REGNO (node->loc));
3998 var_reg_decl_set (*dfpm->permp, node->loc,
3999 VAR_INIT_STATUS_INITIALIZED,
4000 cdv, 0, NULL, INSERT);
4002 node->loc = cval;
4003 check_dupes = true;
4006 /* Remove attribute referring to the decl, which now
4007 uses the value for the register, already existing or
4008 to be added when we bring perm in. */
4009 att = *curp;
4010 *curp = att->next;
4011 pool_free (attrs_pool, att);
4015 if (check_dupes)
4016 remove_duplicate_values (var);
4019 return 1;
4022 /* Reset values in the permanent set that are not associated with the
4023 chosen expression. */
4025 static int
4026 variable_post_merge_perm_vals (void **pslot, void *info)
4028 struct dfset_post_merge *dfpm = (struct dfset_post_merge *)info;
4029 dataflow_set *set = dfpm->set;
4030 variable pvar = (variable)*pslot, var;
4031 location_chain pnode;
4032 decl_or_value dv;
4033 attrs att;
4035 gcc_assert (dv_is_value_p (pvar->dv)
4036 && pvar->n_var_parts == 1);
4037 pnode = pvar->var_part[0].loc_chain;
4038 gcc_assert (pnode
4039 && !pnode->next
4040 && REG_P (pnode->loc));
4042 dv = pvar->dv;
4044 var = shared_hash_find (set->vars, dv);
4045 if (var)
4047 /* Although variable_post_merge_new_vals may have made decls
4048 non-star-canonical, values that pre-existed in canonical form
4049 remain canonical, and newly-created values reference a single
4050 REG, so they are canonical as well. Since VAR has the
4051 location list for a VALUE, using find_loc_in_1pdv for it is
4052 fine, since VALUEs don't map back to DECLs. */
4053 if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
4054 return 1;
4055 val_reset (set, dv);
4058 for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next)
4059 if (att->offset == 0
4060 && GET_MODE (att->loc) == GET_MODE (pnode->loc)
4061 && dv_is_value_p (att->dv))
4062 break;
4064 /* If there is a value associated with this register already, create
4065 an equivalence. */
4066 if (att && dv_as_value (att->dv) != dv_as_value (dv))
4068 rtx cval = dv_as_value (att->dv);
4069 set_variable_part (set, cval, dv, 0, pnode->init, NULL, INSERT);
4070 set_variable_part (set, dv_as_value (dv), att->dv, 0, pnode->init,
4071 NULL, INSERT);
4073 else if (!att)
4075 attrs_list_insert (&set->regs[REGNO (pnode->loc)],
4076 dv, 0, pnode->loc);
4077 variable_union (pvar, set);
4080 return 1;
4083 /* Just checking stuff and registering register attributes for
4084 now. */
4086 static void
4087 dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
4089 struct dfset_post_merge dfpm;
4091 dfpm.set = set;
4092 dfpm.permp = permp;
4094 htab_traverse (shared_hash_htab (set->vars), variable_post_merge_new_vals,
4095 &dfpm);
4096 if (*permp)
4097 htab_traverse (shared_hash_htab ((*permp)->vars),
4098 variable_post_merge_perm_vals, &dfpm);
4099 htab_traverse (shared_hash_htab (set->vars), canonicalize_values_star, set);
4100 htab_traverse (shared_hash_htab (set->vars), canonicalize_vars_star, set);
4103 /* Return a node whose loc is a MEM that refers to EXPR in the
4104 location list of a one-part variable or value VAR, or in that of
4105 any values recursively mentioned in the location lists. */
4107 static location_chain
4108 find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
4110 location_chain node;
4111 decl_or_value dv;
4112 variable var;
4113 location_chain where = NULL;
4115 if (!val)
4116 return NULL;
4118 gcc_assert (GET_CODE (val) == VALUE
4119 && !VALUE_RECURSED_INTO (val));
4121 dv = dv_from_value (val);
4122 var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
4124 if (!var)
4125 return NULL;
4127 gcc_assert (dv_onepart_p (var->dv));
4129 if (!var->n_var_parts)
4130 return NULL;
4132 gcc_assert (var->var_part[0].offset == 0);
4134 VALUE_RECURSED_INTO (val) = true;
4136 for (node = var->var_part[0].loc_chain; node; node = node->next)
4137 if (MEM_P (node->loc) && MEM_EXPR (node->loc) == expr
4138 && MEM_OFFSET (node->loc) == 0)
4140 where = node;
4141 break;
4143 else if (GET_CODE (node->loc) == VALUE
4144 && !VALUE_RECURSED_INTO (node->loc)
4145 && (where = find_mem_expr_in_1pdv (expr, node->loc, vars)))
4146 break;
4148 VALUE_RECURSED_INTO (val) = false;
4150 return where;
4153 /* Return TRUE if the value of MEM may vary across a call. */
4155 static bool
4156 mem_dies_at_call (rtx mem)
4158 tree expr = MEM_EXPR (mem);
4159 tree decl;
4161 if (!expr)
4162 return true;
4164 decl = get_base_address (expr);
4166 if (!decl)
4167 return true;
4169 if (!DECL_P (decl))
4170 return true;
4172 return (may_be_aliased (decl)
4173 || (!TREE_READONLY (decl) && is_global_var (decl)));
4176 /* Remove all MEMs from the location list of a hash table entry for a
4177 one-part variable, except those whose MEM attributes map back to
4178 the variable itself, directly or within a VALUE. */
4180 static int
4181 dataflow_set_preserve_mem_locs (void **slot, void *data)
4183 dataflow_set *set = (dataflow_set *) data;
4184 variable var = (variable) *slot;
4186 if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv))
4188 tree decl = dv_as_decl (var->dv);
4189 location_chain loc, *locp;
4190 bool changed = false;
4192 if (!var->n_var_parts)
4193 return 1;
4195 gcc_assert (var->n_var_parts == 1);
4197 if (shared_var_p (var, set->vars))
4199 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4201 /* We want to remove dying MEMs that doesn't refer to
4202 DECL. */
4203 if (GET_CODE (loc->loc) == MEM
4204 && (MEM_EXPR (loc->loc) != decl
4205 || MEM_OFFSET (loc->loc))
4206 && !mem_dies_at_call (loc->loc))
4207 break;
4208 /* We want to move here MEMs that do refer to DECL. */
4209 else if (GET_CODE (loc->loc) == VALUE
4210 && find_mem_expr_in_1pdv (decl, loc->loc,
4211 shared_hash_htab (set->vars)))
4212 break;
4215 if (!loc)
4216 return 1;
4218 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4219 var = (variable)*slot;
4220 gcc_assert (var->n_var_parts == 1);
4223 for (locp = &var->var_part[0].loc_chain, loc = *locp;
4224 loc; loc = *locp)
4226 rtx old_loc = loc->loc;
4227 if (GET_CODE (old_loc) == VALUE)
4229 location_chain mem_node
4230 = find_mem_expr_in_1pdv (decl, loc->loc,
4231 shared_hash_htab (set->vars));
4233 /* ??? This picks up only one out of multiple MEMs that
4234 refer to the same variable. Do we ever need to be
4235 concerned about dealing with more than one, or, given
4236 that they should all map to the same variable
4237 location, their addresses will have been merged and
4238 they will be regarded as equivalent? */
4239 if (mem_node)
4241 loc->loc = mem_node->loc;
4242 loc->set_src = mem_node->set_src;
4243 loc->init = MIN (loc->init, mem_node->init);
4247 if (GET_CODE (loc->loc) != MEM
4248 || (MEM_EXPR (loc->loc) == decl
4249 && MEM_OFFSET (loc->loc) == 0)
4250 || !mem_dies_at_call (loc->loc))
4252 if (old_loc != loc->loc && emit_notes)
4254 if (old_loc == var->var_part[0].cur_loc)
4256 changed = true;
4257 var->var_part[0].cur_loc = NULL;
4258 var->cur_loc_changed = true;
4260 add_value_chains (var->dv, loc->loc);
4261 remove_value_chains (var->dv, old_loc);
4263 locp = &loc->next;
4264 continue;
4267 if (emit_notes)
4269 remove_value_chains (var->dv, old_loc);
4270 if (old_loc == var->var_part[0].cur_loc)
4272 changed = true;
4273 var->var_part[0].cur_loc = NULL;
4274 var->cur_loc_changed = true;
4277 *locp = loc->next;
4278 pool_free (loc_chain_pool, loc);
4281 if (!var->var_part[0].loc_chain)
4283 var->n_var_parts--;
4284 changed = true;
4286 if (changed)
4287 variable_was_changed (var, set);
4290 return 1;
4293 /* Remove all MEMs from the location list of a hash table entry for a
4294 value. */
4296 static int
4297 dataflow_set_remove_mem_locs (void **slot, void *data)
4299 dataflow_set *set = (dataflow_set *) data;
4300 variable var = (variable) *slot;
4302 if (dv_is_value_p (var->dv))
4304 location_chain loc, *locp;
4305 bool changed = false;
4307 gcc_assert (var->n_var_parts == 1);
4309 if (shared_var_p (var, set->vars))
4311 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4312 if (GET_CODE (loc->loc) == MEM
4313 && mem_dies_at_call (loc->loc))
4314 break;
4316 if (!loc)
4317 return 1;
4319 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4320 var = (variable)*slot;
4321 gcc_assert (var->n_var_parts == 1);
4324 for (locp = &var->var_part[0].loc_chain, loc = *locp;
4325 loc; loc = *locp)
4327 if (GET_CODE (loc->loc) != MEM
4328 || !mem_dies_at_call (loc->loc))
4330 locp = &loc->next;
4331 continue;
4334 if (emit_notes)
4335 remove_value_chains (var->dv, loc->loc);
4336 *locp = loc->next;
4337 /* If we have deleted the location which was last emitted
4338 we have to emit new location so add the variable to set
4339 of changed variables. */
4340 if (var->var_part[0].cur_loc == loc->loc)
4342 changed = true;
4343 var->var_part[0].cur_loc = NULL;
4344 var->cur_loc_changed = true;
4346 pool_free (loc_chain_pool, loc);
4349 if (!var->var_part[0].loc_chain)
4351 var->n_var_parts--;
4352 changed = true;
4354 if (changed)
4355 variable_was_changed (var, set);
4358 return 1;
4361 /* Remove all variable-location information about call-clobbered
4362 registers, as well as associations between MEMs and VALUEs. */
4364 static void
4365 dataflow_set_clear_at_call (dataflow_set *set)
4367 int r;
4369 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
4370 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, r))
4371 var_regno_delete (set, r);
4373 if (MAY_HAVE_DEBUG_INSNS)
4375 set->traversed_vars = set->vars;
4376 htab_traverse (shared_hash_htab (set->vars),
4377 dataflow_set_preserve_mem_locs, set);
4378 set->traversed_vars = set->vars;
4379 htab_traverse (shared_hash_htab (set->vars), dataflow_set_remove_mem_locs,
4380 set);
4381 set->traversed_vars = NULL;
4385 static bool
4386 variable_part_different_p (variable_part *vp1, variable_part *vp2)
4388 location_chain lc1, lc2;
4390 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
4392 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
4394 if (REG_P (lc1->loc) && REG_P (lc2->loc))
4396 if (REGNO (lc1->loc) == REGNO (lc2->loc))
4397 break;
4399 if (rtx_equal_p (lc1->loc, lc2->loc))
4400 break;
4402 if (!lc2)
4403 return true;
4405 return false;
4408 /* Return true if one-part variables VAR1 and VAR2 are different.
4409 They must be in canonical order. */
4411 static bool
4412 onepart_variable_different_p (variable var1, variable var2)
4414 location_chain lc1, lc2;
4416 if (var1 == var2)
4417 return false;
4419 gcc_assert (var1->n_var_parts == 1
4420 && var2->n_var_parts == 1);
4422 lc1 = var1->var_part[0].loc_chain;
4423 lc2 = var2->var_part[0].loc_chain;
4425 gcc_assert (lc1 && lc2);
4427 while (lc1 && lc2)
4429 if (loc_cmp (lc1->loc, lc2->loc))
4430 return true;
4431 lc1 = lc1->next;
4432 lc2 = lc2->next;
4435 return lc1 != lc2;
4438 /* Return true if variables VAR1 and VAR2 are different. */
4440 static bool
4441 variable_different_p (variable var1, variable var2)
4443 int i;
4445 if (var1 == var2)
4446 return false;
4448 if (var1->n_var_parts != var2->n_var_parts)
4449 return true;
4451 for (i = 0; i < var1->n_var_parts; i++)
4453 if (var1->var_part[i].offset != var2->var_part[i].offset)
4454 return true;
4455 /* One-part values have locations in a canonical order. */
4456 if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv))
4458 gcc_assert (var1->n_var_parts == 1
4459 && dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
4460 return onepart_variable_different_p (var1, var2);
4462 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
4463 return true;
4464 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
4465 return true;
4467 return false;
4470 /* Return true if dataflow sets OLD_SET and NEW_SET differ. */
4472 static bool
4473 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
4475 htab_iterator hi;
4476 variable var1;
4478 if (old_set->vars == new_set->vars)
4479 return false;
4481 if (htab_elements (shared_hash_htab (old_set->vars))
4482 != htab_elements (shared_hash_htab (new_set->vars)))
4483 return true;
4485 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (old_set->vars), var1, variable, hi)
4487 htab_t htab = shared_hash_htab (new_set->vars);
4488 variable var2 = (variable) htab_find_with_hash (htab, var1->dv,
4489 dv_htab_hash (var1->dv));
4490 if (!var2)
4492 if (dump_file && (dump_flags & TDF_DETAILS))
4494 fprintf (dump_file, "dataflow difference found: removal of:\n");
4495 dump_var (var1);
4497 return true;
4500 if (variable_different_p (var1, var2))
4502 if (dump_file && (dump_flags & TDF_DETAILS))
4504 fprintf (dump_file, "dataflow difference found: "
4505 "old and new follow:\n");
4506 dump_var (var1);
4507 dump_var (var2);
4509 return true;
4513 /* No need to traverse the second hashtab, if both have the same number
4514 of elements and the second one had all entries found in the first one,
4515 then it can't have any extra entries. */
4516 return false;
4519 /* Free the contents of dataflow set SET. */
4521 static void
4522 dataflow_set_destroy (dataflow_set *set)
4524 int i;
4526 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4527 attrs_list_clear (&set->regs[i]);
4529 shared_hash_destroy (set->vars);
4530 set->vars = NULL;
4533 /* Return true if RTL X contains a SYMBOL_REF. */
4535 static bool
4536 contains_symbol_ref (rtx x)
4538 const char *fmt;
4539 RTX_CODE code;
4540 int i;
4542 if (!x)
4543 return false;
4545 code = GET_CODE (x);
4546 if (code == SYMBOL_REF)
4547 return true;
4549 fmt = GET_RTX_FORMAT (code);
4550 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4552 if (fmt[i] == 'e')
4554 if (contains_symbol_ref (XEXP (x, i)))
4555 return true;
4557 else if (fmt[i] == 'E')
4559 int j;
4560 for (j = 0; j < XVECLEN (x, i); j++)
4561 if (contains_symbol_ref (XVECEXP (x, i, j)))
4562 return true;
4566 return false;
4569 /* Shall EXPR be tracked? */
4571 static bool
4572 track_expr_p (tree expr, bool need_rtl)
4574 rtx decl_rtl;
4575 tree realdecl;
4577 if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
4578 return DECL_RTL_SET_P (expr);
4580 /* If EXPR is not a parameter or a variable do not track it. */
4581 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
4582 return 0;
4584 /* It also must have a name... */
4585 if (!DECL_NAME (expr) && need_rtl)
4586 return 0;
4588 /* ... and a RTL assigned to it. */
4589 decl_rtl = DECL_RTL_IF_SET (expr);
4590 if (!decl_rtl && need_rtl)
4591 return 0;
4593 /* If this expression is really a debug alias of some other declaration, we
4594 don't need to track this expression if the ultimate declaration is
4595 ignored. */
4596 realdecl = expr;
4597 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
4599 realdecl = DECL_DEBUG_EXPR (realdecl);
4600 /* ??? We don't yet know how to emit DW_OP_piece for variable
4601 that has been SRA'ed. */
4602 if (!DECL_P (realdecl))
4603 return 0;
4606 /* Do not track EXPR if REALDECL it should be ignored for debugging
4607 purposes. */
4608 if (DECL_IGNORED_P (realdecl))
4609 return 0;
4611 /* Do not track global variables until we are able to emit correct location
4612 list for them. */
4613 if (TREE_STATIC (realdecl))
4614 return 0;
4616 /* When the EXPR is a DECL for alias of some variable (see example)
4617 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
4618 DECL_RTL contains SYMBOL_REF.
4620 Example:
4621 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
4622 char **_dl_argv;
4624 if (decl_rtl && MEM_P (decl_rtl)
4625 && contains_symbol_ref (XEXP (decl_rtl, 0)))
4626 return 0;
4628 /* If RTX is a memory it should not be very large (because it would be
4629 an array or struct). */
4630 if (decl_rtl && MEM_P (decl_rtl))
4632 /* Do not track structures and arrays. */
4633 if (GET_MODE (decl_rtl) == BLKmode
4634 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
4635 return 0;
4636 if (MEM_SIZE (decl_rtl)
4637 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
4638 return 0;
4641 DECL_CHANGED (expr) = 0;
4642 DECL_CHANGED (realdecl) = 0;
4643 return 1;
4646 /* Determine whether a given LOC refers to the same variable part as
4647 EXPR+OFFSET. */
4649 static bool
4650 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
4652 tree expr2;
4653 HOST_WIDE_INT offset2;
4655 if (! DECL_P (expr))
4656 return false;
4658 if (REG_P (loc))
4660 expr2 = REG_EXPR (loc);
4661 offset2 = REG_OFFSET (loc);
4663 else if (MEM_P (loc))
4665 expr2 = MEM_EXPR (loc);
4666 offset2 = INT_MEM_OFFSET (loc);
4668 else
4669 return false;
4671 if (! expr2 || ! DECL_P (expr2))
4672 return false;
4674 expr = var_debug_decl (expr);
4675 expr2 = var_debug_decl (expr2);
4677 return (expr == expr2 && offset == offset2);
4680 /* LOC is a REG or MEM that we would like to track if possible.
4681 If EXPR is null, we don't know what expression LOC refers to,
4682 otherwise it refers to EXPR + OFFSET. STORE_REG_P is true if
4683 LOC is an lvalue register.
4685 Return true if EXPR is nonnull and if LOC, or some lowpart of it,
4686 is something we can track. When returning true, store the mode of
4687 the lowpart we can track in *MODE_OUT (if nonnull) and its offset
4688 from EXPR in *OFFSET_OUT (if nonnull). */
4690 static bool
4691 track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
4692 enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
4694 enum machine_mode mode;
4696 if (expr == NULL || !track_expr_p (expr, true))
4697 return false;
4699 /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
4700 whole subreg, but only the old inner part is really relevant. */
4701 mode = GET_MODE (loc);
4702 if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
4704 enum machine_mode pseudo_mode;
4706 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
4707 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
4709 offset += byte_lowpart_offset (pseudo_mode, mode);
4710 mode = pseudo_mode;
4714 /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
4715 Do the same if we are storing to a register and EXPR occupies
4716 the whole of register LOC; in that case, the whole of EXPR is
4717 being changed. We exclude complex modes from the second case
4718 because the real and imaginary parts are represented as separate
4719 pseudo registers, even if the whole complex value fits into one
4720 hard register. */
4721 if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
4722 || (store_reg_p
4723 && !COMPLEX_MODE_P (DECL_MODE (expr))
4724 && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
4725 && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
4727 mode = DECL_MODE (expr);
4728 offset = 0;
4731 if (offset < 0 || offset >= MAX_VAR_PARTS)
4732 return false;
4734 if (mode_out)
4735 *mode_out = mode;
4736 if (offset_out)
4737 *offset_out = offset;
4738 return true;
4741 /* Return the MODE lowpart of LOC, or null if LOC is not something we
4742 want to track. When returning nonnull, make sure that the attributes
4743 on the returned value are updated. */
4745 static rtx
4746 var_lowpart (enum machine_mode mode, rtx loc)
4748 unsigned int offset, reg_offset, regno;
4750 if (!REG_P (loc) && !MEM_P (loc))
4751 return NULL;
4753 if (GET_MODE (loc) == mode)
4754 return loc;
4756 offset = byte_lowpart_offset (mode, GET_MODE (loc));
4758 if (MEM_P (loc))
4759 return adjust_address_nv (loc, mode, offset);
4761 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
4762 regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
4763 reg_offset, mode);
4764 return gen_rtx_REG_offset (loc, mode, regno, offset);
4767 /* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or
4768 hard_frame_pointer_rtx is being mapped to it. */
4769 static rtx cfa_base_rtx;
4771 /* Carry information about uses and stores while walking rtx. */
4773 struct count_use_info
4775 /* The insn where the RTX is. */
4776 rtx insn;
4778 /* The basic block where insn is. */
4779 basic_block bb;
4781 /* The array of n_sets sets in the insn, as determined by cselib. */
4782 struct cselib_set *sets;
4783 int n_sets;
4785 /* True if we're counting stores, false otherwise. */
4786 bool store_p;
4789 /* Find a VALUE corresponding to X. */
4791 static inline cselib_val *
4792 find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
4794 int i;
4796 if (cui->sets)
4798 /* This is called after uses are set up and before stores are
4799 processed bycselib, so it's safe to look up srcs, but not
4800 dsts. So we look up expressions that appear in srcs or in
4801 dest expressions, but we search the sets array for dests of
4802 stores. */
4803 if (cui->store_p)
4805 for (i = 0; i < cui->n_sets; i++)
4806 if (cui->sets[i].dest == x)
4807 return cui->sets[i].src_elt;
4809 else
4810 return cselib_lookup (x, mode, 0);
4813 return NULL;
4816 /* Helper function to get mode of MEM's address. */
4818 static inline enum machine_mode
4819 get_address_mode (rtx mem)
4821 enum machine_mode mode = GET_MODE (XEXP (mem, 0));
4822 if (mode != VOIDmode)
4823 return mode;
4824 return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
4827 /* Replace all registers and addresses in an expression with VALUE
4828 expressions that map back to them, unless the expression is a
4829 register. If no mapping is or can be performed, returns NULL. */
4831 static rtx
4832 replace_expr_with_values (rtx loc)
4834 if (REG_P (loc))
4835 return NULL;
4836 else if (MEM_P (loc))
4838 cselib_val *addr = cselib_lookup (XEXP (loc, 0),
4839 get_address_mode (loc), 0);
4840 if (addr)
4841 return replace_equiv_address_nv (loc, addr->val_rtx);
4842 else
4843 return NULL;
4845 else
4846 return cselib_subst_to_values (loc);
4849 /* Determine what kind of micro operation to choose for a USE. Return
4850 MO_CLOBBER if no micro operation is to be generated. */
4852 static enum micro_operation_type
4853 use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
4855 tree expr;
4857 if (cui && cui->sets)
4859 if (GET_CODE (loc) == VAR_LOCATION)
4861 if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false))
4863 rtx ploc = PAT_VAR_LOCATION_LOC (loc);
4864 if (! VAR_LOC_UNKNOWN_P (ploc))
4866 cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1);
4868 /* ??? flag_float_store and volatile mems are never
4869 given values, but we could in theory use them for
4870 locations. */
4871 gcc_assert (val || 1);
4873 return MO_VAL_LOC;
4875 else
4876 return MO_CLOBBER;
4879 if (REG_P (loc) || MEM_P (loc))
4881 if (modep)
4882 *modep = GET_MODE (loc);
4883 if (cui->store_p)
4885 if (REG_P (loc)
4886 || (find_use_val (loc, GET_MODE (loc), cui)
4887 && cselib_lookup (XEXP (loc, 0),
4888 get_address_mode (loc), 0)))
4889 return MO_VAL_SET;
4891 else
4893 cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
4895 if (val && !cselib_preserved_value_p (val))
4896 return MO_VAL_USE;
4901 if (REG_P (loc))
4903 gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER);
4905 if (loc == cfa_base_rtx)
4906 return MO_CLOBBER;
4907 expr = REG_EXPR (loc);
4909 if (!expr)
4910 return MO_USE_NO_VAR;
4911 else if (target_for_debug_bind (var_debug_decl (expr)))
4912 return MO_CLOBBER;
4913 else if (track_loc_p (loc, expr, REG_OFFSET (loc),
4914 false, modep, NULL))
4915 return MO_USE;
4916 else
4917 return MO_USE_NO_VAR;
4919 else if (MEM_P (loc))
4921 expr = MEM_EXPR (loc);
4923 if (!expr)
4924 return MO_CLOBBER;
4925 else if (target_for_debug_bind (var_debug_decl (expr)))
4926 return MO_CLOBBER;
4927 else if (track_loc_p (loc, expr, INT_MEM_OFFSET (loc),
4928 false, modep, NULL))
4929 return MO_USE;
4930 else
4931 return MO_CLOBBER;
4934 return MO_CLOBBER;
4937 /* Log to OUT information about micro-operation MOPT involving X in
4938 INSN of BB. */
4940 static inline void
4941 log_op_type (rtx x, basic_block bb, rtx insn,
4942 enum micro_operation_type mopt, FILE *out)
4944 fprintf (out, "bb %i op %i insn %i %s ",
4945 bb->index, VEC_length (micro_operation, VTI (bb)->mos),
4946 INSN_UID (insn), micro_operation_type_name[mopt]);
4947 print_inline_rtx (out, x, 2);
4948 fputc ('\n', out);
4951 /* Tell whether the CONCAT used to holds a VALUE and its location
4952 needs value resolution, i.e., an attempt of mapping the location
4953 back to other incoming values. */
4954 #define VAL_NEEDS_RESOLUTION(x) \
4955 (RTL_FLAG_CHECK1 ("VAL_NEEDS_RESOLUTION", (x), CONCAT)->volatil)
4956 /* Whether the location in the CONCAT is a tracked expression, that
4957 should also be handled like a MO_USE. */
4958 #define VAL_HOLDS_TRACK_EXPR(x) \
4959 (RTL_FLAG_CHECK1 ("VAL_HOLDS_TRACK_EXPR", (x), CONCAT)->used)
4960 /* Whether the location in the CONCAT should be handled like a MO_COPY
4961 as well. */
4962 #define VAL_EXPR_IS_COPIED(x) \
4963 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_COPIED", (x), CONCAT)->jump)
4964 /* Whether the location in the CONCAT should be handled like a
4965 MO_CLOBBER as well. */
4966 #define VAL_EXPR_IS_CLOBBERED(x) \
4967 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_CLOBBERED", (x), CONCAT)->unchanging)
4968 /* Whether the location is a CONCAT of the MO_VAL_SET expression and
4969 a reverse operation that should be handled afterwards. */
4970 #define VAL_EXPR_HAS_REVERSE(x) \
4971 (RTL_FLAG_CHECK1 ("VAL_EXPR_HAS_REVERSE", (x), CONCAT)->return_val)
4973 /* All preserved VALUEs. */
4974 static VEC (rtx, heap) *preserved_values;
4976 /* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */
4978 static void
4979 preserve_value (cselib_val *val)
4981 cselib_preserve_value (val);
4982 VEC_safe_push (rtx, heap, preserved_values, val->val_rtx);
4985 /* Helper function for MO_VAL_LOC handling. Return non-zero if
4986 any rtxes not suitable for CONST use not replaced by VALUEs
4987 are discovered. */
4989 static int
4990 non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED)
4992 if (*x == NULL_RTX)
4993 return 0;
4995 switch (GET_CODE (*x))
4997 case REG:
4998 case DEBUG_EXPR:
4999 case PC:
5000 case SCRATCH:
5001 case CC0:
5002 case ASM_INPUT:
5003 case ASM_OPERANDS:
5004 return 1;
5005 case MEM:
5006 return !MEM_READONLY_P (*x);
5007 default:
5008 return 0;
5012 /* Add uses (register and memory references) LOC which will be tracked
5013 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */
5015 static int
5016 add_uses (rtx *ploc, void *data)
5018 rtx loc = *ploc;
5019 enum machine_mode mode = VOIDmode;
5020 struct count_use_info *cui = (struct count_use_info *)data;
5021 enum micro_operation_type type = use_type (loc, cui, &mode);
5023 if (type != MO_CLOBBER)
5025 basic_block bb = cui->bb;
5026 micro_operation mo;
5028 mo.type = type;
5029 mo.u.loc = type == MO_USE ? var_lowpart (mode, loc) : loc;
5030 mo.insn = cui->insn;
5032 if (type == MO_VAL_LOC)
5034 rtx oloc = loc;
5035 rtx vloc = PAT_VAR_LOCATION_LOC (oloc);
5036 cselib_val *val;
5038 gcc_assert (cui->sets);
5040 if (MEM_P (vloc)
5041 && !REG_P (XEXP (vloc, 0))
5042 && !MEM_P (XEXP (vloc, 0))
5043 && (GET_CODE (XEXP (vloc, 0)) != PLUS
5044 || XEXP (XEXP (vloc, 0), 0) != cfa_base_rtx
5045 || !CONST_INT_P (XEXP (XEXP (vloc, 0), 1))))
5047 rtx mloc = vloc;
5048 enum machine_mode address_mode = get_address_mode (mloc);
5049 cselib_val *val
5050 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
5052 if (val && !cselib_preserved_value_p (val))
5054 micro_operation moa;
5055 preserve_value (val);
5056 mloc = cselib_subst_to_values (XEXP (mloc, 0));
5057 moa.type = MO_VAL_USE;
5058 moa.insn = cui->insn;
5059 moa.u.loc = gen_rtx_CONCAT (address_mode,
5060 val->val_rtx, mloc);
5061 if (dump_file && (dump_flags & TDF_DETAILS))
5062 log_op_type (moa.u.loc, cui->bb, cui->insn,
5063 moa.type, dump_file);
5064 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
5068 if (CONSTANT_P (vloc)
5069 && (GET_CODE (vloc) != CONST
5070 || for_each_rtx (&vloc, non_suitable_const, NULL)))
5071 /* For constants don't look up any value. */;
5072 else if (!VAR_LOC_UNKNOWN_P (vloc)
5073 && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
5075 enum machine_mode mode2;
5076 enum micro_operation_type type2;
5077 rtx nloc = replace_expr_with_values (vloc);
5079 if (nloc)
5081 oloc = shallow_copy_rtx (oloc);
5082 PAT_VAR_LOCATION_LOC (oloc) = nloc;
5085 oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc);
5087 type2 = use_type (vloc, 0, &mode2);
5089 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
5090 || type2 == MO_CLOBBER);
5092 if (type2 == MO_CLOBBER
5093 && !cselib_preserved_value_p (val))
5095 VAL_NEEDS_RESOLUTION (oloc) = 1;
5096 preserve_value (val);
5099 else if (!VAR_LOC_UNKNOWN_P (vloc))
5101 oloc = shallow_copy_rtx (oloc);
5102 PAT_VAR_LOCATION_LOC (oloc) = gen_rtx_UNKNOWN_VAR_LOC ();
5105 mo.u.loc = oloc;
5107 else if (type == MO_VAL_USE)
5109 enum machine_mode mode2 = VOIDmode;
5110 enum micro_operation_type type2;
5111 cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
5112 rtx vloc, oloc = loc, nloc;
5114 gcc_assert (cui->sets);
5116 if (MEM_P (oloc)
5117 && !REG_P (XEXP (oloc, 0))
5118 && !MEM_P (XEXP (oloc, 0))
5119 && (GET_CODE (XEXP (oloc, 0)) != PLUS
5120 || XEXP (XEXP (oloc, 0), 0) != cfa_base_rtx
5121 || !CONST_INT_P (XEXP (XEXP (oloc, 0), 1))))
5123 rtx mloc = oloc;
5124 enum machine_mode address_mode = get_address_mode (mloc);
5125 cselib_val *val
5126 = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
5128 if (val && !cselib_preserved_value_p (val))
5130 micro_operation moa;
5131 preserve_value (val);
5132 mloc = cselib_subst_to_values (XEXP (mloc, 0));
5133 moa.type = MO_VAL_USE;
5134 moa.insn = cui->insn;
5135 moa.u.loc = gen_rtx_CONCAT (address_mode,
5136 val->val_rtx, mloc);
5137 if (dump_file && (dump_flags & TDF_DETAILS))
5138 log_op_type (moa.u.loc, cui->bb, cui->insn,
5139 moa.type, dump_file);
5140 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
5144 type2 = use_type (loc, 0, &mode2);
5146 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR
5147 || type2 == MO_CLOBBER);
5149 if (type2 == MO_USE)
5150 vloc = var_lowpart (mode2, loc);
5151 else
5152 vloc = oloc;
5154 /* The loc of a MO_VAL_USE may have two forms:
5156 (concat val src): val is at src, a value-based
5157 representation.
5159 (concat (concat val use) src): same as above, with use as
5160 the MO_USE tracked value, if it differs from src.
5164 nloc = replace_expr_with_values (loc);
5165 if (!nloc)
5166 nloc = oloc;
5168 if (vloc != nloc)
5169 oloc = gen_rtx_CONCAT (mode2, val->val_rtx, vloc);
5170 else
5171 oloc = val->val_rtx;
5173 mo.u.loc = gen_rtx_CONCAT (mode, oloc, nloc);
5175 if (type2 == MO_USE)
5176 VAL_HOLDS_TRACK_EXPR (mo.u.loc) = 1;
5177 if (!cselib_preserved_value_p (val))
5179 VAL_NEEDS_RESOLUTION (mo.u.loc) = 1;
5180 preserve_value (val);
5183 else
5184 gcc_assert (type == MO_USE || type == MO_USE_NO_VAR);
5186 if (dump_file && (dump_flags & TDF_DETAILS))
5187 log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
5188 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5191 return 0;
5194 /* Helper function for finding all uses of REG/MEM in X in insn INSN. */
5196 static void
5197 add_uses_1 (rtx *x, void *cui)
5199 for_each_rtx (x, add_uses, cui);
5202 /* Attempt to reverse the EXPR operation in the debug info. Say for
5203 reg1 = reg2 + 6 even when reg2 is no longer live we
5204 can express its value as VAL - 6. */
5206 static rtx
5207 reverse_op (rtx val, const_rtx expr)
5209 rtx src, arg, ret;
5210 cselib_val *v;
5211 enum rtx_code code;
5213 if (GET_CODE (expr) != SET)
5214 return NULL_RTX;
5216 if (!REG_P (SET_DEST (expr)) || GET_MODE (val) != GET_MODE (SET_DEST (expr)))
5217 return NULL_RTX;
5219 src = SET_SRC (expr);
5220 switch (GET_CODE (src))
5222 case PLUS:
5223 case MINUS:
5224 case XOR:
5225 case NOT:
5226 case NEG:
5227 case SIGN_EXTEND:
5228 case ZERO_EXTEND:
5229 break;
5230 default:
5231 return NULL_RTX;
5234 if (!REG_P (XEXP (src, 0))
5235 || !SCALAR_INT_MODE_P (GET_MODE (src))
5236 || XEXP (src, 0) == cfa_base_rtx)
5237 return NULL_RTX;
5239 v = cselib_lookup (XEXP (src, 0), GET_MODE (XEXP (src, 0)), 0);
5240 if (!v || !cselib_preserved_value_p (v))
5241 return NULL_RTX;
5243 switch (GET_CODE (src))
5245 case NOT:
5246 case NEG:
5247 if (GET_MODE (v->val_rtx) != GET_MODE (val))
5248 return NULL_RTX;
5249 ret = gen_rtx_fmt_e (GET_CODE (src), GET_MODE (val), val);
5250 break;
5251 case SIGN_EXTEND:
5252 case ZERO_EXTEND:
5253 ret = gen_lowpart_SUBREG (GET_MODE (v->val_rtx), val);
5254 break;
5255 case XOR:
5256 code = XOR;
5257 goto binary;
5258 case PLUS:
5259 code = MINUS;
5260 goto binary;
5261 case MINUS:
5262 code = PLUS;
5263 goto binary;
5264 binary:
5265 if (GET_MODE (v->val_rtx) != GET_MODE (val))
5266 return NULL_RTX;
5267 arg = XEXP (src, 1);
5268 if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
5270 arg = cselib_expand_value_rtx (arg, scratch_regs, 5);
5271 if (arg == NULL_RTX)
5272 return NULL_RTX;
5273 if (!CONST_INT_P (arg) && GET_CODE (arg) != SYMBOL_REF)
5274 return NULL_RTX;
5276 ret = simplify_gen_binary (code, GET_MODE (val), val, arg);
5277 if (ret == val)
5278 /* Ensure ret isn't VALUE itself (which can happen e.g. for
5279 (plus (reg1) (reg2)) when reg2 is known to be 0), as that
5280 breaks a lot of routines during var-tracking. */
5281 ret = gen_rtx_fmt_ee (PLUS, GET_MODE (val), val, const0_rtx);
5282 break;
5283 default:
5284 gcc_unreachable ();
5287 return gen_rtx_CONCAT (GET_MODE (v->val_rtx), v->val_rtx, ret);
5290 /* Add stores (register and memory references) LOC which will be tracked
5291 to VTI (bb)->mos. EXPR is the RTL expression containing the store.
5292 CUIP->insn is instruction which the LOC is part of. */
5294 static void
5295 add_stores (rtx loc, const_rtx expr, void *cuip)
5297 enum machine_mode mode = VOIDmode, mode2;
5298 struct count_use_info *cui = (struct count_use_info *)cuip;
5299 basic_block bb = cui->bb;
5300 micro_operation mo;
5301 rtx oloc = loc, nloc, src = NULL;
5302 enum micro_operation_type type = use_type (loc, cui, &mode);
5303 bool track_p = false;
5304 cselib_val *v;
5305 bool resolve, preserve;
5306 rtx reverse;
5308 if (type == MO_CLOBBER)
5309 return;
5311 mode2 = mode;
5313 if (REG_P (loc))
5315 gcc_assert (loc != cfa_base_rtx);
5316 if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET)
5317 || !(track_p = use_type (loc, NULL, &mode2) == MO_USE)
5318 || GET_CODE (expr) == CLOBBER)
5320 mo.type = MO_CLOBBER;
5321 mo.u.loc = loc;
5323 else
5325 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
5326 src = var_lowpart (mode2, SET_SRC (expr));
5327 loc = var_lowpart (mode2, loc);
5329 if (src == NULL)
5331 mo.type = MO_SET;
5332 mo.u.loc = loc;
5334 else
5336 rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
5337 if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
5338 mo.type = MO_COPY;
5339 else
5340 mo.type = MO_SET;
5341 mo.u.loc = xexpr;
5344 mo.insn = cui->insn;
5346 else if (MEM_P (loc)
5347 && ((track_p = use_type (loc, NULL, &mode2) == MO_USE)
5348 || cui->sets))
5350 if (MEM_P (loc) && type == MO_VAL_SET
5351 && !REG_P (XEXP (loc, 0))
5352 && !MEM_P (XEXP (loc, 0))
5353 && (GET_CODE (XEXP (loc, 0)) != PLUS
5354 || XEXP (XEXP (loc, 0), 0) != cfa_base_rtx
5355 || !CONST_INT_P (XEXP (XEXP (loc, 0), 1))))
5357 rtx mloc = loc;
5358 enum machine_mode address_mode = get_address_mode (mloc);
5359 cselib_val *val = cselib_lookup (XEXP (mloc, 0),
5360 address_mode, 0);
5362 if (val && !cselib_preserved_value_p (val))
5364 preserve_value (val);
5365 mo.type = MO_VAL_USE;
5366 mloc = cselib_subst_to_values (XEXP (mloc, 0));
5367 mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
5368 mo.insn = cui->insn;
5369 if (dump_file && (dump_flags & TDF_DETAILS))
5370 log_op_type (mo.u.loc, cui->bb, cui->insn,
5371 mo.type, dump_file);
5372 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5376 if (GET_CODE (expr) == CLOBBER || !track_p)
5378 mo.type = MO_CLOBBER;
5379 mo.u.loc = track_p ? var_lowpart (mode2, loc) : loc;
5381 else
5383 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc)
5384 src = var_lowpart (mode2, SET_SRC (expr));
5385 loc = var_lowpart (mode2, loc);
5387 if (src == NULL)
5389 mo.type = MO_SET;
5390 mo.u.loc = loc;
5392 else
5394 rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
5395 if (same_variable_part_p (SET_SRC (xexpr),
5396 MEM_EXPR (loc),
5397 INT_MEM_OFFSET (loc)))
5398 mo.type = MO_COPY;
5399 else
5400 mo.type = MO_SET;
5401 mo.u.loc = xexpr;
5404 mo.insn = cui->insn;
5406 else
5407 return;
5409 if (type != MO_VAL_SET)
5410 goto log_and_return;
5412 v = find_use_val (oloc, mode, cui);
5414 if (!v)
5415 goto log_and_return;
5417 resolve = preserve = !cselib_preserved_value_p (v);
5419 nloc = replace_expr_with_values (oloc);
5420 if (nloc)
5421 oloc = nloc;
5423 if (GET_CODE (PATTERN (cui->insn)) == COND_EXEC)
5425 cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0);
5427 gcc_assert (oval != v);
5428 gcc_assert (REG_P (oloc) || MEM_P (oloc));
5430 if (!cselib_preserved_value_p (oval))
5432 micro_operation moa;
5434 preserve_value (oval);
5436 moa.type = MO_VAL_USE;
5437 moa.u.loc = gen_rtx_CONCAT (mode, oval->val_rtx, oloc);
5438 VAL_NEEDS_RESOLUTION (moa.u.loc) = 1;
5439 moa.insn = cui->insn;
5441 if (dump_file && (dump_flags & TDF_DETAILS))
5442 log_op_type (moa.u.loc, cui->bb, cui->insn,
5443 moa.type, dump_file);
5444 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
5447 resolve = false;
5449 else if (resolve && GET_CODE (mo.u.loc) == SET)
5451 nloc = replace_expr_with_values (SET_SRC (expr));
5453 /* Avoid the mode mismatch between oexpr and expr. */
5454 if (!nloc && mode != mode2)
5456 nloc = SET_SRC (expr);
5457 gcc_assert (oloc == SET_DEST (expr));
5460 if (nloc)
5461 oloc = gen_rtx_SET (GET_MODE (mo.u.loc), oloc, nloc);
5462 else
5464 if (oloc == SET_DEST (mo.u.loc))
5465 /* No point in duplicating. */
5466 oloc = mo.u.loc;
5467 if (!REG_P (SET_SRC (mo.u.loc)))
5468 resolve = false;
5471 else if (!resolve)
5473 if (GET_CODE (mo.u.loc) == SET
5474 && oloc == SET_DEST (mo.u.loc))
5475 /* No point in duplicating. */
5476 oloc = mo.u.loc;
5478 else
5479 resolve = false;
5481 loc = gen_rtx_CONCAT (mode, v->val_rtx, oloc);
5483 if (mo.u.loc != oloc)
5484 loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, mo.u.loc);
5486 /* The loc of a MO_VAL_SET may have various forms:
5488 (concat val dst): dst now holds val
5490 (concat val (set dst src)): dst now holds val, copied from src
5492 (concat (concat val dstv) dst): dst now holds val; dstv is dst
5493 after replacing mems and non-top-level regs with values.
5495 (concat (concat val dstv) (set dst src)): dst now holds val,
5496 copied from src. dstv is a value-based representation of dst, if
5497 it differs from dst. If resolution is needed, src is a REG, and
5498 its mode is the same as that of val.
5500 (concat (concat val (set dstv srcv)) (set dst src)): src
5501 copied to dst, holding val. dstv and srcv are value-based
5502 representations of dst and src, respectively.
5506 if (GET_CODE (PATTERN (cui->insn)) != COND_EXEC)
5508 reverse = reverse_op (v->val_rtx, expr);
5509 if (reverse)
5511 loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, reverse);
5512 VAL_EXPR_HAS_REVERSE (loc) = 1;
5516 mo.u.loc = loc;
5518 if (track_p)
5519 VAL_HOLDS_TRACK_EXPR (loc) = 1;
5520 if (preserve)
5522 VAL_NEEDS_RESOLUTION (loc) = resolve;
5523 preserve_value (v);
5525 if (mo.type == MO_CLOBBER)
5526 VAL_EXPR_IS_CLOBBERED (loc) = 1;
5527 if (mo.type == MO_COPY)
5528 VAL_EXPR_IS_COPIED (loc) = 1;
5530 mo.type = MO_VAL_SET;
5532 log_and_return:
5533 if (dump_file && (dump_flags & TDF_DETAILS))
5534 log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
5535 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5538 /* Callback for cselib_record_sets_hook, that records as micro
5539 operations uses and stores in an insn after cselib_record_sets has
5540 analyzed the sets in an insn, but before it modifies the stored
5541 values in the internal tables, unless cselib_record_sets doesn't
5542 call it directly (perhaps because we're not doing cselib in the
5543 first place, in which case sets and n_sets will be 0). */
5545 static void
5546 add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
5548 basic_block bb = BLOCK_FOR_INSN (insn);
5549 int n1, n2;
5550 struct count_use_info cui;
5551 micro_operation *mos;
5553 cselib_hook_called = true;
5555 cui.insn = insn;
5556 cui.bb = bb;
5557 cui.sets = sets;
5558 cui.n_sets = n_sets;
5560 n1 = VEC_length (micro_operation, VTI (bb)->mos);
5561 cui.store_p = false;
5562 note_uses (&PATTERN (insn), add_uses_1, &cui);
5563 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5564 mos = VEC_address (micro_operation, VTI (bb)->mos);
5566 /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
5567 MO_VAL_LOC last. */
5568 while (n1 < n2)
5570 while (n1 < n2 && mos[n1].type == MO_USE)
5571 n1++;
5572 while (n1 < n2 && mos[n2].type != MO_USE)
5573 n2--;
5574 if (n1 < n2)
5576 micro_operation sw;
5578 sw = mos[n1];
5579 mos[n1] = mos[n2];
5580 mos[n2] = sw;
5584 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5585 while (n1 < n2)
5587 while (n1 < n2 && mos[n1].type != MO_VAL_LOC)
5588 n1++;
5589 while (n1 < n2 && mos[n2].type == MO_VAL_LOC)
5590 n2--;
5591 if (n1 < n2)
5593 micro_operation sw;
5595 sw = mos[n1];
5596 mos[n1] = mos[n2];
5597 mos[n2] = sw;
5601 if (CALL_P (insn))
5603 micro_operation mo;
5605 mo.type = MO_CALL;
5606 mo.insn = insn;
5607 mo.u.loc = NULL_RTX;
5609 if (dump_file && (dump_flags & TDF_DETAILS))
5610 log_op_type (PATTERN (insn), bb, insn, mo.type, dump_file);
5611 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
5614 n1 = VEC_length (micro_operation, VTI (bb)->mos);
5615 /* This will record NEXT_INSN (insn), such that we can
5616 insert notes before it without worrying about any
5617 notes that MO_USEs might emit after the insn. */
5618 cui.store_p = true;
5619 note_stores (PATTERN (insn), add_stores, &cui);
5620 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5621 mos = VEC_address (micro_operation, VTI (bb)->mos);
5623 /* Order the MO_VAL_USEs first (note_stores does nothing
5624 on DEBUG_INSNs, so there are no MO_VAL_LOCs from this
5625 insn), then MO_CLOBBERs, then MO_SET/MO_COPY/MO_VAL_SET. */
5626 while (n1 < n2)
5628 while (n1 < n2 && mos[n1].type == MO_VAL_USE)
5629 n1++;
5630 while (n1 < n2 && mos[n2].type != MO_VAL_USE)
5631 n2--;
5632 if (n1 < n2)
5634 micro_operation sw;
5636 sw = mos[n1];
5637 mos[n1] = mos[n2];
5638 mos[n2] = sw;
5642 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1;
5643 while (n1 < n2)
5645 while (n1 < n2 && mos[n1].type == MO_CLOBBER)
5646 n1++;
5647 while (n1 < n2 && mos[n2].type != MO_CLOBBER)
5648 n2--;
5649 if (n1 < n2)
5651 micro_operation sw;
5653 sw = mos[n1];
5654 mos[n1] = mos[n2];
5655 mos[n2] = sw;
5660 static enum var_init_status
5661 find_src_status (dataflow_set *in, rtx src)
5663 tree decl = NULL_TREE;
5664 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
5666 if (! flag_var_tracking_uninit)
5667 status = VAR_INIT_STATUS_INITIALIZED;
5669 if (src && REG_P (src))
5670 decl = var_debug_decl (REG_EXPR (src));
5671 else if (src && MEM_P (src))
5672 decl = var_debug_decl (MEM_EXPR (src));
5674 if (src && decl)
5675 status = get_init_value (in, src, dv_from_decl (decl));
5677 return status;
5680 /* SRC is the source of an assignment. Use SET to try to find what
5681 was ultimately assigned to SRC. Return that value if known,
5682 otherwise return SRC itself. */
5684 static rtx
5685 find_src_set_src (dataflow_set *set, rtx src)
5687 tree decl = NULL_TREE; /* The variable being copied around. */
5688 rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */
5689 variable var;
5690 location_chain nextp;
5691 int i;
5692 bool found;
5694 if (src && REG_P (src))
5695 decl = var_debug_decl (REG_EXPR (src));
5696 else if (src && MEM_P (src))
5697 decl = var_debug_decl (MEM_EXPR (src));
5699 if (src && decl)
5701 decl_or_value dv = dv_from_decl (decl);
5703 var = shared_hash_find (set->vars, dv);
5704 if (var)
5706 found = false;
5707 for (i = 0; i < var->n_var_parts && !found; i++)
5708 for (nextp = var->var_part[i].loc_chain; nextp && !found;
5709 nextp = nextp->next)
5710 if (rtx_equal_p (nextp->loc, src))
5712 set_src = nextp->set_src;
5713 found = true;
5719 return set_src;
5722 /* Compute the changes of variable locations in the basic block BB. */
5724 static bool
5725 compute_bb_dataflow (basic_block bb)
5727 unsigned int i;
5728 micro_operation *mo;
5729 bool changed;
5730 dataflow_set old_out;
5731 dataflow_set *in = &VTI (bb)->in;
5732 dataflow_set *out = &VTI (bb)->out;
5734 dataflow_set_init (&old_out);
5735 dataflow_set_copy (&old_out, out);
5736 dataflow_set_copy (out, in);
5738 for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
5740 rtx insn = mo->insn;
5742 switch (mo->type)
5744 case MO_CALL:
5745 dataflow_set_clear_at_call (out);
5746 break;
5748 case MO_USE:
5750 rtx loc = mo->u.loc;
5752 if (REG_P (loc))
5753 var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5754 else if (MEM_P (loc))
5755 var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
5757 break;
5759 case MO_VAL_LOC:
5761 rtx loc = mo->u.loc;
5762 rtx val, vloc;
5763 tree var;
5765 if (GET_CODE (loc) == CONCAT)
5767 val = XEXP (loc, 0);
5768 vloc = XEXP (loc, 1);
5770 else
5772 val = NULL_RTX;
5773 vloc = loc;
5776 var = PAT_VAR_LOCATION_DECL (vloc);
5778 clobber_variable_part (out, NULL_RTX,
5779 dv_from_decl (var), 0, NULL_RTX);
5780 if (val)
5782 if (VAL_NEEDS_RESOLUTION (loc))
5783 val_resolve (out, val, PAT_VAR_LOCATION_LOC (vloc), insn);
5784 set_variable_part (out, val, dv_from_decl (var), 0,
5785 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
5786 INSERT);
5788 else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
5789 set_variable_part (out, PAT_VAR_LOCATION_LOC (vloc),
5790 dv_from_decl (var), 0,
5791 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
5792 INSERT);
5794 break;
5796 case MO_VAL_USE:
5798 rtx loc = mo->u.loc;
5799 rtx val, vloc, uloc;
5801 vloc = uloc = XEXP (loc, 1);
5802 val = XEXP (loc, 0);
5804 if (GET_CODE (val) == CONCAT)
5806 uloc = XEXP (val, 1);
5807 val = XEXP (val, 0);
5810 if (VAL_NEEDS_RESOLUTION (loc))
5811 val_resolve (out, val, vloc, insn);
5812 else
5813 val_store (out, val, uloc, insn, false);
5815 if (VAL_HOLDS_TRACK_EXPR (loc))
5817 if (GET_CODE (uloc) == REG)
5818 var_reg_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5819 NULL);
5820 else if (GET_CODE (uloc) == MEM)
5821 var_mem_set (out, uloc, VAR_INIT_STATUS_UNINITIALIZED,
5822 NULL);
5825 break;
5827 case MO_VAL_SET:
5829 rtx loc = mo->u.loc;
5830 rtx val, vloc, uloc, reverse = NULL_RTX;
5832 vloc = loc;
5833 if (VAL_EXPR_HAS_REVERSE (loc))
5835 reverse = XEXP (loc, 1);
5836 vloc = XEXP (loc, 0);
5838 uloc = XEXP (vloc, 1);
5839 val = XEXP (vloc, 0);
5840 vloc = uloc;
5842 if (GET_CODE (val) == CONCAT)
5844 vloc = XEXP (val, 1);
5845 val = XEXP (val, 0);
5848 if (GET_CODE (vloc) == SET)
5850 rtx vsrc = SET_SRC (vloc);
5852 gcc_assert (val != vsrc);
5853 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
5855 vloc = SET_DEST (vloc);
5857 if (VAL_NEEDS_RESOLUTION (loc))
5858 val_resolve (out, val, vsrc, insn);
5860 else if (VAL_NEEDS_RESOLUTION (loc))
5862 gcc_assert (GET_CODE (uloc) == SET
5863 && GET_CODE (SET_SRC (uloc)) == REG);
5864 val_resolve (out, val, SET_SRC (uloc), insn);
5867 if (VAL_HOLDS_TRACK_EXPR (loc))
5869 if (VAL_EXPR_IS_CLOBBERED (loc))
5871 if (REG_P (uloc))
5872 var_reg_delete (out, uloc, true);
5873 else if (MEM_P (uloc))
5874 var_mem_delete (out, uloc, true);
5876 else
5878 bool copied_p = VAL_EXPR_IS_COPIED (loc);
5879 rtx set_src = NULL;
5880 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
5882 if (GET_CODE (uloc) == SET)
5884 set_src = SET_SRC (uloc);
5885 uloc = SET_DEST (uloc);
5888 if (copied_p)
5890 if (flag_var_tracking_uninit)
5892 status = find_src_status (in, set_src);
5894 if (status == VAR_INIT_STATUS_UNKNOWN)
5895 status = find_src_status (out, set_src);
5898 set_src = find_src_set_src (in, set_src);
5901 if (REG_P (uloc))
5902 var_reg_delete_and_set (out, uloc, !copied_p,
5903 status, set_src);
5904 else if (MEM_P (uloc))
5905 var_mem_delete_and_set (out, uloc, !copied_p,
5906 status, set_src);
5909 else if (REG_P (uloc))
5910 var_regno_delete (out, REGNO (uloc));
5912 val_store (out, val, vloc, insn, true);
5914 if (reverse)
5915 val_store (out, XEXP (reverse, 0), XEXP (reverse, 1),
5916 insn, false);
5918 break;
5920 case MO_SET:
5922 rtx loc = mo->u.loc;
5923 rtx set_src = NULL;
5925 if (GET_CODE (loc) == SET)
5927 set_src = SET_SRC (loc);
5928 loc = SET_DEST (loc);
5931 if (REG_P (loc))
5932 var_reg_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5933 set_src);
5934 else if (MEM_P (loc))
5935 var_mem_delete_and_set (out, loc, true, VAR_INIT_STATUS_INITIALIZED,
5936 set_src);
5938 break;
5940 case MO_COPY:
5942 rtx loc = mo->u.loc;
5943 enum var_init_status src_status;
5944 rtx set_src = NULL;
5946 if (GET_CODE (loc) == SET)
5948 set_src = SET_SRC (loc);
5949 loc = SET_DEST (loc);
5952 if (! flag_var_tracking_uninit)
5953 src_status = VAR_INIT_STATUS_INITIALIZED;
5954 else
5956 src_status = find_src_status (in, set_src);
5958 if (src_status == VAR_INIT_STATUS_UNKNOWN)
5959 src_status = find_src_status (out, set_src);
5962 set_src = find_src_set_src (in, set_src);
5964 if (REG_P (loc))
5965 var_reg_delete_and_set (out, loc, false, src_status, set_src);
5966 else if (MEM_P (loc))
5967 var_mem_delete_and_set (out, loc, false, src_status, set_src);
5969 break;
5971 case MO_USE_NO_VAR:
5973 rtx loc = mo->u.loc;
5975 if (REG_P (loc))
5976 var_reg_delete (out, loc, false);
5977 else if (MEM_P (loc))
5978 var_mem_delete (out, loc, false);
5980 break;
5982 case MO_CLOBBER:
5984 rtx loc = mo->u.loc;
5986 if (REG_P (loc))
5987 var_reg_delete (out, loc, true);
5988 else if (MEM_P (loc))
5989 var_mem_delete (out, loc, true);
5991 break;
5993 case MO_ADJUST:
5994 out->stack_adjust += mo->u.adjust;
5995 break;
5999 if (MAY_HAVE_DEBUG_INSNS)
6001 dataflow_set_equiv_regs (out);
6002 htab_traverse (shared_hash_htab (out->vars), canonicalize_values_mark,
6003 out);
6004 htab_traverse (shared_hash_htab (out->vars), canonicalize_values_star,
6005 out);
6006 #if ENABLE_CHECKING
6007 htab_traverse (shared_hash_htab (out->vars),
6008 canonicalize_loc_order_check, out);
6009 #endif
6011 changed = dataflow_set_different (&old_out, out);
6012 dataflow_set_destroy (&old_out);
6013 return changed;
6016 /* Find the locations of variables in the whole function. */
6018 static bool
6019 vt_find_locations (void)
6021 fibheap_t worklist, pending, fibheap_swap;
6022 sbitmap visited, in_worklist, in_pending, sbitmap_swap;
6023 basic_block bb;
6024 edge e;
6025 int *bb_order;
6026 int *rc_order;
6027 int i;
6028 int htabsz = 0;
6029 int htabmax = PARAM_VALUE (PARAM_MAX_VARTRACK_SIZE);
6030 bool success = true;
6032 /* Compute reverse completion order of depth first search of the CFG
6033 so that the data-flow runs faster. */
6034 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
6035 bb_order = XNEWVEC (int, last_basic_block);
6036 pre_and_rev_post_order_compute (NULL, rc_order, false);
6037 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
6038 bb_order[rc_order[i]] = i;
6039 free (rc_order);
6041 worklist = fibheap_new ();
6042 pending = fibheap_new ();
6043 visited = sbitmap_alloc (last_basic_block);
6044 in_worklist = sbitmap_alloc (last_basic_block);
6045 in_pending = sbitmap_alloc (last_basic_block);
6046 sbitmap_zero (in_worklist);
6048 FOR_EACH_BB (bb)
6049 fibheap_insert (pending, bb_order[bb->index], bb);
6050 sbitmap_ones (in_pending);
6052 while (success && !fibheap_empty (pending))
6054 fibheap_swap = pending;
6055 pending = worklist;
6056 worklist = fibheap_swap;
6057 sbitmap_swap = in_pending;
6058 in_pending = in_worklist;
6059 in_worklist = sbitmap_swap;
6061 sbitmap_zero (visited);
6063 while (!fibheap_empty (worklist))
6065 bb = (basic_block) fibheap_extract_min (worklist);
6066 RESET_BIT (in_worklist, bb->index);
6067 if (!TEST_BIT (visited, bb->index))
6069 bool changed;
6070 edge_iterator ei;
6071 int oldinsz, oldoutsz;
6073 SET_BIT (visited, bb->index);
6075 if (VTI (bb)->in.vars)
6077 htabsz
6078 -= (htab_size (shared_hash_htab (VTI (bb)->in.vars))
6079 + htab_size (shared_hash_htab (VTI (bb)->out.vars)));
6080 oldinsz
6081 = htab_elements (shared_hash_htab (VTI (bb)->in.vars));
6082 oldoutsz
6083 = htab_elements (shared_hash_htab (VTI (bb)->out.vars));
6085 else
6086 oldinsz = oldoutsz = 0;
6088 if (MAY_HAVE_DEBUG_INSNS)
6090 dataflow_set *in = &VTI (bb)->in, *first_out = NULL;
6091 bool first = true, adjust = false;
6093 /* Calculate the IN set as the intersection of
6094 predecessor OUT sets. */
6096 dataflow_set_clear (in);
6097 dst_can_be_shared = true;
6099 FOR_EACH_EDGE (e, ei, bb->preds)
6100 if (!VTI (e->src)->flooded)
6101 gcc_assert (bb_order[bb->index]
6102 <= bb_order[e->src->index]);
6103 else if (first)
6105 dataflow_set_copy (in, &VTI (e->src)->out);
6106 first_out = &VTI (e->src)->out;
6107 first = false;
6109 else
6111 dataflow_set_merge (in, &VTI (e->src)->out);
6112 adjust = true;
6115 if (adjust)
6117 dataflow_post_merge_adjust (in, &VTI (bb)->permp);
6118 #if ENABLE_CHECKING
6119 /* Merge and merge_adjust should keep entries in
6120 canonical order. */
6121 htab_traverse (shared_hash_htab (in->vars),
6122 canonicalize_loc_order_check,
6123 in);
6124 #endif
6125 if (dst_can_be_shared)
6127 shared_hash_destroy (in->vars);
6128 in->vars = shared_hash_copy (first_out->vars);
6132 VTI (bb)->flooded = true;
6134 else
6136 /* Calculate the IN set as union of predecessor OUT sets. */
6137 dataflow_set_clear (&VTI (bb)->in);
6138 FOR_EACH_EDGE (e, ei, bb->preds)
6139 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
6142 changed = compute_bb_dataflow (bb);
6143 htabsz += (htab_size (shared_hash_htab (VTI (bb)->in.vars))
6144 + htab_size (shared_hash_htab (VTI (bb)->out.vars)));
6146 if (htabmax && htabsz > htabmax)
6148 if (MAY_HAVE_DEBUG_INSNS)
6149 inform (DECL_SOURCE_LOCATION (cfun->decl),
6150 "variable tracking size limit exceeded with "
6151 "-fvar-tracking-assignments, retrying without");
6152 else
6153 inform (DECL_SOURCE_LOCATION (cfun->decl),
6154 "variable tracking size limit exceeded");
6155 success = false;
6156 break;
6159 if (changed)
6161 FOR_EACH_EDGE (e, ei, bb->succs)
6163 if (e->dest == EXIT_BLOCK_PTR)
6164 continue;
6166 if (TEST_BIT (visited, e->dest->index))
6168 if (!TEST_BIT (in_pending, e->dest->index))
6170 /* Send E->DEST to next round. */
6171 SET_BIT (in_pending, e->dest->index);
6172 fibheap_insert (pending,
6173 bb_order[e->dest->index],
6174 e->dest);
6177 else if (!TEST_BIT (in_worklist, e->dest->index))
6179 /* Add E->DEST to current round. */
6180 SET_BIT (in_worklist, e->dest->index);
6181 fibheap_insert (worklist, bb_order[e->dest->index],
6182 e->dest);
6187 if (dump_file)
6188 fprintf (dump_file,
6189 "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n",
6190 bb->index,
6191 (int)htab_elements (shared_hash_htab (VTI (bb)->in.vars)),
6192 oldinsz,
6193 (int)htab_elements (shared_hash_htab (VTI (bb)->out.vars)),
6194 oldoutsz,
6195 (int)worklist->nodes, (int)pending->nodes, htabsz);
6197 if (dump_file && (dump_flags & TDF_DETAILS))
6199 fprintf (dump_file, "BB %i IN:\n", bb->index);
6200 dump_dataflow_set (&VTI (bb)->in);
6201 fprintf (dump_file, "BB %i OUT:\n", bb->index);
6202 dump_dataflow_set (&VTI (bb)->out);
6208 if (success && MAY_HAVE_DEBUG_INSNS)
6209 FOR_EACH_BB (bb)
6210 gcc_assert (VTI (bb)->flooded);
6212 free (bb_order);
6213 fibheap_delete (worklist);
6214 fibheap_delete (pending);
6215 sbitmap_free (visited);
6216 sbitmap_free (in_worklist);
6217 sbitmap_free (in_pending);
6219 return success;
6222 /* Print the content of the LIST to dump file. */
6224 static void
6225 dump_attrs_list (attrs list)
6227 for (; list; list = list->next)
6229 if (dv_is_decl_p (list->dv))
6230 print_mem_expr (dump_file, dv_as_decl (list->dv));
6231 else
6232 print_rtl_single (dump_file, dv_as_value (list->dv));
6233 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
6235 fprintf (dump_file, "\n");
6238 /* Print the information about variable *SLOT to dump file. */
6240 static int
6241 dump_var_slot (void **slot, void *data ATTRIBUTE_UNUSED)
6243 variable var = (variable) *slot;
6245 dump_var (var);
6247 /* Continue traversing the hash table. */
6248 return 1;
6251 /* Print the information about variable VAR to dump file. */
6253 static void
6254 dump_var (variable var)
6256 int i;
6257 location_chain node;
6259 if (dv_is_decl_p (var->dv))
6261 const_tree decl = dv_as_decl (var->dv);
6263 if (DECL_NAME (decl))
6265 fprintf (dump_file, " name: %s",
6266 IDENTIFIER_POINTER (DECL_NAME (decl)));
6267 if (dump_flags & TDF_UID)
6268 fprintf (dump_file, "D.%u", DECL_UID (decl));
6270 else if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
6271 fprintf (dump_file, " name: D#%u", DEBUG_TEMP_UID (decl));
6272 else
6273 fprintf (dump_file, " name: D.%u", DECL_UID (decl));
6274 fprintf (dump_file, "\n");
6276 else
6278 fputc (' ', dump_file);
6279 print_rtl_single (dump_file, dv_as_value (var->dv));
6282 for (i = 0; i < var->n_var_parts; i++)
6284 fprintf (dump_file, " offset %ld\n",
6285 (long) var->var_part[i].offset);
6286 for (node = var->var_part[i].loc_chain; node; node = node->next)
6288 fprintf (dump_file, " ");
6289 if (node->init == VAR_INIT_STATUS_UNINITIALIZED)
6290 fprintf (dump_file, "[uninit]");
6291 print_rtl_single (dump_file, node->loc);
6296 /* Print the information about variables from hash table VARS to dump file. */
6298 static void
6299 dump_vars (htab_t vars)
6301 if (htab_elements (vars) > 0)
6303 fprintf (dump_file, "Variables:\n");
6304 htab_traverse (vars, dump_var_slot, NULL);
6308 /* Print the dataflow set SET to dump file. */
6310 static void
6311 dump_dataflow_set (dataflow_set *set)
6313 int i;
6315 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
6316 set->stack_adjust);
6317 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
6319 if (set->regs[i])
6321 fprintf (dump_file, "Reg %d:", i);
6322 dump_attrs_list (set->regs[i]);
6325 dump_vars (shared_hash_htab (set->vars));
6326 fprintf (dump_file, "\n");
6329 /* Print the IN and OUT sets for each basic block to dump file. */
6331 static void
6332 dump_dataflow_sets (void)
6334 basic_block bb;
6336 FOR_EACH_BB (bb)
6338 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
6339 fprintf (dump_file, "IN:\n");
6340 dump_dataflow_set (&VTI (bb)->in);
6341 fprintf (dump_file, "OUT:\n");
6342 dump_dataflow_set (&VTI (bb)->out);
6346 /* Add variable VAR to the hash table of changed variables and
6347 if it has no locations delete it from SET's hash table. */
6349 static void
6350 variable_was_changed (variable var, dataflow_set *set)
6352 hashval_t hash = dv_htab_hash (var->dv);
6354 if (emit_notes)
6356 void **slot;
6357 bool old_cur_loc_changed = false;
6359 /* Remember this decl or VALUE has been added to changed_variables. */
6360 set_dv_changed (var->dv, true);
6362 slot = htab_find_slot_with_hash (changed_variables,
6363 var->dv,
6364 hash, INSERT);
6366 if (*slot)
6368 variable old_var = (variable) *slot;
6369 gcc_assert (old_var->in_changed_variables);
6370 old_var->in_changed_variables = false;
6371 old_cur_loc_changed = old_var->cur_loc_changed;
6372 variable_htab_free (*slot);
6374 if (set && var->n_var_parts == 0)
6376 variable empty_var;
6378 empty_var = (variable) pool_alloc (dv_pool (var->dv));
6379 empty_var->dv = var->dv;
6380 empty_var->refcount = 1;
6381 empty_var->n_var_parts = 0;
6382 empty_var->cur_loc_changed = true;
6383 empty_var->in_changed_variables = true;
6384 *slot = empty_var;
6385 goto drop_var;
6387 else
6389 var->refcount++;
6390 var->in_changed_variables = true;
6391 /* If within processing one uop a variable is deleted
6392 and then readded, we need to assume it has changed. */
6393 if (old_cur_loc_changed)
6394 var->cur_loc_changed = true;
6395 *slot = var;
6398 else
6400 gcc_assert (set);
6401 if (var->n_var_parts == 0)
6403 void **slot;
6405 drop_var:
6406 slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
6407 if (slot)
6409 if (shared_hash_shared (set->vars))
6410 slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
6411 NO_INSERT);
6412 htab_clear_slot (shared_hash_htab (set->vars), slot);
6418 /* Look for the index in VAR->var_part corresponding to OFFSET.
6419 Return -1 if not found. If INSERTION_POINT is non-NULL, the
6420 referenced int will be set to the index that the part has or should
6421 have, if it should be inserted. */
6423 static inline int
6424 find_variable_location_part (variable var, HOST_WIDE_INT offset,
6425 int *insertion_point)
6427 int pos, low, high;
6429 /* Find the location part. */
6430 low = 0;
6431 high = var->n_var_parts;
6432 while (low != high)
6434 pos = (low + high) / 2;
6435 if (var->var_part[pos].offset < offset)
6436 low = pos + 1;
6437 else
6438 high = pos;
6440 pos = low;
6442 if (insertion_point)
6443 *insertion_point = pos;
6445 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
6446 return pos;
6448 return -1;
6451 static void **
6452 set_slot_part (dataflow_set *set, rtx loc, void **slot,
6453 decl_or_value dv, HOST_WIDE_INT offset,
6454 enum var_init_status initialized, rtx set_src)
6456 int pos;
6457 location_chain node, next;
6458 location_chain *nextp;
6459 variable var;
6460 bool onepart = dv_onepart_p (dv);
6462 gcc_assert (offset == 0 || !onepart);
6463 gcc_assert (loc != dv_as_opaque (dv));
6465 var = (variable) *slot;
6467 if (! flag_var_tracking_uninit)
6468 initialized = VAR_INIT_STATUS_INITIALIZED;
6470 if (!var)
6472 /* Create new variable information. */
6473 var = (variable) pool_alloc (dv_pool (dv));
6474 var->dv = dv;
6475 var->refcount = 1;
6476 var->n_var_parts = 1;
6477 var->cur_loc_changed = false;
6478 var->in_changed_variables = false;
6479 var->var_part[0].offset = offset;
6480 var->var_part[0].loc_chain = NULL;
6481 var->var_part[0].cur_loc = NULL;
6482 *slot = var;
6483 pos = 0;
6484 nextp = &var->var_part[0].loc_chain;
6486 else if (onepart)
6488 int r = -1, c = 0;
6490 gcc_assert (dv_as_opaque (var->dv) == dv_as_opaque (dv));
6492 pos = 0;
6494 if (GET_CODE (loc) == VALUE)
6496 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6497 nextp = &node->next)
6498 if (GET_CODE (node->loc) == VALUE)
6500 if (node->loc == loc)
6502 r = 0;
6503 break;
6505 if (canon_value_cmp (node->loc, loc))
6506 c++;
6507 else
6509 r = 1;
6510 break;
6513 else if (REG_P (node->loc) || MEM_P (node->loc))
6514 c++;
6515 else
6517 r = 1;
6518 break;
6521 else if (REG_P (loc))
6523 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6524 nextp = &node->next)
6525 if (REG_P (node->loc))
6527 if (REGNO (node->loc) < REGNO (loc))
6528 c++;
6529 else
6531 if (REGNO (node->loc) == REGNO (loc))
6532 r = 0;
6533 else
6534 r = 1;
6535 break;
6538 else
6540 r = 1;
6541 break;
6544 else if (MEM_P (loc))
6546 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6547 nextp = &node->next)
6548 if (REG_P (node->loc))
6549 c++;
6550 else if (MEM_P (node->loc))
6552 if ((r = loc_cmp (XEXP (node->loc, 0), XEXP (loc, 0))) >= 0)
6553 break;
6554 else
6555 c++;
6557 else
6559 r = 1;
6560 break;
6563 else
6564 for (nextp = &var->var_part[0].loc_chain; (node = *nextp);
6565 nextp = &node->next)
6566 if ((r = loc_cmp (node->loc, loc)) >= 0)
6567 break;
6568 else
6569 c++;
6571 if (r == 0)
6572 return slot;
6574 if (shared_var_p (var, set->vars))
6576 slot = unshare_variable (set, slot, var, initialized);
6577 var = (variable)*slot;
6578 for (nextp = &var->var_part[0].loc_chain; c;
6579 nextp = &(*nextp)->next)
6580 c--;
6581 gcc_assert ((!node && !*nextp) || node->loc == (*nextp)->loc);
6584 else
6586 int inspos = 0;
6588 gcc_assert (dv_as_decl (var->dv) == dv_as_decl (dv));
6590 pos = find_variable_location_part (var, offset, &inspos);
6592 if (pos >= 0)
6594 node = var->var_part[pos].loc_chain;
6596 if (node
6597 && ((REG_P (node->loc) && REG_P (loc)
6598 && REGNO (node->loc) == REGNO (loc))
6599 || rtx_equal_p (node->loc, loc)))
6601 /* LOC is in the beginning of the chain so we have nothing
6602 to do. */
6603 if (node->init < initialized)
6604 node->init = initialized;
6605 if (set_src != NULL)
6606 node->set_src = set_src;
6608 return slot;
6610 else
6612 /* We have to make a copy of a shared variable. */
6613 if (shared_var_p (var, set->vars))
6615 slot = unshare_variable (set, slot, var, initialized);
6616 var = (variable)*slot;
6620 else
6622 /* We have not found the location part, new one will be created. */
6624 /* We have to make a copy of the shared variable. */
6625 if (shared_var_p (var, set->vars))
6627 slot = unshare_variable (set, slot, var, initialized);
6628 var = (variable)*slot;
6631 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
6632 thus there are at most MAX_VAR_PARTS different offsets. */
6633 gcc_assert (var->n_var_parts < MAX_VAR_PARTS
6634 && (!var->n_var_parts || !dv_onepart_p (var->dv)));
6636 /* We have to move the elements of array starting at index
6637 inspos to the next position. */
6638 for (pos = var->n_var_parts; pos > inspos; pos--)
6639 var->var_part[pos] = var->var_part[pos - 1];
6641 var->n_var_parts++;
6642 var->var_part[pos].offset = offset;
6643 var->var_part[pos].loc_chain = NULL;
6644 var->var_part[pos].cur_loc = NULL;
6647 /* Delete the location from the list. */
6648 nextp = &var->var_part[pos].loc_chain;
6649 for (node = var->var_part[pos].loc_chain; node; node = next)
6651 next = node->next;
6652 if ((REG_P (node->loc) && REG_P (loc)
6653 && REGNO (node->loc) == REGNO (loc))
6654 || rtx_equal_p (node->loc, loc))
6656 /* Save these values, to assign to the new node, before
6657 deleting this one. */
6658 if (node->init > initialized)
6659 initialized = node->init;
6660 if (node->set_src != NULL && set_src == NULL)
6661 set_src = node->set_src;
6662 if (var->var_part[pos].cur_loc == node->loc)
6664 var->var_part[pos].cur_loc = NULL;
6665 var->cur_loc_changed = true;
6667 pool_free (loc_chain_pool, node);
6668 *nextp = next;
6669 break;
6671 else
6672 nextp = &node->next;
6675 nextp = &var->var_part[pos].loc_chain;
6678 /* Add the location to the beginning. */
6679 node = (location_chain) pool_alloc (loc_chain_pool);
6680 node->loc = loc;
6681 node->init = initialized;
6682 node->set_src = set_src;
6683 node->next = *nextp;
6684 *nextp = node;
6686 if (onepart && emit_notes)
6687 add_value_chains (var->dv, loc);
6689 /* If no location was emitted do so. */
6690 if (var->var_part[pos].cur_loc == NULL)
6691 variable_was_changed (var, set);
6693 return slot;
6696 /* Set the part of variable's location in the dataflow set SET. The
6697 variable part is specified by variable's declaration in DV and
6698 offset OFFSET and the part's location by LOC. IOPT should be
6699 NO_INSERT if the variable is known to be in SET already and the
6700 variable hash table must not be resized, and INSERT otherwise. */
6702 static void
6703 set_variable_part (dataflow_set *set, rtx loc,
6704 decl_or_value dv, HOST_WIDE_INT offset,
6705 enum var_init_status initialized, rtx set_src,
6706 enum insert_option iopt)
6708 void **slot;
6710 if (iopt == NO_INSERT)
6711 slot = shared_hash_find_slot_noinsert (set->vars, dv);
6712 else
6714 slot = shared_hash_find_slot (set->vars, dv);
6715 if (!slot)
6716 slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt);
6718 slot = set_slot_part (set, loc, slot, dv, offset, initialized, set_src);
6721 /* Remove all recorded register locations for the given variable part
6722 from dataflow set SET, except for those that are identical to loc.
6723 The variable part is specified by variable's declaration or value
6724 DV and offset OFFSET. */
6726 static void **
6727 clobber_slot_part (dataflow_set *set, rtx loc, void **slot,
6728 HOST_WIDE_INT offset, rtx set_src)
6730 variable var = (variable) *slot;
6731 int pos = find_variable_location_part (var, offset, NULL);
6733 if (pos >= 0)
6735 location_chain node, next;
6737 /* Remove the register locations from the dataflow set. */
6738 next = var->var_part[pos].loc_chain;
6739 for (node = next; node; node = next)
6741 next = node->next;
6742 if (node->loc != loc
6743 && (!flag_var_tracking_uninit
6744 || !set_src
6745 || MEM_P (set_src)
6746 || !rtx_equal_p (set_src, node->set_src)))
6748 if (REG_P (node->loc))
6750 attrs anode, anext;
6751 attrs *anextp;
6753 /* Remove the variable part from the register's
6754 list, but preserve any other variable parts
6755 that might be regarded as live in that same
6756 register. */
6757 anextp = &set->regs[REGNO (node->loc)];
6758 for (anode = *anextp; anode; anode = anext)
6760 anext = anode->next;
6761 if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
6762 && anode->offset == offset)
6764 pool_free (attrs_pool, anode);
6765 *anextp = anext;
6767 else
6768 anextp = &anode->next;
6772 slot = delete_slot_part (set, node->loc, slot, offset);
6777 return slot;
6780 /* Remove all recorded register locations for the given variable part
6781 from dataflow set SET, except for those that are identical to loc.
6782 The variable part is specified by variable's declaration or value
6783 DV and offset OFFSET. */
6785 static void
6786 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6787 HOST_WIDE_INT offset, rtx set_src)
6789 void **slot;
6791 if (!dv_as_opaque (dv)
6792 || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
6793 return;
6795 slot = shared_hash_find_slot_noinsert (set->vars, dv);
6796 if (!slot)
6797 return;
6799 slot = clobber_slot_part (set, loc, slot, offset, set_src);
6802 /* Delete the part of variable's location from dataflow set SET. The
6803 variable part is specified by its SET->vars slot SLOT and offset
6804 OFFSET and the part's location by LOC. */
6806 static void **
6807 delete_slot_part (dataflow_set *set, rtx loc, void **slot,
6808 HOST_WIDE_INT offset)
6810 variable var = (variable) *slot;
6811 int pos = find_variable_location_part (var, offset, NULL);
6813 if (pos >= 0)
6815 location_chain node, next;
6816 location_chain *nextp;
6817 bool changed;
6819 if (shared_var_p (var, set->vars))
6821 /* If the variable contains the location part we have to
6822 make a copy of the variable. */
6823 for (node = var->var_part[pos].loc_chain; node;
6824 node = node->next)
6826 if ((REG_P (node->loc) && REG_P (loc)
6827 && REGNO (node->loc) == REGNO (loc))
6828 || rtx_equal_p (node->loc, loc))
6830 slot = unshare_variable (set, slot, var,
6831 VAR_INIT_STATUS_UNKNOWN);
6832 var = (variable)*slot;
6833 break;
6838 /* Delete the location part. */
6839 changed = false;
6840 nextp = &var->var_part[pos].loc_chain;
6841 for (node = *nextp; node; node = next)
6843 next = node->next;
6844 if ((REG_P (node->loc) && REG_P (loc)
6845 && REGNO (node->loc) == REGNO (loc))
6846 || rtx_equal_p (node->loc, loc))
6848 if (emit_notes && pos == 0 && dv_onepart_p (var->dv))
6849 remove_value_chains (var->dv, node->loc);
6850 /* If we have deleted the location which was last emitted
6851 we have to emit new location so add the variable to set
6852 of changed variables. */
6853 if (var->var_part[pos].cur_loc == node->loc)
6855 changed = true;
6856 var->var_part[pos].cur_loc = NULL;
6857 var->cur_loc_changed = true;
6859 pool_free (loc_chain_pool, node);
6860 *nextp = next;
6861 break;
6863 else
6864 nextp = &node->next;
6867 if (var->var_part[pos].loc_chain == NULL)
6869 changed = true;
6870 var->n_var_parts--;
6871 if (emit_notes)
6872 var->cur_loc_changed = true;
6873 while (pos < var->n_var_parts)
6875 var->var_part[pos] = var->var_part[pos + 1];
6876 pos++;
6879 if (changed)
6880 variable_was_changed (var, set);
6883 return slot;
6886 /* Delete the part of variable's location from dataflow set SET. The
6887 variable part is specified by variable's declaration or value DV
6888 and offset OFFSET and the part's location by LOC. */
6890 static void
6891 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
6892 HOST_WIDE_INT offset)
6894 void **slot = shared_hash_find_slot_noinsert (set->vars, dv);
6895 if (!slot)
6896 return;
6898 slot = delete_slot_part (set, loc, slot, offset);
6901 /* Structure for passing some other parameters to function
6902 vt_expand_loc_callback. */
6903 struct expand_loc_callback_data
6905 /* The variables and values active at this point. */
6906 htab_t vars;
6908 /* True in vt_expand_loc_dummy calls, no rtl should be allocated.
6909 Non-NULL should be returned if vt_expand_loc would return
6910 non-NULL in that case, NULL otherwise. cur_loc_changed should be
6911 computed and cur_loc recomputed when possible (but just once
6912 per emit_notes_for_changes call). */
6913 bool dummy;
6915 /* True if expansion of subexpressions had to recompute some
6916 VALUE/DEBUG_EXPR_DECL's cur_loc or used a VALUE/DEBUG_EXPR_DECL
6917 whose cur_loc has been already recomputed during current
6918 emit_notes_for_changes call. */
6919 bool cur_loc_changed;
6922 /* Callback for cselib_expand_value, that looks for expressions
6923 holding the value in the var-tracking hash tables. Return X for
6924 standard processing, anything else is to be used as-is. */
6926 static rtx
6927 vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
6929 struct expand_loc_callback_data *elcd
6930 = (struct expand_loc_callback_data *) data;
6931 bool dummy = elcd->dummy;
6932 bool cur_loc_changed = elcd->cur_loc_changed;
6933 decl_or_value dv;
6934 variable var;
6935 location_chain loc;
6936 rtx result, subreg, xret;
6938 switch (GET_CODE (x))
6940 case SUBREG:
6941 if (dummy)
6943 if (cselib_dummy_expand_value_rtx_cb (SUBREG_REG (x), regs,
6944 max_depth - 1,
6945 vt_expand_loc_callback, data))
6946 return pc_rtx;
6947 else
6948 return NULL;
6951 subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
6952 max_depth - 1,
6953 vt_expand_loc_callback, data);
6955 if (!subreg)
6956 return NULL;
6958 result = simplify_gen_subreg (GET_MODE (x), subreg,
6959 GET_MODE (SUBREG_REG (x)),
6960 SUBREG_BYTE (x));
6962 /* Invalid SUBREGs are ok in debug info. ??? We could try
6963 alternate expansions for the VALUE as well. */
6964 if (!result)
6965 result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
6967 return result;
6969 case DEBUG_EXPR:
6970 dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
6971 xret = NULL;
6972 break;
6974 case VALUE:
6975 dv = dv_from_value (x);
6976 xret = x;
6977 break;
6979 default:
6980 return x;
6983 if (VALUE_RECURSED_INTO (x))
6984 return NULL;
6986 var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv));
6988 if (!var)
6990 if (dummy && dv_changed_p (dv))
6991 elcd->cur_loc_changed = true;
6992 return xret;
6995 if (var->n_var_parts == 0)
6997 if (dummy)
6998 elcd->cur_loc_changed = true;
6999 return xret;
7002 gcc_assert (var->n_var_parts == 1);
7004 VALUE_RECURSED_INTO (x) = true;
7005 result = NULL;
7007 if (var->var_part[0].cur_loc)
7009 if (dummy)
7011 if (cselib_dummy_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
7012 max_depth,
7013 vt_expand_loc_callback, data))
7014 result = pc_rtx;
7016 else
7017 result = cselib_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
7018 max_depth,
7019 vt_expand_loc_callback, data);
7020 if (result)
7021 set_dv_changed (dv, false);
7023 if (!result && dv_changed_p (dv))
7025 set_dv_changed (dv, false);
7026 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
7027 if (loc->loc == var->var_part[0].cur_loc)
7028 continue;
7029 else if (dummy)
7031 elcd->cur_loc_changed = cur_loc_changed;
7032 if (cselib_dummy_expand_value_rtx_cb (loc->loc, regs, max_depth,
7033 vt_expand_loc_callback,
7034 data))
7036 result = pc_rtx;
7037 break;
7040 else
7042 result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
7043 vt_expand_loc_callback, data);
7044 if (result)
7045 break;
7047 if (dummy && (result || var->var_part[0].cur_loc))
7048 var->cur_loc_changed = true;
7049 var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
7051 if (dummy)
7053 if (var->cur_loc_changed)
7054 elcd->cur_loc_changed = true;
7055 else if (!result && var->var_part[0].cur_loc == NULL_RTX)
7056 elcd->cur_loc_changed = cur_loc_changed;
7059 VALUE_RECURSED_INTO (x) = false;
7060 if (result)
7061 return result;
7062 else
7063 return xret;
7066 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
7067 tables. */
7069 static rtx
7070 vt_expand_loc (rtx loc, htab_t vars)
7072 struct expand_loc_callback_data data;
7074 if (!MAY_HAVE_DEBUG_INSNS)
7075 return loc;
7077 data.vars = vars;
7078 data.dummy = false;
7079 data.cur_loc_changed = false;
7080 loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
7081 vt_expand_loc_callback, &data);
7083 if (loc && MEM_P (loc))
7084 loc = targetm.delegitimize_address (loc);
7085 return loc;
7088 /* Like vt_expand_loc, but only return true/false (whether vt_expand_loc
7089 would succeed or not, without actually allocating new rtxes. */
7091 static bool
7092 vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
7094 struct expand_loc_callback_data data;
7095 bool ret;
7097 gcc_assert (MAY_HAVE_DEBUG_INSNS);
7098 data.vars = vars;
7099 data.dummy = true;
7100 data.cur_loc_changed = false;
7101 ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, 5,
7102 vt_expand_loc_callback, &data);
7103 *pcur_loc_changed = data.cur_loc_changed;
7104 return ret;
7107 #ifdef ENABLE_RTL_CHECKING
7108 /* Used to verify that cur_loc_changed updating is safe. */
7109 static struct pointer_map_t *emitted_notes;
7110 #endif
7112 /* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
7113 additional parameters: WHERE specifies whether the note shall be emitted
7114 before or after instruction INSN. */
7116 static int
7117 emit_note_insn_var_location (void **varp, void *data)
7119 variable var = (variable) *varp;
7120 rtx insn = ((emit_note_data *)data)->insn;
7121 enum emit_note_where where = ((emit_note_data *)data)->where;
7122 htab_t vars = ((emit_note_data *)data)->vars;
7123 rtx note, note_vl;
7124 int i, j, n_var_parts;
7125 bool complete;
7126 enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
7127 HOST_WIDE_INT last_limit;
7128 tree type_size_unit;
7129 HOST_WIDE_INT offsets[MAX_VAR_PARTS];
7130 rtx loc[MAX_VAR_PARTS];
7131 tree decl;
7132 location_chain lc;
7134 if (dv_is_value_p (var->dv))
7135 goto value_or_debug_decl;
7137 decl = dv_as_decl (var->dv);
7139 if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
7140 goto value_or_debug_decl;
7142 complete = true;
7143 last_limit = 0;
7144 n_var_parts = 0;
7145 if (!MAY_HAVE_DEBUG_INSNS)
7147 for (i = 0; i < var->n_var_parts; i++)
7148 if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
7150 var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
7151 var->cur_loc_changed = true;
7153 if (var->n_var_parts == 0)
7154 var->cur_loc_changed = true;
7156 #ifndef ENABLE_RTL_CHECKING
7157 if (!var->cur_loc_changed)
7158 goto clear;
7159 #endif
7160 for (i = 0; i < var->n_var_parts; i++)
7162 enum machine_mode mode, wider_mode;
7163 rtx loc2;
7165 if (last_limit < var->var_part[i].offset)
7167 complete = false;
7168 break;
7170 else if (last_limit > var->var_part[i].offset)
7171 continue;
7172 offsets[n_var_parts] = var->var_part[i].offset;
7173 if (!var->var_part[i].cur_loc)
7175 complete = false;
7176 continue;
7178 loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars);
7179 if (!loc2)
7181 complete = false;
7182 continue;
7184 loc[n_var_parts] = loc2;
7185 mode = GET_MODE (var->var_part[i].cur_loc);
7186 if (mode == VOIDmode && dv_onepart_p (var->dv))
7187 mode = DECL_MODE (decl);
7188 for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
7189 if (var->var_part[i].cur_loc == lc->loc)
7191 initialized = lc->init;
7192 break;
7194 gcc_assert (lc);
7195 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
7197 /* Attempt to merge adjacent registers or memory. */
7198 wider_mode = GET_MODE_WIDER_MODE (mode);
7199 for (j = i + 1; j < var->n_var_parts; j++)
7200 if (last_limit <= var->var_part[j].offset)
7201 break;
7202 if (j < var->n_var_parts
7203 && wider_mode != VOIDmode
7204 && var->var_part[j].cur_loc
7205 && mode == GET_MODE (var->var_part[j].cur_loc)
7206 && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
7207 && last_limit == var->var_part[j].offset
7208 && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
7209 && GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
7211 rtx new_loc = NULL;
7213 if (REG_P (loc[n_var_parts])
7214 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
7215 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
7216 && end_hard_regno (mode, REGNO (loc[n_var_parts]))
7217 == REGNO (loc2))
7219 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
7220 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
7221 mode, 0);
7222 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
7223 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
7224 if (new_loc)
7226 if (!REG_P (new_loc)
7227 || REGNO (new_loc) != REGNO (loc[n_var_parts]))
7228 new_loc = NULL;
7229 else
7230 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
7233 else if (MEM_P (loc[n_var_parts])
7234 && GET_CODE (XEXP (loc2, 0)) == PLUS
7235 && REG_P (XEXP (XEXP (loc2, 0), 0))
7236 && CONST_INT_P (XEXP (XEXP (loc2, 0), 1)))
7238 if ((REG_P (XEXP (loc[n_var_parts], 0))
7239 && rtx_equal_p (XEXP (loc[n_var_parts], 0),
7240 XEXP (XEXP (loc2, 0), 0))
7241 && INTVAL (XEXP (XEXP (loc2, 0), 1))
7242 == GET_MODE_SIZE (mode))
7243 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
7244 && CONST_INT_P (XEXP (XEXP (loc[n_var_parts], 0), 1))
7245 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
7246 XEXP (XEXP (loc2, 0), 0))
7247 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
7248 + GET_MODE_SIZE (mode)
7249 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
7250 new_loc = adjust_address_nv (loc[n_var_parts],
7251 wider_mode, 0);
7254 if (new_loc)
7256 loc[n_var_parts] = new_loc;
7257 mode = wider_mode;
7258 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
7259 i = j;
7262 ++n_var_parts;
7264 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (decl));
7265 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
7266 complete = false;
7268 if (! flag_var_tracking_uninit)
7269 initialized = VAR_INIT_STATUS_INITIALIZED;
7271 note_vl = NULL_RTX;
7272 if (!complete)
7273 note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX,
7274 (int) initialized);
7275 else if (n_var_parts == 1)
7277 rtx expr_list;
7279 if (offsets[0] || GET_CODE (loc[0]) == PARALLEL)
7280 expr_list = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
7281 else
7282 expr_list = loc[0];
7284 note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list,
7285 (int) initialized);
7287 else if (n_var_parts)
7289 rtx parallel;
7291 for (i = 0; i < n_var_parts; i++)
7292 loc[i]
7293 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
7295 parallel = gen_rtx_PARALLEL (VOIDmode,
7296 gen_rtvec_v (n_var_parts, loc));
7297 note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl,
7298 parallel, (int) initialized);
7301 #ifdef ENABLE_RTL_CHECKING
7302 if (note_vl)
7304 void **note_slot = pointer_map_insert (emitted_notes, decl);
7305 rtx pnote = (rtx) *note_slot;
7306 if (!var->cur_loc_changed && (pnote || PAT_VAR_LOCATION_LOC (note_vl)))
7308 gcc_assert (pnote);
7309 gcc_assert (rtx_equal_p (PAT_VAR_LOCATION_LOC (pnote),
7310 PAT_VAR_LOCATION_LOC (note_vl)));
7312 *note_slot = (void *) note_vl;
7314 if (!var->cur_loc_changed)
7315 goto clear;
7316 #endif
7318 if (where != EMIT_NOTE_BEFORE_INSN)
7320 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
7321 if (where == EMIT_NOTE_AFTER_CALL_INSN)
7322 NOTE_DURING_CALL_P (note) = true;
7324 else
7325 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
7326 NOTE_VAR_LOCATION (note) = note_vl;
7328 clear:
7329 set_dv_changed (var->dv, false);
7330 var->cur_loc_changed = false;
7331 gcc_assert (var->in_changed_variables);
7332 var->in_changed_variables = false;
7333 htab_clear_slot (changed_variables, varp);
7335 /* Continue traversing the hash table. */
7336 return 1;
7338 value_or_debug_decl:
7339 if (dv_changed_p (var->dv) && var->n_var_parts)
7341 location_chain lc;
7342 bool cur_loc_changed;
7344 if (var->var_part[0].cur_loc
7345 && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars,
7346 &cur_loc_changed))
7347 goto clear;
7348 for (lc = var->var_part[0].loc_chain; lc; lc = lc->next)
7349 if (lc->loc != var->var_part[0].cur_loc
7350 && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
7351 break;
7352 var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX;
7354 goto clear;
7357 DEF_VEC_P (variable);
7358 DEF_VEC_ALLOC_P (variable, heap);
7360 /* Stack of variable_def pointers that need processing with
7361 check_changed_vars_2. */
7363 static VEC (variable, heap) *changed_variables_stack;
7365 /* VALUEs with no variables that need set_dv_changed (val, false)
7366 called before check_changed_vars_3. */
7368 static VEC (rtx, heap) *changed_values_stack;
7370 /* Helper function for check_changed_vars_1 and check_changed_vars_2. */
7372 static void
7373 check_changed_vars_0 (decl_or_value dv, htab_t htab)
7375 value_chain vc
7376 = (value_chain) htab_find_with_hash (value_chains, dv, dv_htab_hash (dv));
7378 if (vc == NULL)
7379 return;
7380 for (vc = vc->next; vc; vc = vc->next)
7381 if (!dv_changed_p (vc->dv))
7383 variable vcvar
7384 = (variable) htab_find_with_hash (htab, vc->dv,
7385 dv_htab_hash (vc->dv));
7386 if (vcvar)
7388 set_dv_changed (vc->dv, true);
7389 VEC_safe_push (variable, heap, changed_variables_stack, vcvar);
7391 else if (dv_is_value_p (vc->dv))
7393 set_dv_changed (vc->dv, true);
7394 VEC_safe_push (rtx, heap, changed_values_stack,
7395 dv_as_value (vc->dv));
7396 check_changed_vars_0 (vc->dv, htab);
7401 /* Populate changed_variables_stack with variable_def pointers
7402 that need variable_was_changed called on them. */
7404 static int
7405 check_changed_vars_1 (void **slot, void *data)
7407 variable var = (variable) *slot;
7408 htab_t htab = (htab_t) data;
7410 if (dv_is_value_p (var->dv)
7411 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7412 check_changed_vars_0 (var->dv, htab);
7413 return 1;
7416 /* Add VAR to changed_variables and also for VALUEs add recursively
7417 all DVs that aren't in changed_variables yet but reference the
7418 VALUE from its loc_chain. */
7420 static void
7421 check_changed_vars_2 (variable var, htab_t htab)
7423 variable_was_changed (var, NULL);
7424 if (dv_is_value_p (var->dv)
7425 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7426 check_changed_vars_0 (var->dv, htab);
7429 /* For each changed decl (except DEBUG_EXPR_DECLs) recompute
7430 cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs
7431 it needs and are also in changed variables) and track whether
7432 cur_loc (or anything it uses to compute location) had to change
7433 during the current emit_notes_for_changes call. */
7435 static int
7436 check_changed_vars_3 (void **slot, void *data)
7438 variable var = (variable) *slot;
7439 htab_t vars = (htab_t) data;
7440 int i;
7441 location_chain lc;
7442 bool cur_loc_changed;
7444 if (dv_is_value_p (var->dv)
7445 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
7446 return 1;
7448 for (i = 0; i < var->n_var_parts; i++)
7450 if (var->var_part[i].cur_loc
7451 && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars,
7452 &cur_loc_changed))
7454 if (cur_loc_changed)
7455 var->cur_loc_changed = true;
7456 continue;
7458 for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
7459 if (lc->loc != var->var_part[i].cur_loc
7460 && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
7461 break;
7462 if (lc || var->var_part[i].cur_loc)
7463 var->cur_loc_changed = true;
7464 var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX;
7466 if (var->n_var_parts == 0)
7467 var->cur_loc_changed = true;
7468 return 1;
7471 /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
7472 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
7473 shall be emitted before of after instruction INSN. */
7475 static void
7476 emit_notes_for_changes (rtx insn, enum emit_note_where where,
7477 shared_hash vars)
7479 emit_note_data data;
7480 htab_t htab = shared_hash_htab (vars);
7482 if (!htab_elements (changed_variables))
7483 return;
7485 if (MAY_HAVE_DEBUG_INSNS)
7487 /* Unfortunately this has to be done in two steps, because
7488 we can't traverse a hashtab into which we are inserting
7489 through variable_was_changed. */
7490 htab_traverse (changed_variables, check_changed_vars_1, htab);
7491 while (VEC_length (variable, changed_variables_stack) > 0)
7492 check_changed_vars_2 (VEC_pop (variable, changed_variables_stack),
7493 htab);
7494 while (VEC_length (rtx, changed_values_stack) > 0)
7495 set_dv_changed (dv_from_value (VEC_pop (rtx, changed_values_stack)),
7496 false);
7497 htab_traverse (changed_variables, check_changed_vars_3, htab);
7500 data.insn = insn;
7501 data.where = where;
7502 data.vars = htab;
7504 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
7507 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
7508 same variable in hash table DATA or is not there at all. */
7510 static int
7511 emit_notes_for_differences_1 (void **slot, void *data)
7513 htab_t new_vars = (htab_t) data;
7514 variable old_var, new_var;
7516 old_var = (variable) *slot;
7517 new_var = (variable) htab_find_with_hash (new_vars, old_var->dv,
7518 dv_htab_hash (old_var->dv));
7520 if (!new_var)
7522 /* Variable has disappeared. */
7523 variable empty_var;
7525 empty_var = (variable) pool_alloc (dv_pool (old_var->dv));
7526 empty_var->dv = old_var->dv;
7527 empty_var->refcount = 0;
7528 empty_var->n_var_parts = 0;
7529 empty_var->cur_loc_changed = false;
7530 empty_var->in_changed_variables = false;
7531 if (dv_onepart_p (old_var->dv))
7533 location_chain lc;
7535 gcc_assert (old_var->n_var_parts == 1);
7536 for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next)
7537 remove_value_chains (old_var->dv, lc->loc);
7539 variable_was_changed (empty_var, NULL);
7540 /* Continue traversing the hash table. */
7541 return 1;
7543 if (variable_different_p (old_var, new_var))
7545 if (dv_onepart_p (old_var->dv))
7547 location_chain lc1, lc2;
7549 gcc_assert (old_var->n_var_parts == 1
7550 && new_var->n_var_parts == 1);
7551 lc1 = old_var->var_part[0].loc_chain;
7552 lc2 = new_var->var_part[0].loc_chain;
7553 while (lc1
7554 && lc2
7555 && ((REG_P (lc1->loc) && REG_P (lc2->loc))
7556 || rtx_equal_p (lc1->loc, lc2->loc)))
7558 lc1 = lc1->next;
7559 lc2 = lc2->next;
7561 for (; lc2; lc2 = lc2->next)
7562 add_value_chains (old_var->dv, lc2->loc);
7563 for (; lc1; lc1 = lc1->next)
7564 remove_value_chains (old_var->dv, lc1->loc);
7566 variable_was_changed (new_var, NULL);
7568 /* Update cur_loc. */
7569 if (old_var != new_var)
7571 int i;
7572 for (i = 0; i < new_var->n_var_parts; i++)
7574 new_var->var_part[i].cur_loc = NULL;
7575 if (old_var->n_var_parts != new_var->n_var_parts
7576 || old_var->var_part[i].offset != new_var->var_part[i].offset)
7577 new_var->cur_loc_changed = true;
7578 else if (old_var->var_part[i].cur_loc != NULL)
7580 location_chain lc;
7581 rtx cur_loc = old_var->var_part[i].cur_loc;
7583 for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next)
7584 if (lc->loc == cur_loc
7585 || rtx_equal_p (cur_loc, lc->loc))
7587 new_var->var_part[i].cur_loc = lc->loc;
7588 break;
7590 if (lc == NULL)
7591 new_var->cur_loc_changed = true;
7596 /* Continue traversing the hash table. */
7597 return 1;
7600 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash
7601 table DATA. */
7603 static int
7604 emit_notes_for_differences_2 (void **slot, void *data)
7606 htab_t old_vars = (htab_t) data;
7607 variable old_var, new_var;
7609 new_var = (variable) *slot;
7610 old_var = (variable) htab_find_with_hash (old_vars, new_var->dv,
7611 dv_htab_hash (new_var->dv));
7612 if (!old_var)
7614 int i;
7615 /* Variable has appeared. */
7616 if (dv_onepart_p (new_var->dv))
7618 location_chain lc;
7620 gcc_assert (new_var->n_var_parts == 1);
7621 for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next)
7622 add_value_chains (new_var->dv, lc->loc);
7624 for (i = 0; i < new_var->n_var_parts; i++)
7625 new_var->var_part[i].cur_loc = NULL;
7626 variable_was_changed (new_var, NULL);
7629 /* Continue traversing the hash table. */
7630 return 1;
7633 /* Emit notes before INSN for differences between dataflow sets OLD_SET and
7634 NEW_SET. */
7636 static void
7637 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
7638 dataflow_set *new_set)
7640 htab_traverse (shared_hash_htab (old_set->vars),
7641 emit_notes_for_differences_1,
7642 shared_hash_htab (new_set->vars));
7643 htab_traverse (shared_hash_htab (new_set->vars),
7644 emit_notes_for_differences_2,
7645 shared_hash_htab (old_set->vars));
7646 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
7649 /* Emit the notes for changes of location parts in the basic block BB. */
7651 static void
7652 emit_notes_in_bb (basic_block bb, dataflow_set *set)
7654 unsigned int i;
7655 micro_operation *mo;
7657 dataflow_set_clear (set);
7658 dataflow_set_copy (set, &VTI (bb)->in);
7660 for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
7662 rtx insn = mo->insn;
7664 switch (mo->type)
7666 case MO_CALL:
7667 dataflow_set_clear_at_call (set);
7668 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
7669 break;
7671 case MO_USE:
7673 rtx loc = mo->u.loc;
7675 if (REG_P (loc))
7676 var_reg_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
7677 else
7678 var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
7680 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7682 break;
7684 case MO_VAL_LOC:
7686 rtx loc = mo->u.loc;
7687 rtx val, vloc;
7688 tree var;
7690 if (GET_CODE (loc) == CONCAT)
7692 val = XEXP (loc, 0);
7693 vloc = XEXP (loc, 1);
7695 else
7697 val = NULL_RTX;
7698 vloc = loc;
7701 var = PAT_VAR_LOCATION_DECL (vloc);
7703 clobber_variable_part (set, NULL_RTX,
7704 dv_from_decl (var), 0, NULL_RTX);
7705 if (val)
7707 if (VAL_NEEDS_RESOLUTION (loc))
7708 val_resolve (set, val, PAT_VAR_LOCATION_LOC (vloc), insn);
7709 set_variable_part (set, val, dv_from_decl (var), 0,
7710 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
7711 INSERT);
7713 else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
7714 set_variable_part (set, PAT_VAR_LOCATION_LOC (vloc),
7715 dv_from_decl (var), 0,
7716 VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
7717 INSERT);
7719 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7721 break;
7723 case MO_VAL_USE:
7725 rtx loc = mo->u.loc;
7726 rtx val, vloc, uloc;
7728 vloc = uloc = XEXP (loc, 1);
7729 val = XEXP (loc, 0);
7731 if (GET_CODE (val) == CONCAT)
7733 uloc = XEXP (val, 1);
7734 val = XEXP (val, 0);
7737 if (VAL_NEEDS_RESOLUTION (loc))
7738 val_resolve (set, val, vloc, insn);
7739 else
7740 val_store (set, val, uloc, insn, false);
7742 if (VAL_HOLDS_TRACK_EXPR (loc))
7744 if (GET_CODE (uloc) == REG)
7745 var_reg_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
7746 NULL);
7747 else if (GET_CODE (uloc) == MEM)
7748 var_mem_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED,
7749 NULL);
7752 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars);
7754 break;
7756 case MO_VAL_SET:
7758 rtx loc = mo->u.loc;
7759 rtx val, vloc, uloc, reverse = NULL_RTX;
7761 vloc = loc;
7762 if (VAL_EXPR_HAS_REVERSE (loc))
7764 reverse = XEXP (loc, 1);
7765 vloc = XEXP (loc, 0);
7767 uloc = XEXP (vloc, 1);
7768 val = XEXP (vloc, 0);
7769 vloc = uloc;
7771 if (GET_CODE (val) == CONCAT)
7773 vloc = XEXP (val, 1);
7774 val = XEXP (val, 0);
7777 if (GET_CODE (vloc) == SET)
7779 rtx vsrc = SET_SRC (vloc);
7781 gcc_assert (val != vsrc);
7782 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc));
7784 vloc = SET_DEST (vloc);
7786 if (VAL_NEEDS_RESOLUTION (loc))
7787 val_resolve (set, val, vsrc, insn);
7789 else if (VAL_NEEDS_RESOLUTION (loc))
7791 gcc_assert (GET_CODE (uloc) == SET
7792 && GET_CODE (SET_SRC (uloc)) == REG);
7793 val_resolve (set, val, SET_SRC (uloc), insn);
7796 if (VAL_HOLDS_TRACK_EXPR (loc))
7798 if (VAL_EXPR_IS_CLOBBERED (loc))
7800 if (REG_P (uloc))
7801 var_reg_delete (set, uloc, true);
7802 else if (MEM_P (uloc))
7803 var_mem_delete (set, uloc, true);
7805 else
7807 bool copied_p = VAL_EXPR_IS_COPIED (loc);
7808 rtx set_src = NULL;
7809 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED;
7811 if (GET_CODE (uloc) == SET)
7813 set_src = SET_SRC (uloc);
7814 uloc = SET_DEST (uloc);
7817 if (copied_p)
7819 status = find_src_status (set, set_src);
7821 set_src = find_src_set_src (set, set_src);
7824 if (REG_P (uloc))
7825 var_reg_delete_and_set (set, uloc, !copied_p,
7826 status, set_src);
7827 else if (MEM_P (uloc))
7828 var_mem_delete_and_set (set, uloc, !copied_p,
7829 status, set_src);
7832 else if (REG_P (uloc))
7833 var_regno_delete (set, REGNO (uloc));
7835 val_store (set, val, vloc, insn, true);
7837 if (reverse)
7838 val_store (set, XEXP (reverse, 0), XEXP (reverse, 1),
7839 insn, false);
7841 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7842 set->vars);
7844 break;
7846 case MO_SET:
7848 rtx loc = mo->u.loc;
7849 rtx set_src = NULL;
7851 if (GET_CODE (loc) == SET)
7853 set_src = SET_SRC (loc);
7854 loc = SET_DEST (loc);
7857 if (REG_P (loc))
7858 var_reg_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
7859 set_src);
7860 else
7861 var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED,
7862 set_src);
7864 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7865 set->vars);
7867 break;
7869 case MO_COPY:
7871 rtx loc = mo->u.loc;
7872 enum var_init_status src_status;
7873 rtx set_src = NULL;
7875 if (GET_CODE (loc) == SET)
7877 set_src = SET_SRC (loc);
7878 loc = SET_DEST (loc);
7881 src_status = find_src_status (set, set_src);
7882 set_src = find_src_set_src (set, set_src);
7884 if (REG_P (loc))
7885 var_reg_delete_and_set (set, loc, false, src_status, set_src);
7886 else
7887 var_mem_delete_and_set (set, loc, false, src_status, set_src);
7889 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7890 set->vars);
7892 break;
7894 case MO_USE_NO_VAR:
7896 rtx loc = mo->u.loc;
7898 if (REG_P (loc))
7899 var_reg_delete (set, loc, false);
7900 else
7901 var_mem_delete (set, loc, false);
7903 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
7905 break;
7907 case MO_CLOBBER:
7909 rtx loc = mo->u.loc;
7911 if (REG_P (loc))
7912 var_reg_delete (set, loc, true);
7913 else
7914 var_mem_delete (set, loc, true);
7916 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN,
7917 set->vars);
7919 break;
7921 case MO_ADJUST:
7922 set->stack_adjust += mo->u.adjust;
7923 break;
7928 /* Emit notes for the whole function. */
7930 static void
7931 vt_emit_notes (void)
7933 basic_block bb;
7934 dataflow_set cur;
7936 #ifdef ENABLE_RTL_CHECKING
7937 emitted_notes = pointer_map_create ();
7938 #endif
7939 gcc_assert (!htab_elements (changed_variables));
7941 /* Free memory occupied by the out hash tables, as they aren't used
7942 anymore. */
7943 FOR_EACH_BB (bb)
7944 dataflow_set_clear (&VTI (bb)->out);
7946 /* Enable emitting notes by functions (mainly by set_variable_part and
7947 delete_variable_part). */
7948 emit_notes = true;
7950 if (MAY_HAVE_DEBUG_INSNS)
7952 unsigned int i;
7953 rtx val;
7955 for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
7956 add_cselib_value_chains (dv_from_value (val));
7957 changed_variables_stack = VEC_alloc (variable, heap, 40);
7958 changed_values_stack = VEC_alloc (rtx, heap, 40);
7961 dataflow_set_init (&cur);
7963 FOR_EACH_BB (bb)
7965 /* Emit the notes for changes of variable locations between two
7966 subsequent basic blocks. */
7967 emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
7969 /* Emit the notes for the changes in the basic block itself. */
7970 emit_notes_in_bb (bb, &cur);
7972 /* Free memory occupied by the in hash table, we won't need it
7973 again. */
7974 dataflow_set_clear (&VTI (bb)->in);
7976 #ifdef ENABLE_CHECKING
7977 htab_traverse (shared_hash_htab (cur.vars),
7978 emit_notes_for_differences_1,
7979 shared_hash_htab (empty_shared_hash));
7980 if (MAY_HAVE_DEBUG_INSNS)
7982 unsigned int i;
7983 rtx val;
7985 for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++)
7986 remove_cselib_value_chains (dv_from_value (val));
7987 gcc_assert (htab_elements (value_chains) == 0);
7989 #endif
7990 dataflow_set_destroy (&cur);
7992 if (MAY_HAVE_DEBUG_INSNS)
7994 VEC_free (variable, heap, changed_variables_stack);
7995 VEC_free (rtx, heap, changed_values_stack);
7998 #ifdef ENABLE_RTL_CHECKING
7999 pointer_map_destroy (emitted_notes);
8000 #endif
8001 emit_notes = false;
8004 /* If there is a declaration and offset associated with register/memory RTL
8005 assign declaration to *DECLP and offset to *OFFSETP, and return true. */
8007 static bool
8008 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
8010 if (REG_P (rtl))
8012 if (REG_ATTRS (rtl))
8014 *declp = REG_EXPR (rtl);
8015 *offsetp = REG_OFFSET (rtl);
8016 return true;
8019 else if (MEM_P (rtl))
8021 if (MEM_ATTRS (rtl))
8023 *declp = MEM_EXPR (rtl);
8024 *offsetp = INT_MEM_OFFSET (rtl);
8025 return true;
8028 return false;
8031 /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */
8033 static void
8034 vt_add_function_parameters (void)
8036 tree parm;
8038 for (parm = DECL_ARGUMENTS (current_function_decl);
8039 parm; parm = TREE_CHAIN (parm))
8041 rtx decl_rtl = DECL_RTL_IF_SET (parm);
8042 rtx incoming = DECL_INCOMING_RTL (parm);
8043 tree decl;
8044 enum machine_mode mode;
8045 HOST_WIDE_INT offset;
8046 dataflow_set *out;
8047 decl_or_value dv;
8049 if (TREE_CODE (parm) != PARM_DECL)
8050 continue;
8052 if (!DECL_NAME (parm))
8053 continue;
8055 if (!decl_rtl || !incoming)
8056 continue;
8058 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
8059 continue;
8061 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
8063 if (REG_P (incoming) || MEM_P (incoming))
8065 /* This means argument is passed by invisible reference. */
8066 offset = 0;
8067 decl = parm;
8068 incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
8070 else
8072 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
8073 continue;
8074 offset += byte_lowpart_offset (GET_MODE (incoming),
8075 GET_MODE (decl_rtl));
8079 if (!decl)
8080 continue;
8082 if (parm != decl)
8084 /* Assume that DECL_RTL was a pseudo that got spilled to
8085 memory. The spill slot sharing code will force the
8086 memory to reference spill_slot_decl (%sfp), so we don't
8087 match above. That's ok, the pseudo must have referenced
8088 the entire parameter, so just reset OFFSET. */
8089 gcc_assert (decl == get_spill_slot_decl (false));
8090 offset = 0;
8093 if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
8094 continue;
8096 out = &VTI (ENTRY_BLOCK_PTR)->out;
8098 dv = dv_from_decl (parm);
8100 if (target_for_debug_bind (parm)
8101 /* We can't deal with these right now, because this kind of
8102 variable is single-part. ??? We could handle parallels
8103 that describe multiple locations for the same single
8104 value, but ATM we don't. */
8105 && GET_CODE (incoming) != PARALLEL)
8107 cselib_val *val;
8109 /* ??? We shouldn't ever hit this, but it may happen because
8110 arguments passed by invisible reference aren't dealt with
8111 above: incoming-rtl will have Pmode rather than the
8112 expected mode for the type. */
8113 if (offset)
8114 continue;
8116 val = cselib_lookup (var_lowpart (mode, incoming), mode, true);
8118 /* ??? Float-typed values in memory are not handled by
8119 cselib. */
8120 if (val)
8122 preserve_value (val);
8123 set_variable_part (out, val->val_rtx, dv, offset,
8124 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
8125 dv = dv_from_value (val->val_rtx);
8129 if (REG_P (incoming))
8131 incoming = var_lowpart (mode, incoming);
8132 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
8133 attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
8134 incoming);
8135 set_variable_part (out, incoming, dv, offset,
8136 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
8138 else if (MEM_P (incoming))
8140 incoming = var_lowpart (mode, incoming);
8141 set_variable_part (out, incoming, dv, offset,
8142 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
8146 if (MAY_HAVE_DEBUG_INSNS)
8148 cselib_preserve_only_values ();
8149 cselib_reset_table (cselib_get_next_uid ());
8154 /* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */
8156 static bool
8157 fp_setter (rtx insn)
8159 rtx pat = PATTERN (insn);
8160 if (RTX_FRAME_RELATED_P (insn))
8162 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
8163 if (expr)
8164 pat = XEXP (expr, 0);
8166 if (GET_CODE (pat) == SET)
8167 return SET_DEST (pat) == hard_frame_pointer_rtx;
8168 else if (GET_CODE (pat) == PARALLEL)
8170 int i;
8171 for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
8172 if (GET_CODE (XVECEXP (pat, 0, i)) == SET
8173 && SET_DEST (XVECEXP (pat, 0, i)) == hard_frame_pointer_rtx)
8174 return true;
8176 return false;
8179 /* Initialize cfa_base_rtx, create a preserved VALUE for it and
8180 ensure it isn't flushed during cselib_reset_table.
8181 Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
8182 has been eliminated. */
8184 static void
8185 vt_init_cfa_base (void)
8187 cselib_val *val;
8189 #ifdef FRAME_POINTER_CFA_OFFSET
8190 cfa_base_rtx = frame_pointer_rtx;
8191 #else
8192 cfa_base_rtx = arg_pointer_rtx;
8193 #endif
8194 if (cfa_base_rtx == hard_frame_pointer_rtx
8195 || !fixed_regs[REGNO (cfa_base_rtx)])
8197 cfa_base_rtx = NULL_RTX;
8198 return;
8200 if (!MAY_HAVE_DEBUG_INSNS)
8201 return;
8203 val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1,
8204 get_insns ());
8205 preserve_value (val);
8206 cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx));
8207 var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx,
8208 VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx),
8209 0, NULL_RTX, INSERT);
8212 /* Allocate and initialize the data structures for variable tracking
8213 and parse the RTL to get the micro operations. */
8215 static bool
8216 vt_initialize (void)
8218 basic_block bb, prologue_bb = NULL;
8219 HOST_WIDE_INT fp_cfa_offset = -1;
8221 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
8223 attrs_pool = create_alloc_pool ("attrs_def pool",
8224 sizeof (struct attrs_def), 1024);
8225 var_pool = create_alloc_pool ("variable_def pool",
8226 sizeof (struct variable_def)
8227 + (MAX_VAR_PARTS - 1)
8228 * sizeof (((variable)NULL)->var_part[0]), 64);
8229 loc_chain_pool = create_alloc_pool ("location_chain_def pool",
8230 sizeof (struct location_chain_def),
8231 1024);
8232 shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
8233 sizeof (struct shared_hash_def), 256);
8234 empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
8235 empty_shared_hash->refcount = 1;
8236 empty_shared_hash->htab
8237 = htab_create (1, variable_htab_hash, variable_htab_eq,
8238 variable_htab_free);
8239 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
8240 variable_htab_free);
8241 if (MAY_HAVE_DEBUG_INSNS)
8243 value_chain_pool = create_alloc_pool ("value_chain_def pool",
8244 sizeof (struct value_chain_def),
8245 1024);
8246 value_chains = htab_create (32, value_chain_htab_hash,
8247 value_chain_htab_eq, NULL);
8250 /* Init the IN and OUT sets. */
8251 FOR_ALL_BB (bb)
8253 VTI (bb)->visited = false;
8254 VTI (bb)->flooded = false;
8255 dataflow_set_init (&VTI (bb)->in);
8256 dataflow_set_init (&VTI (bb)->out);
8257 VTI (bb)->permp = NULL;
8260 if (MAY_HAVE_DEBUG_INSNS)
8262 cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
8263 scratch_regs = BITMAP_ALLOC (NULL);
8264 valvar_pool = create_alloc_pool ("small variable_def pool",
8265 sizeof (struct variable_def), 256);
8266 preserved_values = VEC_alloc (rtx, heap, 256);
8268 else
8270 scratch_regs = NULL;
8271 valvar_pool = NULL;
8274 if (!frame_pointer_needed)
8276 rtx reg, elim;
8278 if (!vt_stack_adjustments ())
8279 return false;
8281 #ifdef FRAME_POINTER_CFA_OFFSET
8282 reg = frame_pointer_rtx;
8283 #else
8284 reg = arg_pointer_rtx;
8285 #endif
8286 elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
8287 if (elim != reg)
8289 if (GET_CODE (elim) == PLUS)
8290 elim = XEXP (elim, 0);
8291 if (elim == stack_pointer_rtx)
8292 vt_init_cfa_base ();
8295 else if (!crtl->stack_realign_tried)
8297 rtx reg, elim;
8299 #ifdef FRAME_POINTER_CFA_OFFSET
8300 reg = frame_pointer_rtx;
8301 fp_cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
8302 #else
8303 reg = arg_pointer_rtx;
8304 fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
8305 #endif
8306 elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
8307 if (elim != reg)
8309 if (GET_CODE (elim) == PLUS)
8311 fp_cfa_offset -= INTVAL (XEXP (elim, 1));
8312 elim = XEXP (elim, 0);
8314 if (elim != hard_frame_pointer_rtx)
8315 fp_cfa_offset = -1;
8316 else
8317 prologue_bb = single_succ (ENTRY_BLOCK_PTR);
8321 hard_frame_pointer_adjustment = -1;
8323 FOR_EACH_BB (bb)
8325 rtx insn;
8326 HOST_WIDE_INT pre, post = 0;
8327 basic_block first_bb, last_bb;
8329 if (MAY_HAVE_DEBUG_INSNS)
8331 cselib_record_sets_hook = add_with_sets;
8332 if (dump_file && (dump_flags & TDF_DETAILS))
8333 fprintf (dump_file, "first value: %i\n",
8334 cselib_get_next_uid ());
8337 first_bb = bb;
8338 for (;;)
8340 edge e;
8341 if (bb->next_bb == EXIT_BLOCK_PTR
8342 || ! single_pred_p (bb->next_bb))
8343 break;
8344 e = find_edge (bb, bb->next_bb);
8345 if (! e || (e->flags & EDGE_FALLTHRU) == 0)
8346 break;
8347 bb = bb->next_bb;
8349 last_bb = bb;
8351 /* Add the micro-operations to the vector. */
8352 FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb)
8354 HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
8355 VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
8356 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
8357 insn = NEXT_INSN (insn))
8359 if (INSN_P (insn))
8361 if (!frame_pointer_needed)
8363 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
8364 if (pre)
8366 micro_operation mo;
8367 mo.type = MO_ADJUST;
8368 mo.u.adjust = pre;
8369 mo.insn = insn;
8370 if (dump_file && (dump_flags & TDF_DETAILS))
8371 log_op_type (PATTERN (insn), bb, insn,
8372 MO_ADJUST, dump_file);
8373 VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
8374 &mo);
8375 VTI (bb)->out.stack_adjust += pre;
8379 cselib_hook_called = false;
8380 adjust_insn (bb, insn);
8381 if (MAY_HAVE_DEBUG_INSNS)
8383 cselib_process_insn (insn);
8384 if (dump_file && (dump_flags & TDF_DETAILS))
8386 print_rtl_single (dump_file, insn);
8387 dump_cselib_table (dump_file);
8390 if (!cselib_hook_called)
8391 add_with_sets (insn, 0, 0);
8392 cancel_changes (0);
8394 if (!frame_pointer_needed && post)
8396 micro_operation mo;
8397 mo.type = MO_ADJUST;
8398 mo.u.adjust = post;
8399 mo.insn = insn;
8400 if (dump_file && (dump_flags & TDF_DETAILS))
8401 log_op_type (PATTERN (insn), bb, insn,
8402 MO_ADJUST, dump_file);
8403 VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
8404 &mo);
8405 VTI (bb)->out.stack_adjust += post;
8408 if (bb == prologue_bb
8409 && hard_frame_pointer_adjustment == -1
8410 && RTX_FRAME_RELATED_P (insn)
8411 && fp_setter (insn))
8413 vt_init_cfa_base ();
8414 hard_frame_pointer_adjustment = fp_cfa_offset;
8418 gcc_assert (offset == VTI (bb)->out.stack_adjust);
8421 bb = last_bb;
8423 if (MAY_HAVE_DEBUG_INSNS)
8425 cselib_preserve_only_values ();
8426 cselib_reset_table (cselib_get_next_uid ());
8427 cselib_record_sets_hook = NULL;
8431 hard_frame_pointer_adjustment = -1;
8432 VTI (ENTRY_BLOCK_PTR)->flooded = true;
8433 vt_add_function_parameters ();
8434 cfa_base_rtx = NULL_RTX;
8435 return true;
8438 /* Get rid of all debug insns from the insn stream. */
8440 static void
8441 delete_debug_insns (void)
8443 basic_block bb;
8444 rtx insn, next;
8446 if (!MAY_HAVE_DEBUG_INSNS)
8447 return;
8449 FOR_EACH_BB (bb)
8451 FOR_BB_INSNS_SAFE (bb, insn, next)
8452 if (DEBUG_INSN_P (insn))
8453 delete_insn (insn);
8457 /* Run a fast, BB-local only version of var tracking, to take care of
8458 information that we don't do global analysis on, such that not all
8459 information is lost. If SKIPPED holds, we're skipping the global
8460 pass entirely, so we should try to use information it would have
8461 handled as well.. */
8463 static void
8464 vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED)
8466 /* ??? Just skip it all for now. */
8467 delete_debug_insns ();
8470 /* Free the data structures needed for variable tracking. */
8472 static void
8473 vt_finalize (void)
8475 basic_block bb;
8477 FOR_EACH_BB (bb)
8479 VEC_free (micro_operation, heap, VTI (bb)->mos);
8482 FOR_ALL_BB (bb)
8484 dataflow_set_destroy (&VTI (bb)->in);
8485 dataflow_set_destroy (&VTI (bb)->out);
8486 if (VTI (bb)->permp)
8488 dataflow_set_destroy (VTI (bb)->permp);
8489 XDELETE (VTI (bb)->permp);
8492 free_aux_for_blocks ();
8493 htab_delete (empty_shared_hash->htab);
8494 htab_delete (changed_variables);
8495 free_alloc_pool (attrs_pool);
8496 free_alloc_pool (var_pool);
8497 free_alloc_pool (loc_chain_pool);
8498 free_alloc_pool (shared_hash_pool);
8500 if (MAY_HAVE_DEBUG_INSNS)
8502 htab_delete (value_chains);
8503 free_alloc_pool (value_chain_pool);
8504 free_alloc_pool (valvar_pool);
8505 VEC_free (rtx, heap, preserved_values);
8506 cselib_finish ();
8507 BITMAP_FREE (scratch_regs);
8508 scratch_regs = NULL;
8511 if (vui_vec)
8512 XDELETEVEC (vui_vec);
8513 vui_vec = NULL;
8514 vui_allocated = 0;
8517 /* The entry point to variable tracking pass. */
8519 static inline unsigned int
8520 variable_tracking_main_1 (void)
8522 bool success;
8524 if (flag_var_tracking_assignments < 0)
8526 delete_debug_insns ();
8527 return 0;
8530 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
8532 vt_debug_insns_local (true);
8533 return 0;
8536 mark_dfs_back_edges ();
8537 if (!vt_initialize ())
8539 vt_finalize ();
8540 vt_debug_insns_local (true);
8541 return 0;
8544 success = vt_find_locations ();
8546 if (!success && flag_var_tracking_assignments > 0)
8548 vt_finalize ();
8550 delete_debug_insns ();
8552 /* This is later restored by our caller. */
8553 flag_var_tracking_assignments = 0;
8555 success = vt_initialize ();
8556 gcc_assert (success);
8558 success = vt_find_locations ();
8561 if (!success)
8563 vt_finalize ();
8564 vt_debug_insns_local (false);
8565 return 0;
8568 if (dump_file && (dump_flags & TDF_DETAILS))
8570 dump_dataflow_sets ();
8571 dump_flow_info (dump_file, dump_flags);
8574 vt_emit_notes ();
8576 vt_finalize ();
8577 vt_debug_insns_local (false);
8578 return 0;
8581 unsigned int
8582 variable_tracking_main (void)
8584 unsigned int ret;
8585 int save = flag_var_tracking_assignments;
8587 ret = variable_tracking_main_1 ();
8589 flag_var_tracking_assignments = save;
8591 return ret;
8594 static bool
8595 gate_handle_var_tracking (void)
8597 return (flag_var_tracking);
8602 struct rtl_opt_pass pass_variable_tracking =
8605 RTL_PASS,
8606 "vartrack", /* name */
8607 gate_handle_var_tracking, /* gate */
8608 variable_tracking_main, /* execute */
8609 NULL, /* sub */
8610 NULL, /* next */
8611 0, /* static_pass_number */
8612 TV_VAR_TRACKING, /* tv_id */
8613 0, /* properties_required */
8614 0, /* properties_provided */
8615 0, /* properties_destroyed */
8616 0, /* todo_flags_start */
8617 TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */