1/* Variable tracking routines for the GNU compiler. 2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING. If not, write to the Free 18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 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. 28 29 How does the variable tracking pass work? 30 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 38 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. 45 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. 55 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: 61 62 if (cond) 63 set A; 64 else 65 set B; 66 CODE; 67 if (cond) 68 use A; 69 else 70 use B; 71 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). 79 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). 86 87*/ 88 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 110/* Type of micro operation. */ 111enum micro_operation_type 112{ 113 MO_USE, /* Use location (REG or MEM). */ 114 MO_USE_NO_VAR,/* Use location which is not associated with a variable 115 or the variable is not trackable. */ 116 MO_SET, /* Set location. */ 117 MO_COPY, /* Copy the same portion of a variable from one 118 location to another. */ 119 MO_CLOBBER, /* Clobber location. */ 120 MO_CALL, /* Call insn. */ 121 MO_ADJUST /* Adjust stack pointer. */ 122}; 123 124/* Where shall the note be emitted? BEFORE or AFTER the instruction. */ 125enum emit_note_where 126{ 127 EMIT_NOTE_BEFORE_INSN, 128 EMIT_NOTE_AFTER_INSN 129}; 130 131/* Structure holding information about micro operation. */ 132typedef struct micro_operation_def 133{ 134 /* Type of micro operation. */ 135 enum micro_operation_type type; 136 137 union { 138 /* Location. */ 139 rtx loc; 140 141 /* Stack adjustment. */ 142 HOST_WIDE_INT adjust; 143 } u; 144 145 /* The instruction which the micro operation is in, for MO_USE, 146 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent 147 instruction or note in the original flow (before any var-tracking 148 notes are inserted, to simplify emission of notes), for MO_SET 149 and MO_CLOBBER. */ 150 rtx insn; 151} micro_operation; 152 153/* Structure for passing some other parameters to function 154 emit_note_insn_var_location. */ 155typedef struct emit_note_data_def 156{ 157 /* The instruction which the note will be emitted before/after. */ 158 rtx insn; 159 160 /* Where the note will be emitted (before/after insn)? */ 161 enum emit_note_where where; 162} emit_note_data; 163 164/* Description of location of a part of a variable. The content of a physical 165 register is described by a chain of these structures. 166 The chains are pretty short (usually 1 or 2 elements) and thus 167 chain is the best data structure. */ 168typedef struct attrs_def 169{ 170 /* Pointer to next member of the list. */ 171 struct attrs_def *next; 172 173 /* The rtx of register. */ 174 rtx loc; 175 176 /* The declaration corresponding to LOC. */ 177 tree decl; 178 179 /* Offset from start of DECL. */ 180 HOST_WIDE_INT offset; 181} *attrs; 182 183/* Structure holding the IN or OUT set for a basic block. */ 184typedef struct dataflow_set_def 185{ 186 /* Adjustment of stack offset. */ 187 HOST_WIDE_INT stack_adjust; 188 189 /* Attributes for registers (lists of attrs). */ 190 attrs regs[FIRST_PSEUDO_REGISTER]; 191 192 /* Variable locations. */ 193 htab_t vars; 194} dataflow_set; 195 196/* The structure (one for each basic block) containing the information 197 needed for variable tracking. */ 198typedef struct variable_tracking_info_def 199{ 200 /* Number of micro operations stored in the MOS array. */ 201 int n_mos; 202 203 /* The array of micro operations. */ 204 micro_operation *mos; 205 206 /* The IN and OUT set for dataflow analysis. */ 207 dataflow_set in; 208 dataflow_set out; 209 210 /* Has the block been visited in DFS? */ 211 bool visited; 212} *variable_tracking_info; 213 214/* Structure for chaining the locations. */ 215typedef struct location_chain_def 216{ 217 /* Next element in the chain. */ 218 struct location_chain_def *next; 219 220 /* The location (REG or MEM). */ 221 rtx loc; 222} *location_chain; 223 224/* Structure describing one part of variable. */ 225typedef struct variable_part_def 226{ 227 /* Chain of locations of the part. */ 228 location_chain loc_chain; 229 230 /* Location which was last emitted to location list. */ 231 rtx cur_loc; 232 233 /* The offset in the variable. */ 234 HOST_WIDE_INT offset; 235} variable_part; 236 237/* Maximum number of location parts. */ 238#define MAX_VAR_PARTS 16 239 240/* Structure describing where the variable is located. */ 241typedef struct variable_def 242{ 243 /* The declaration of the variable. */ 244 tree decl; 245 246 /* Reference count. */ 247 int refcount; 248 249 /* Number of variable parts. */ 250 int n_var_parts; 251 252 /* The variable parts. */ 253 variable_part var_part[MAX_VAR_PARTS]; 254} *variable; 255 256/* Hash function for DECL for VARIABLE_HTAB. */ 257#define VARIABLE_HASH_VAL(decl) (DECL_UID (decl)) 258 259/* Pointer to the BB's information specific to variable tracking pass. */ 260#define VTI(BB) ((variable_tracking_info) (BB)->aux) 261 262/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */ 263#define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0) 264 265/* Alloc pool for struct attrs_def. */ 266static alloc_pool attrs_pool; 267 268/* Alloc pool for struct variable_def. */ 269static alloc_pool var_pool; 270 271/* Alloc pool for struct location_chain_def. */ 272static alloc_pool loc_chain_pool; 273 274/* Changed variables, notes will be emitted for them. */ 275static htab_t changed_variables; 276 277/* Shall notes be emitted? */ 278static bool emit_notes; 279 280/* Local function prototypes. */ 281static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, 282 HOST_WIDE_INT *); 283static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, 284 HOST_WIDE_INT *); 285static void bb_stack_adjust_offset (basic_block); 286static bool vt_stack_adjustments (void); 287static rtx adjust_stack_reference (rtx, HOST_WIDE_INT); 288static hashval_t variable_htab_hash (const void *); 289static int variable_htab_eq (const void *, const void *); 290static void variable_htab_free (void *); 291 292static void init_attrs_list_set (attrs *); 293static void attrs_list_clear (attrs *); 294static attrs attrs_list_member (attrs, tree, HOST_WIDE_INT); 295static void attrs_list_insert (attrs *, tree, HOST_WIDE_INT, rtx); 296static void attrs_list_copy (attrs *, attrs); 297static void attrs_list_union (attrs *, attrs); 298 299static void vars_clear (htab_t); 300static variable unshare_variable (dataflow_set *set, variable var); 301static int vars_copy_1 (void **, void *); 302static void vars_copy (htab_t, htab_t); 303static tree var_debug_decl (tree); 304static void var_reg_set (dataflow_set *, rtx); 305static void var_reg_delete_and_set (dataflow_set *, rtx, bool); 306static void var_reg_delete (dataflow_set *, rtx, bool); 307static void var_regno_delete (dataflow_set *, int); 308static void var_mem_set (dataflow_set *, rtx); 309static void var_mem_delete_and_set (dataflow_set *, rtx, bool); 310static void var_mem_delete (dataflow_set *, rtx, bool); 311 312static void dataflow_set_init (dataflow_set *, int); 313static void dataflow_set_clear (dataflow_set *); 314static void dataflow_set_copy (dataflow_set *, dataflow_set *); 315static int variable_union_info_cmp_pos (const void *, const void *); 316static int variable_union (void **, void *); 317static void dataflow_set_union (dataflow_set *, dataflow_set *); 318static bool variable_part_different_p (variable_part *, variable_part *); 319static bool variable_different_p (variable, variable, bool); 320static int dataflow_set_different_1 (void **, void *); 321static int dataflow_set_different_2 (void **, void *); 322static bool dataflow_set_different (dataflow_set *, dataflow_set *); 323static void dataflow_set_destroy (dataflow_set *); 324 325static bool contains_symbol_ref (rtx); 326static bool track_expr_p (tree); 327static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT); 328static int count_uses (rtx *, void *); 329static void count_uses_1 (rtx *, void *); 330static void count_stores (rtx, rtx, void *); 331static int add_uses (rtx *, void *); 332static void add_uses_1 (rtx *, void *); 333static void add_stores (rtx, rtx, void *); 334static bool compute_bb_dataflow (basic_block); 335static void vt_find_locations (void); 336 337static void dump_attrs_list (attrs); 338static int dump_variable (void **, void *); 339static void dump_vars (htab_t); 340static void dump_dataflow_set (dataflow_set *); 341static void dump_dataflow_sets (void); 342 343static void variable_was_changed (variable, htab_t); 344static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); 345static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); 346static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); 347static int emit_note_insn_var_location (void **, void *); 348static void emit_notes_for_changes (rtx, enum emit_note_where); 349static int emit_notes_for_differences_1 (void **, void *); 350static int emit_notes_for_differences_2 (void **, void *); 351static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *); 352static void emit_notes_in_bb (basic_block); 353static void vt_emit_notes (void); 354 355static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *); 356static void vt_add_function_parameters (void); 357static void vt_initialize (void); 358static void vt_finalize (void); 359 360/* Given a SET, calculate the amount of stack adjustment it contains 361 PRE- and POST-modifying stack pointer. 362 This function is similar to stack_adjust_offset. */ 363 364static void 365stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre, 366 HOST_WIDE_INT *post) 367{ 368 rtx src = SET_SRC (pattern); 369 rtx dest = SET_DEST (pattern); 370 enum rtx_code code; 371 372 if (dest == stack_pointer_rtx) 373 { 374 /* (set (reg sp) (plus (reg sp) (const_int))) */ 375 code = GET_CODE (src); 376 if (! (code == PLUS || code == MINUS) 377 || XEXP (src, 0) != stack_pointer_rtx 378 || GET_CODE (XEXP (src, 1)) != CONST_INT) 379 return; 380 381 if (code == MINUS) 382 *post += INTVAL (XEXP (src, 1)); 383 else 384 *post -= INTVAL (XEXP (src, 1)); 385 } 386 else if (MEM_P (dest)) 387 { 388 /* (set (mem (pre_dec (reg sp))) (foo)) */ 389 src = XEXP (dest, 0); 390 code = GET_CODE (src); 391 392 switch (code) 393 { 394 case PRE_MODIFY: 395 case POST_MODIFY: 396 if (XEXP (src, 0) == stack_pointer_rtx) 397 { 398 rtx val = XEXP (XEXP (src, 1), 1); 399 /* We handle only adjustments by constant amount. */ 400 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS && 401 GET_CODE (val) == CONST_INT); 402 403 if (code == PRE_MODIFY) 404 *pre -= INTVAL (val); 405 else 406 *post -= INTVAL (val); 407 break; 408 } 409 return; 410 411 case PRE_DEC: 412 if (XEXP (src, 0) == stack_pointer_rtx) 413 { 414 *pre += GET_MODE_SIZE (GET_MODE (dest)); 415 break; 416 } 417 return; 418 419 case POST_DEC: 420 if (XEXP (src, 0) == stack_pointer_rtx) 421 { 422 *post += GET_MODE_SIZE (GET_MODE (dest)); 423 break; 424 } 425 return; 426 427 case PRE_INC: 428 if (XEXP (src, 0) == stack_pointer_rtx) 429 { 430 *pre -= GET_MODE_SIZE (GET_MODE (dest)); 431 break; 432 } 433 return; 434 435 case POST_INC: 436 if (XEXP (src, 0) == stack_pointer_rtx) 437 { 438 *post -= GET_MODE_SIZE (GET_MODE (dest)); 439 break; 440 } 441 return; 442 443 default: 444 return; 445 } 446 } 447} 448 449/* Given an INSN, calculate the amount of stack adjustment it contains 450 PRE- and POST-modifying stack pointer. */ 451 452static void 453insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre, 454 HOST_WIDE_INT *post) 455{ 456 *pre = 0; 457 *post = 0; 458 459 if (GET_CODE (PATTERN (insn)) == SET) 460 stack_adjust_offset_pre_post (PATTERN (insn), pre, post); 461 else if (GET_CODE (PATTERN (insn)) == PARALLEL 462 || GET_CODE (PATTERN (insn)) == SEQUENCE) 463 { 464 int i; 465 466 /* There may be stack adjustments inside compound insns. Search 467 for them. */ 468 for ( i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) 469 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 470 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn), 0, i), 471 pre, post); 472 } 473} 474 475/* Compute stack adjustment in basic block BB. */ 476 477static void 478bb_stack_adjust_offset (basic_block bb) 479{ 480 HOST_WIDE_INT offset; 481 int i; 482 483 offset = VTI (bb)->in.stack_adjust; 484 for (i = 0; i < VTI (bb)->n_mos; i++) 485 { 486 if (VTI (bb)->mos[i].type == MO_ADJUST) 487 offset += VTI (bb)->mos[i].u.adjust; 488 else if (VTI (bb)->mos[i].type != MO_CALL) 489 { 490 if (MEM_P (VTI (bb)->mos[i].u.loc)) 491 { 492 VTI (bb)->mos[i].u.loc 493 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset); 494 } 495 } 496 } 497 VTI (bb)->out.stack_adjust = offset; 498} 499 500/* Compute stack adjustments for all blocks by traversing DFS tree. 501 Return true when the adjustments on all incoming edges are consistent. 502 Heavily borrowed from pre_and_rev_post_order_compute. */ 503 504static bool 505vt_stack_adjustments (void) 506{ 507 edge_iterator *stack; 508 int sp; 509 510 /* Initialize entry block. */ 511 VTI (ENTRY_BLOCK_PTR)->visited = true; 512 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET; 513 514 /* Allocate stack for back-tracking up CFG. */ 515 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1); 516 sp = 0; 517 518 /* Push the first edge on to the stack. */ 519 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs); 520 521 while (sp) 522 { 523 edge_iterator ei; 524 basic_block src; 525 basic_block dest; 526 527 /* Look at the edge on the top of the stack. */ 528 ei = stack[sp - 1]; 529 src = ei_edge (ei)->src; 530 dest = ei_edge (ei)->dest; 531 532 /* Check if the edge destination has been visited yet. */ 533 if (!VTI (dest)->visited) 534 { 535 VTI (dest)->visited = true; 536 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust; 537 bb_stack_adjust_offset (dest); 538 539 if (EDGE_COUNT (dest->succs) > 0) 540 /* Since the DEST node has been visited for the first 541 time, check its successors. */ 542 stack[sp++] = ei_start (dest->succs); 543 } 544 else 545 { 546 /* Check whether the adjustments on the edges are the same. */ 547 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust) 548 { 549 free (stack); 550 return false; 551 } 552 553 if (! ei_one_before_end_p (ei)) 554 /* Go to the next edge. */ 555 ei_next (&stack[sp - 1]); 556 else 557 /* Return to previous level if there are no more edges. */ 558 sp--; 559 } 560 } 561 562 free (stack); 563 return true; 564} 565 566/* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative 567 to the argument pointer. Return the new rtx. */ 568 569static rtx 570adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) 571{ 572 rtx addr, cfa, tmp; 573 574#ifdef FRAME_POINTER_CFA_OFFSET 575 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl); 576 cfa = plus_constant (frame_pointer_rtx, adjustment); 577#else 578 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl); 579 cfa = plus_constant (arg_pointer_rtx, adjustment); 580#endif 581 582 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa); 583 tmp = simplify_rtx (addr); 584 if (tmp) 585 addr = tmp; 586 587 return replace_equiv_address_nv (mem, addr); 588} 589 590/* The hash function for variable_htab, computes the hash value 591 from the declaration of variable X. */ 592 593static hashval_t 594variable_htab_hash (const void *x) 595{ 596 const variable v = (const variable) x; 597 598 return (VARIABLE_HASH_VAL (v->decl)); 599} 600 601/* Compare the declaration of variable X with declaration Y. */ 602 603static int 604variable_htab_eq (const void *x, const void *y) 605{ 606 const variable v = (const variable) x; 607 const tree decl = (const tree) y; 608 609 return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl)); 610} 611 612/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */ 613 614static void 615variable_htab_free (void *elem) 616{ 617 int i; 618 variable var = (variable) elem; 619 location_chain node, next; 620 621 gcc_assert (var->refcount > 0); 622 623 var->refcount--; 624 if (var->refcount > 0) 625 return; 626 627 for (i = 0; i < var->n_var_parts; i++) 628 { 629 for (node = var->var_part[i].loc_chain; node; node = next) 630 { 631 next = node->next; 632 pool_free (loc_chain_pool, node); 633 } 634 var->var_part[i].loc_chain = NULL; 635 } 636 pool_free (var_pool, var); 637} 638 639/* Initialize the set (array) SET of attrs to empty lists. */ 640 641static void 642init_attrs_list_set (attrs *set) 643{ 644 int i; 645 646 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 647 set[i] = NULL; 648} 649 650/* Make the list *LISTP empty. */ 651 652static void 653attrs_list_clear (attrs *listp) 654{ 655 attrs list, next; 656 657 for (list = *listp; list; list = next) 658 { 659 next = list->next; 660 pool_free (attrs_pool, list); 661 } 662 *listp = NULL; 663} 664 665/* Return true if the pair of DECL and OFFSET is the member of the LIST. */ 666 667static attrs 668attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset) 669{ 670 for (; list; list = list->next) 671 if (list->decl == decl && list->offset == offset) 672 return list; 673 return NULL; 674} 675 676/* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */ 677 678static void 679attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc) 680{ 681 attrs list; 682 683 list = pool_alloc (attrs_pool); 684 list->loc = loc; 685 list->decl = decl; 686 list->offset = offset; 687 list->next = *listp; 688 *listp = list; 689} 690 691/* Copy all nodes from SRC and create a list *DSTP of the copies. */ 692 693static void 694attrs_list_copy (attrs *dstp, attrs src) 695{ 696 attrs n; 697 698 attrs_list_clear (dstp); 699 for (; src; src = src->next) 700 { 701 n = pool_alloc (attrs_pool); 702 n->loc = src->loc; 703 n->decl = src->decl; 704 n->offset = src->offset; 705 n->next = *dstp; 706 *dstp = n; 707 } 708} 709 710/* Add all nodes from SRC which are not in *DSTP to *DSTP. */ 711 712static void 713attrs_list_union (attrs *dstp, attrs src) 714{ 715 for (; src; src = src->next) 716 { 717 if (!attrs_list_member (*dstp, src->decl, src->offset)) 718 attrs_list_insert (dstp, src->decl, src->offset, src->loc); 719 } 720} 721 722/* Delete all variables from hash table VARS. */ 723 724static void 725vars_clear (htab_t vars) 726{ 727 htab_empty (vars); 728} 729 730/* Return a copy of a variable VAR and insert it to dataflow set SET. */ 731 732static variable 733unshare_variable (dataflow_set *set, variable var) 734{ 735 void **slot; 736 variable new_var; 737 int i; 738 739 new_var = pool_alloc (var_pool); 740 new_var->decl = var->decl; 741 new_var->refcount = 1; 742 var->refcount--; 743 new_var->n_var_parts = var->n_var_parts; 744 745 for (i = 0; i < var->n_var_parts; i++) 746 { 747 location_chain node; 748 location_chain *nextp; 749 750 new_var->var_part[i].offset = var->var_part[i].offset; 751 nextp = &new_var->var_part[i].loc_chain; 752 for (node = var->var_part[i].loc_chain; node; node = node->next) 753 { 754 location_chain new_lc; 755 756 new_lc = pool_alloc (loc_chain_pool); 757 new_lc->next = NULL; 758 new_lc->loc = node->loc; 759 760 *nextp = new_lc; 761 nextp = &new_lc->next; 762 } 763 764 /* We are at the basic block boundary when copying variable description 765 so set the CUR_LOC to be the first element of the chain. */ 766 if (new_var->var_part[i].loc_chain) 767 new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc; 768 else 769 new_var->var_part[i].cur_loc = NULL; 770 } 771 772 slot = htab_find_slot_with_hash (set->vars, new_var->decl, 773 VARIABLE_HASH_VAL (new_var->decl), 774 INSERT); 775 *slot = new_var; 776 return new_var; 777} 778 779/* Add a variable from *SLOT to hash table DATA and increase its reference 780 count. */ 781 782static int 783vars_copy_1 (void **slot, void *data) 784{ 785 htab_t dst = (htab_t) data; 786 variable src, *dstp; 787 788 src = *(variable *) slot; 789 src->refcount++; 790 791 dstp = (variable *) htab_find_slot_with_hash (dst, src->decl, 792 VARIABLE_HASH_VAL (src->decl), 793 INSERT); 794 *dstp = src; 795 796 /* Continue traversing the hash table. */ 797 return 1; 798} 799 800/* Copy all variables from hash table SRC to hash table DST. */ 801 802static void 803vars_copy (htab_t dst, htab_t src) 804{ 805 vars_clear (dst); 806 htab_traverse (src, vars_copy_1, dst); 807} 808 809/* Map a decl to its main debug decl. */ 810 811static inline tree 812var_debug_decl (tree decl) 813{ 814 if (decl && DECL_P (decl) 815 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl) 816 && DECL_P (DECL_DEBUG_EXPR (decl))) 817 decl = DECL_DEBUG_EXPR (decl); 818 819 return decl; 820} 821 822/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ 823 824static void 825var_reg_set (dataflow_set *set, rtx loc) 826{ 827 tree decl = REG_EXPR (loc); 828 HOST_WIDE_INT offset = REG_OFFSET (loc); 829 attrs node; 830 831 decl = var_debug_decl (decl); 832 833 for (node = set->regs[REGNO (loc)]; node; node = node->next) 834 if (node->decl == decl && node->offset == offset) 835 break; 836 if (!node) 837 attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); 838 set_variable_part (set, loc, decl, offset); 839} 840 841/* Delete current content of register LOC in dataflow set SET and set 842 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If 843 MODIFY is true, any other live copies of the same variable part are 844 also deleted from the dataflow set, otherwise the variable part is 845 assumed to be copied from another location holding the same 846 part. */ 847 848static void 849var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify) 850{ 851 tree decl = REG_EXPR (loc); 852 HOST_WIDE_INT offset = REG_OFFSET (loc); 853 attrs node, next; 854 attrs *nextp; 855 856 decl = var_debug_decl (decl); 857 858 nextp = &set->regs[REGNO (loc)]; 859 for (node = *nextp; node; node = next) 860 { 861 next = node->next; 862 if (node->decl != decl || node->offset != offset) 863 { 864 delete_variable_part (set, node->loc, node->decl, node->offset); 865 pool_free (attrs_pool, node); 866 *nextp = next; 867 } 868 else 869 { 870 node->loc = loc; 871 nextp = &node->next; 872 } 873 } 874 if (modify) 875 clobber_variable_part (set, loc, decl, offset); 876 var_reg_set (set, loc); 877} 878 879/* Delete current content of register LOC in dataflow set SET. If 880 CLOBBER is true, also delete any other live copies of the same 881 variable part. */ 882 883static void 884var_reg_delete (dataflow_set *set, rtx loc, bool clobber) 885{ 886 attrs *reg = &set->regs[REGNO (loc)]; 887 attrs node, next; 888 889 if (clobber) 890 { 891 tree decl = REG_EXPR (loc); 892 HOST_WIDE_INT offset = REG_OFFSET (loc); 893 894 decl = var_debug_decl (decl); 895 896 clobber_variable_part (set, NULL, decl, offset); 897 } 898 899 for (node = *reg; node; node = next) 900 { 901 next = node->next; 902 delete_variable_part (set, node->loc, node->decl, node->offset); 903 pool_free (attrs_pool, node); 904 } 905 *reg = NULL; 906} 907 908/* Delete content of register with number REGNO in dataflow set SET. */ 909 910static void 911var_regno_delete (dataflow_set *set, int regno) 912{ 913 attrs *reg = &set->regs[regno]; 914 attrs node, next; 915 916 for (node = *reg; node; node = next) 917 { 918 next = node->next; 919 delete_variable_part (set, node->loc, node->decl, node->offset); 920 pool_free (attrs_pool, node); 921 } 922 *reg = NULL; 923} 924 925/* Set the location part of variable MEM_EXPR (LOC) in dataflow set 926 SET to LOC. 927 Adjust the address first if it is stack pointer based. */ 928 929static void 930var_mem_set (dataflow_set *set, rtx loc) 931{ 932 tree decl = MEM_EXPR (loc); 933 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 934 935 decl = var_debug_decl (decl); 936 937 set_variable_part (set, loc, decl, offset); 938} 939 940/* Delete and set the location part of variable MEM_EXPR (LOC) in 941 dataflow set SET to LOC. If MODIFY is true, any other live copies 942 of the same variable part are also deleted from the dataflow set, 943 otherwise the variable part is assumed to be copied from another 944 location holding the same part. 945 Adjust the address first if it is stack pointer based. */ 946 947static void 948var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify) 949{ 950 tree decl = MEM_EXPR (loc); 951 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 952 953 decl = var_debug_decl (decl); 954 955 if (modify) 956 clobber_variable_part (set, NULL, decl, offset); 957 var_mem_set (set, loc); 958} 959 960/* Delete the location part LOC from dataflow set SET. If CLOBBER is 961 true, also delete any other live copies of the same variable part. 962 Adjust the address first if it is stack pointer based. */ 963 964static void 965var_mem_delete (dataflow_set *set, rtx loc, bool clobber) 966{ 967 tree decl = MEM_EXPR (loc); 968 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 969 970 decl = var_debug_decl (decl); 971 if (clobber) 972 clobber_variable_part (set, NULL, decl, offset); 973 delete_variable_part (set, loc, decl, offset); 974} 975 976/* Initialize dataflow set SET to be empty. 977 VARS_SIZE is the initial size of hash table VARS. */ 978 979static void 980dataflow_set_init (dataflow_set *set, int vars_size) 981{ 982 init_attrs_list_set (set->regs); 983 set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq, 984 variable_htab_free); 985 set->stack_adjust = 0; 986} 987 988/* Delete the contents of dataflow set SET. */ 989 990static void 991dataflow_set_clear (dataflow_set *set) 992{ 993 int i; 994 995 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 996 attrs_list_clear (&set->regs[i]); 997 998 vars_clear (set->vars); 999} 1000 1001/* Copy the contents of dataflow set SRC to DST. */ 1002 1003static void 1004dataflow_set_copy (dataflow_set *dst, dataflow_set *src) 1005{ 1006 int i; 1007 1008 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1009 attrs_list_copy (&dst->regs[i], src->regs[i]); 1010 1011 vars_copy (dst->vars, src->vars); 1012 dst->stack_adjust = src->stack_adjust; 1013} 1014 1015/* Information for merging lists of locations for a given offset of variable. 1016 */ 1017struct variable_union_info 1018{ 1019 /* Node of the location chain. */ 1020 location_chain lc; 1021 1022 /* The sum of positions in the input chains. */ 1023 int pos; 1024 1025 /* The position in the chains of SRC and DST dataflow sets. */ 1026 int pos_src; 1027 int pos_dst; 1028}; 1029 1030/* Compare function for qsort, order the structures by POS element. */ 1031 1032static int 1033variable_union_info_cmp_pos (const void *n1, const void *n2) 1034{ 1035 const struct variable_union_info *i1 = n1; 1036 const struct variable_union_info *i2 = n2; 1037 1038 if (i1->pos != i2->pos) 1039 return i1->pos - i2->pos; 1040 1041 return (i1->pos_dst - i2->pos_dst); 1042} 1043 1044/* Compute union of location parts of variable *SLOT and the same variable 1045 from hash table DATA. Compute "sorted" union of the location chains 1046 for common offsets, i.e. the locations of a variable part are sorted by 1047 a priority where the priority is the sum of the positions in the 2 chains 1048 (if a location is only in one list the position in the second list is 1049 defined to be larger than the length of the chains). 1050 When we are updating the location parts the newest location is in the 1051 beginning of the chain, so when we do the described "sorted" union 1052 we keep the newest locations in the beginning. */ 1053 1054static int 1055variable_union (void **slot, void *data) 1056{ 1057 variable src, dst, *dstp; 1058 dataflow_set *set = (dataflow_set *) data; 1059 int i, j, k; 1060 1061 src = *(variable *) slot; 1062 dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl, 1063 VARIABLE_HASH_VAL (src->decl), 1064 INSERT); 1065 if (!*dstp) 1066 { 1067 src->refcount++; 1068 1069 /* If CUR_LOC of some variable part is not the first element of 1070 the location chain we are going to change it so we have to make 1071 a copy of the variable. */ 1072 for (k = 0; k < src->n_var_parts; k++) 1073 { 1074 gcc_assert (!src->var_part[k].loc_chain 1075 == !src->var_part[k].cur_loc); 1076 if (src->var_part[k].loc_chain) 1077 { 1078 gcc_assert (src->var_part[k].cur_loc); 1079 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) 1080 break; 1081 } 1082 } 1083 if (k < src->n_var_parts) 1084 unshare_variable (set, src); 1085 else 1086 *dstp = src; 1087 1088 /* Continue traversing the hash table. */ 1089 return 1; 1090 } 1091 else 1092 dst = *dstp; 1093 1094 gcc_assert (src->n_var_parts); 1095 1096 /* Count the number of location parts, result is K. */ 1097 for (i = 0, j = 0, k = 0; 1098 i < src->n_var_parts && j < dst->n_var_parts; k++) 1099 { 1100 if (src->var_part[i].offset == dst->var_part[j].offset) 1101 { 1102 i++; 1103 j++; 1104 } 1105 else if (src->var_part[i].offset < dst->var_part[j].offset) 1106 i++; 1107 else 1108 j++; 1109 } 1110 k += src->n_var_parts - i; 1111 k += dst->n_var_parts - j; 1112 1113 /* We track only variables whose size is <= MAX_VAR_PARTS bytes 1114 thus there are at most MAX_VAR_PARTS different offsets. */ 1115 gcc_assert (k <= MAX_VAR_PARTS); 1116 1117 if (dst->refcount > 1 && dst->n_var_parts != k) 1118 dst = unshare_variable (set, dst); 1119 1120 i = src->n_var_parts - 1; 1121 j = dst->n_var_parts - 1; 1122 dst->n_var_parts = k; 1123 1124 for (k--; k >= 0; k--) 1125 { 1126 location_chain node, node2; 1127 1128 if (i >= 0 && j >= 0 1129 && src->var_part[i].offset == dst->var_part[j].offset) 1130 { 1131 /* Compute the "sorted" union of the chains, i.e. the locations which 1132 are in both chains go first, they are sorted by the sum of 1133 positions in the chains. */ 1134 int dst_l, src_l; 1135 int ii, jj, n; 1136 struct variable_union_info *vui; 1137 1138 /* If DST is shared compare the location chains. 1139 If they are different we will modify the chain in DST with 1140 high probability so make a copy of DST. */ 1141 if (dst->refcount > 1) 1142 { 1143 for (node = src->var_part[i].loc_chain, 1144 node2 = dst->var_part[j].loc_chain; node && node2; 1145 node = node->next, node2 = node2->next) 1146 { 1147 if (!((REG_P (node2->loc) 1148 && REG_P (node->loc) 1149 && REGNO (node2->loc) == REGNO (node->loc)) 1150 || rtx_equal_p (node2->loc, node->loc))) 1151 break; 1152 } 1153 if (node || node2) 1154 dst = unshare_variable (set, dst); 1155 } 1156 1157 src_l = 0; 1158 for (node = src->var_part[i].loc_chain; node; node = node->next) 1159 src_l++; 1160 dst_l = 0; 1161 for (node = dst->var_part[j].loc_chain; node; node = node->next) 1162 dst_l++; 1163 vui = XCNEWVEC (struct variable_union_info, src_l + dst_l); 1164 1165 /* Fill in the locations from DST. */ 1166 for (node = dst->var_part[j].loc_chain, jj = 0; node; 1167 node = node->next, jj++) 1168 { 1169 vui[jj].lc = node; 1170 vui[jj].pos_dst = jj; 1171 1172 /* Value larger than a sum of 2 valid positions. */ 1173 vui[jj].pos_src = src_l + dst_l; 1174 } 1175 1176 /* Fill in the locations from SRC. */ 1177 n = dst_l; 1178 for (node = src->var_part[i].loc_chain, ii = 0; node; 1179 node = node->next, ii++) 1180 { 1181 /* Find location from NODE. */ 1182 for (jj = 0; jj < dst_l; jj++) 1183 { 1184 if ((REG_P (vui[jj].lc->loc) 1185 && REG_P (node->loc) 1186 && REGNO (vui[jj].lc->loc) == REGNO (node->loc)) 1187 || rtx_equal_p (vui[jj].lc->loc, node->loc)) 1188 { 1189 vui[jj].pos_src = ii; 1190 break; 1191 } 1192 } 1193 if (jj >= dst_l) /* The location has not been found. */ 1194 { 1195 location_chain new_node; 1196 1197 /* Copy the location from SRC. */ 1198 new_node = pool_alloc (loc_chain_pool); 1199 new_node->loc = node->loc; 1200 vui[n].lc = new_node; 1201 vui[n].pos_src = ii; 1202 vui[n].pos_dst = src_l + dst_l; 1203 n++; 1204 } 1205 } 1206 1207 for (ii = 0; ii < src_l + dst_l; ii++) 1208 vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst; 1209 1210 qsort (vui, n, sizeof (struct variable_union_info), 1211 variable_union_info_cmp_pos); 1212 1213 /* Reconnect the nodes in sorted order. */ 1214 for (ii = 1; ii < n; ii++) 1215 vui[ii - 1].lc->next = vui[ii].lc; 1216 vui[n - 1].lc->next = NULL; 1217 1218 dst->var_part[k].loc_chain = vui[0].lc; 1219 dst->var_part[k].offset = dst->var_part[j].offset; 1220 1221 free (vui); 1222 i--; 1223 j--; 1224 } 1225 else if ((i >= 0 && j >= 0 1226 && src->var_part[i].offset < dst->var_part[j].offset) 1227 || i < 0) 1228 { 1229 dst->var_part[k] = dst->var_part[j]; 1230 j--; 1231 } 1232 else if ((i >= 0 && j >= 0 1233 && src->var_part[i].offset > dst->var_part[j].offset) 1234 || j < 0) 1235 { 1236 location_chain *nextp; 1237 1238 /* Copy the chain from SRC. */ 1239 nextp = &dst->var_part[k].loc_chain; 1240 for (node = src->var_part[i].loc_chain; node; node = node->next) 1241 { 1242 location_chain new_lc; 1243 1244 new_lc = pool_alloc (loc_chain_pool); 1245 new_lc->next = NULL; 1246 new_lc->loc = node->loc; 1247 1248 *nextp = new_lc; 1249 nextp = &new_lc->next; 1250 } 1251 1252 dst->var_part[k].offset = src->var_part[i].offset; 1253 i--; 1254 } 1255 1256 /* We are at the basic block boundary when computing union 1257 so set the CUR_LOC to be the first element of the chain. */ 1258 if (dst->var_part[k].loc_chain) 1259 dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc; 1260 else 1261 dst->var_part[k].cur_loc = NULL; 1262 } 1263 1264 /* Continue traversing the hash table. */ 1265 return 1; 1266} 1267 1268/* Compute union of dataflow sets SRC and DST and store it to DST. */ 1269 1270static void 1271dataflow_set_union (dataflow_set *dst, dataflow_set *src) 1272{ 1273 int i; 1274 1275 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1276 attrs_list_union (&dst->regs[i], src->regs[i]); 1277 1278 htab_traverse (src->vars, variable_union, dst); 1279} 1280 1281/* Flag whether two dataflow sets being compared contain different data. */ 1282static bool 1283dataflow_set_different_value; 1284 1285static bool 1286variable_part_different_p (variable_part *vp1, variable_part *vp2) 1287{ 1288 location_chain lc1, lc2; 1289 1290 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next) 1291 { 1292 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next) 1293 { 1294 if (REG_P (lc1->loc) && REG_P (lc2->loc)) 1295 { 1296 if (REGNO (lc1->loc) == REGNO (lc2->loc)) 1297 break; 1298 } 1299 if (rtx_equal_p (lc1->loc, lc2->loc)) 1300 break; 1301 } 1302 if (!lc2) 1303 return true; 1304 } 1305 return false; 1306} 1307 1308/* Return true if variables VAR1 and VAR2 are different. 1309 If COMPARE_CURRENT_LOCATION is true compare also the cur_loc of each 1310 variable part. */ 1311 1312static bool 1313variable_different_p (variable var1, variable var2, 1314 bool compare_current_location) 1315{ 1316 int i; 1317 1318 if (var1 == var2) 1319 return false; 1320 1321 if (var1->n_var_parts != var2->n_var_parts) 1322 return true; 1323 1324 for (i = 0; i < var1->n_var_parts; i++) 1325 { 1326 if (var1->var_part[i].offset != var2->var_part[i].offset) 1327 return true; 1328 if (compare_current_location) 1329 { 1330 if (!((REG_P (var1->var_part[i].cur_loc) 1331 && REG_P (var2->var_part[i].cur_loc) 1332 && (REGNO (var1->var_part[i].cur_loc) 1333 == REGNO (var2->var_part[i].cur_loc))) 1334 || rtx_equal_p (var1->var_part[i].cur_loc, 1335 var2->var_part[i].cur_loc))) 1336 return true; 1337 } 1338 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i])) 1339 return true; 1340 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i])) 1341 return true; 1342 } 1343 return false; 1344} 1345 1346/* Compare variable *SLOT with the same variable in hash table DATA 1347 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */ 1348 1349static int 1350dataflow_set_different_1 (void **slot, void *data) 1351{ 1352 htab_t htab = (htab_t) data; 1353 variable var1, var2; 1354 1355 var1 = *(variable *) slot; 1356 var2 = htab_find_with_hash (htab, var1->decl, 1357 VARIABLE_HASH_VAL (var1->decl)); 1358 if (!var2) 1359 { 1360 dataflow_set_different_value = true; 1361 1362 /* Stop traversing the hash table. */ 1363 return 0; 1364 } 1365 1366 if (variable_different_p (var1, var2, false)) 1367 { 1368 dataflow_set_different_value = true; 1369 1370 /* Stop traversing the hash table. */ 1371 return 0; 1372 } 1373 1374 /* Continue traversing the hash table. */ 1375 return 1; 1376} 1377 1378/* Compare variable *SLOT with the same variable in hash table DATA 1379 and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */ 1380 1381static int 1382dataflow_set_different_2 (void **slot, void *data) 1383{ 1384 htab_t htab = (htab_t) data; 1385 variable var1, var2; 1386 1387 var1 = *(variable *) slot; 1388 var2 = htab_find_with_hash (htab, var1->decl, 1389 VARIABLE_HASH_VAL (var1->decl)); 1390 if (!var2) 1391 { 1392 dataflow_set_different_value = true; 1393 1394 /* Stop traversing the hash table. */ 1395 return 0; 1396 } 1397 1398 /* If both variables are defined they have been already checked for 1399 equivalence. */ 1400 gcc_assert (!variable_different_p (var1, var2, false)); 1401 1402 /* Continue traversing the hash table. */ 1403 return 1; 1404} 1405 1406/* Return true if dataflow sets OLD_SET and NEW_SET differ. */ 1407 1408static bool 1409dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set) 1410{ 1411 dataflow_set_different_value = false; 1412 1413 htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars); 1414 if (!dataflow_set_different_value) 1415 { 1416 /* We have compared the variables which are in both hash tables 1417 so now only check whether there are some variables in NEW_SET->VARS 1418 which are not in OLD_SET->VARS. */ 1419 htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars); 1420 } 1421 return dataflow_set_different_value; 1422} 1423 1424/* Free the contents of dataflow set SET. */ 1425 1426static void 1427dataflow_set_destroy (dataflow_set *set) 1428{ 1429 int i; 1430 1431 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1432 attrs_list_clear (&set->regs[i]); 1433 1434 htab_delete (set->vars); 1435 set->vars = NULL; 1436} 1437 1438/* Return true if RTL X contains a SYMBOL_REF. */ 1439 1440static bool 1441contains_symbol_ref (rtx x) 1442{ 1443 const char *fmt; 1444 RTX_CODE code; 1445 int i; 1446 1447 if (!x) 1448 return false; 1449 1450 code = GET_CODE (x); 1451 if (code == SYMBOL_REF) 1452 return true; 1453 1454 fmt = GET_RTX_FORMAT (code); 1455 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 1456 { 1457 if (fmt[i] == 'e') 1458 { 1459 if (contains_symbol_ref (XEXP (x, i))) 1460 return true; 1461 } 1462 else if (fmt[i] == 'E') 1463 { 1464 int j; 1465 for (j = 0; j < XVECLEN (x, i); j++) 1466 if (contains_symbol_ref (XVECEXP (x, i, j))) 1467 return true; 1468 } 1469 } 1470 1471 return false; 1472} 1473 1474/* Shall EXPR be tracked? */ 1475 1476static bool 1477track_expr_p (tree expr) 1478{ 1479 rtx decl_rtl; 1480 tree realdecl; 1481 1482 /* If EXPR is not a parameter or a variable do not track it. */ 1483 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL) 1484 return 0; 1485 1486 /* It also must have a name... */ 1487 if (!DECL_NAME (expr)) 1488 return 0; 1489 1490 /* ... and a RTL assigned to it. */ 1491 decl_rtl = DECL_RTL_IF_SET (expr); 1492 if (!decl_rtl) 1493 return 0; 1494 1495 /* If this expression is really a debug alias of some other declaration, we 1496 don't need to track this expression if the ultimate declaration is 1497 ignored. */ 1498 realdecl = expr; 1499 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl)) 1500 { 1501 realdecl = DECL_DEBUG_EXPR (realdecl); 1502 /* ??? We don't yet know how to emit DW_OP_piece for variable 1503 that has been SRA'ed. */ 1504 if (!DECL_P (realdecl)) 1505 return 0; 1506 } 1507 1508 /* Do not track EXPR if REALDECL it should be ignored for debugging 1509 purposes. */ 1510 if (DECL_IGNORED_P (realdecl)) 1511 return 0; 1512 1513 /* Do not track global variables until we are able to emit correct location 1514 list for them. */ 1515 if (TREE_STATIC (realdecl)) 1516 return 0; 1517 1518 /* When the EXPR is a DECL for alias of some variable (see example) 1519 the TREE_STATIC flag is not used. Disable tracking all DECLs whose 1520 DECL_RTL contains SYMBOL_REF. 1521 1522 Example: 1523 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv"))); 1524 char **_dl_argv; 1525 */ 1526 if (MEM_P (decl_rtl) 1527 && contains_symbol_ref (XEXP (decl_rtl, 0))) 1528 return 0; 1529 1530 /* If RTX is a memory it should not be very large (because it would be 1531 an array or struct). */ 1532 if (MEM_P (decl_rtl)) 1533 { 1534 /* Do not track structures and arrays. */ 1535 if (GET_MODE (decl_rtl) == BLKmode 1536 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl))) 1537 return 0; 1538 if (MEM_SIZE (decl_rtl) 1539 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS) 1540 return 0; 1541 } 1542 1543 return 1; 1544} 1545 1546/* Return true if OFFSET is a valid offset for a register or memory 1547 access we want to track. This is used to reject out-of-bounds 1548 accesses that can cause assertions to fail later. Note that we 1549 don't reject negative offsets because they can be generated for 1550 paradoxical subregs on big-endian architectures. */ 1551 1552static inline bool 1553offset_valid_for_tracked_p (HOST_WIDE_INT offset) 1554{ 1555 return (-MAX_VAR_PARTS < offset) && (offset < MAX_VAR_PARTS); 1556} 1557 1558/* Determine whether a given LOC refers to the same variable part as 1559 EXPR+OFFSET. */ 1560 1561static bool 1562same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) 1563{ 1564 tree expr2; 1565 HOST_WIDE_INT offset2; 1566 1567 if (! DECL_P (expr)) 1568 return false; 1569 1570 if (REG_P (loc)) 1571 { 1572 expr2 = REG_EXPR (loc); 1573 offset2 = REG_OFFSET (loc); 1574 } 1575 else if (MEM_P (loc)) 1576 { 1577 expr2 = MEM_EXPR (loc); 1578 offset2 = INT_MEM_OFFSET (loc); 1579 } 1580 else 1581 return false; 1582 1583 if (! expr2 || ! DECL_P (expr2)) 1584 return false; 1585 1586 expr = var_debug_decl (expr); 1587 expr2 = var_debug_decl (expr2); 1588 1589 return (expr == expr2 && offset == offset2); 1590} 1591 1592 1593/* Count uses (register and memory references) LOC which will be tracked. 1594 INSN is instruction which the LOC is part of. */ 1595 1596static int 1597count_uses (rtx *loc, void *insn) 1598{ 1599 basic_block bb = BLOCK_FOR_INSN ((rtx) insn); 1600 1601 if (REG_P (*loc)) 1602 { 1603 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER); 1604 VTI (bb)->n_mos++; 1605 } 1606 else if (MEM_P (*loc) 1607 && MEM_EXPR (*loc) 1608 && track_expr_p (MEM_EXPR (*loc)) 1609 && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc))) 1610 { 1611 VTI (bb)->n_mos++; 1612 } 1613 1614 return 0; 1615} 1616 1617/* Helper function for finding all uses of REG/MEM in X in insn INSN. */ 1618 1619static void 1620count_uses_1 (rtx *x, void *insn) 1621{ 1622 for_each_rtx (x, count_uses, insn); 1623} 1624 1625/* Count stores (register and memory references) LOC which will be tracked. 1626 INSN is instruction which the LOC is part of. */ 1627 1628static void 1629count_stores (rtx loc, rtx expr ATTRIBUTE_UNUSED, void *insn) 1630{ 1631 count_uses (&loc, insn); 1632} 1633 1634/* Add uses (register and memory references) LOC which will be tracked 1635 to VTI (bb)->mos. INSN is instruction which the LOC is part of. */ 1636 1637static int 1638add_uses (rtx *loc, void *insn) 1639{ 1640 if (REG_P (*loc)) 1641 { 1642 basic_block bb = BLOCK_FOR_INSN ((rtx) insn); 1643 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 1644 1645 if (REG_EXPR (*loc) 1646 && track_expr_p (REG_EXPR (*loc)) 1647 && offset_valid_for_tracked_p (REG_OFFSET (*loc))) 1648 mo->type = MO_USE; 1649 else 1650 mo->type = MO_USE_NO_VAR; 1651 mo->u.loc = *loc; 1652 mo->insn = (rtx) insn; 1653 } 1654 else if (MEM_P (*loc) 1655 && MEM_EXPR (*loc) 1656 && track_expr_p (MEM_EXPR (*loc)) 1657 && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc))) 1658 { 1659 basic_block bb = BLOCK_FOR_INSN ((rtx) insn); 1660 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 1661 1662 mo->type = MO_USE; 1663 mo->u.loc = *loc; 1664 mo->insn = (rtx) insn; 1665 } 1666 1667 return 0; 1668} 1669 1670/* Helper function for finding all uses of REG/MEM in X in insn INSN. */ 1671 1672static void 1673add_uses_1 (rtx *x, void *insn) 1674{ 1675 for_each_rtx (x, add_uses, insn); 1676} 1677 1678/* Add stores (register and memory references) LOC which will be tracked 1679 to VTI (bb)->mos. EXPR is the RTL expression containing the store. 1680 INSN is instruction which the LOC is part of. */ 1681 1682static void 1683add_stores (rtx loc, rtx expr, void *insn) 1684{ 1685 if (REG_P (loc)) 1686 { 1687 basic_block bb = BLOCK_FOR_INSN ((rtx) insn); 1688 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 1689 1690 if (GET_CODE (expr) == CLOBBER 1691 || !(REG_EXPR (loc) 1692 && track_expr_p (REG_EXPR (loc)) 1693 && offset_valid_for_tracked_p (REG_OFFSET (loc)))) 1694 mo->type = MO_CLOBBER; 1695 else if (GET_CODE (expr) == SET 1696 && SET_DEST (expr) == loc 1697 && same_variable_part_p (SET_SRC (expr), 1698 REG_EXPR (loc), 1699 REG_OFFSET (loc))) 1700 mo->type = MO_COPY; 1701 else 1702 mo->type = MO_SET; 1703 mo->u.loc = loc; 1704 mo->insn = NEXT_INSN ((rtx) insn); 1705 } 1706 else if (MEM_P (loc) 1707 && MEM_EXPR (loc) 1708 && track_expr_p (MEM_EXPR (loc)) 1709 && offset_valid_for_tracked_p (INT_MEM_OFFSET (loc))) 1710 { 1711 basic_block bb = BLOCK_FOR_INSN ((rtx) insn); 1712 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 1713 1714 if (GET_CODE (expr) == CLOBBER) 1715 mo->type = MO_CLOBBER; 1716 else if (GET_CODE (expr) == SET 1717 && SET_DEST (expr) == loc 1718 && same_variable_part_p (SET_SRC (expr), 1719 MEM_EXPR (loc), 1720 INT_MEM_OFFSET (loc))) 1721 mo->type = MO_COPY; 1722 else 1723 mo->type = MO_SET; 1724 mo->u.loc = loc; 1725 mo->insn = NEXT_INSN ((rtx) insn); 1726 } 1727} 1728 1729/* Compute the changes of variable locations in the basic block BB. */ 1730 1731static bool 1732compute_bb_dataflow (basic_block bb) 1733{ 1734 int i, n, r; 1735 bool changed; 1736 dataflow_set old_out; 1737 dataflow_set *in = &VTI (bb)->in; 1738 dataflow_set *out = &VTI (bb)->out; 1739 1740 dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3); 1741 dataflow_set_copy (&old_out, out); 1742 dataflow_set_copy (out, in); 1743 1744 n = VTI (bb)->n_mos; 1745 for (i = 0; i < n; i++) 1746 { 1747 switch (VTI (bb)->mos[i].type) 1748 { 1749 case MO_CALL: 1750 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1751 if (TEST_HARD_REG_BIT (call_used_reg_set, r)) 1752 var_regno_delete (out, r); 1753 break; 1754 1755 case MO_USE: 1756 { 1757 rtx loc = VTI (bb)->mos[i].u.loc; 1758 1759 if (GET_CODE (loc) == REG) 1760 var_reg_set (out, loc); 1761 else if (GET_CODE (loc) == MEM) 1762 var_mem_set (out, loc); 1763 } 1764 break; 1765 1766 case MO_SET: 1767 { 1768 rtx loc = VTI (bb)->mos[i].u.loc; 1769 1770 if (REG_P (loc)) 1771 var_reg_delete_and_set (out, loc, true); 1772 else if (MEM_P (loc)) 1773 var_mem_delete_and_set (out, loc, true); 1774 } 1775 break; 1776 1777 case MO_COPY: 1778 { 1779 rtx loc = VTI (bb)->mos[i].u.loc; 1780 1781 if (REG_P (loc)) 1782 var_reg_delete_and_set (out, loc, false); 1783 else if (MEM_P (loc)) 1784 var_mem_delete_and_set (out, loc, false); 1785 } 1786 break; 1787 1788 case MO_USE_NO_VAR: 1789 { 1790 rtx loc = VTI (bb)->mos[i].u.loc; 1791 1792 if (REG_P (loc)) 1793 var_reg_delete (out, loc, false); 1794 else if (MEM_P (loc)) 1795 var_mem_delete (out, loc, false); 1796 } 1797 break; 1798 1799 case MO_CLOBBER: 1800 { 1801 rtx loc = VTI (bb)->mos[i].u.loc; 1802 1803 if (REG_P (loc)) 1804 var_reg_delete (out, loc, true); 1805 else if (MEM_P (loc)) 1806 var_mem_delete (out, loc, true); 1807 } 1808 break; 1809 1810 case MO_ADJUST: 1811 out->stack_adjust += VTI (bb)->mos[i].u.adjust; 1812 break; 1813 } 1814 } 1815 1816 changed = dataflow_set_different (&old_out, out); 1817 dataflow_set_destroy (&old_out); 1818 return changed; 1819} 1820 1821/* Find the locations of variables in the whole function. */ 1822 1823static void 1824vt_find_locations (void) 1825{ 1826 fibheap_t worklist, pending, fibheap_swap; 1827 sbitmap visited, in_worklist, in_pending, sbitmap_swap; 1828 basic_block bb; 1829 edge e; 1830 int *bb_order; 1831 int *rc_order; 1832 int i; 1833 1834 /* Compute reverse completion order of depth first search of the CFG 1835 so that the data-flow runs faster. */ 1836 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS); 1837 bb_order = XNEWVEC (int, last_basic_block); 1838 pre_and_rev_post_order_compute (NULL, rc_order, false); 1839 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++) 1840 bb_order[rc_order[i]] = i; 1841 free (rc_order); 1842 1843 worklist = fibheap_new (); 1844 pending = fibheap_new (); 1845 visited = sbitmap_alloc (last_basic_block); 1846 in_worklist = sbitmap_alloc (last_basic_block); 1847 in_pending = sbitmap_alloc (last_basic_block); 1848 sbitmap_zero (in_worklist); 1849 1850 FOR_EACH_BB (bb) 1851 fibheap_insert (pending, bb_order[bb->index], bb); 1852 sbitmap_ones (in_pending); 1853 1854 while (!fibheap_empty (pending)) 1855 { 1856 fibheap_swap = pending; 1857 pending = worklist; 1858 worklist = fibheap_swap; 1859 sbitmap_swap = in_pending; 1860 in_pending = in_worklist; 1861 in_worklist = sbitmap_swap; 1862 1863 sbitmap_zero (visited); 1864 1865 while (!fibheap_empty (worklist)) 1866 { 1867 bb = fibheap_extract_min (worklist); 1868 RESET_BIT (in_worklist, bb->index); 1869 if (!TEST_BIT (visited, bb->index)) 1870 { 1871 bool changed; 1872 edge_iterator ei; 1873 1874 SET_BIT (visited, bb->index); 1875 1876 /* Calculate the IN set as union of predecessor OUT sets. */ 1877 dataflow_set_clear (&VTI (bb)->in); 1878 FOR_EACH_EDGE (e, ei, bb->preds) 1879 { 1880 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out); 1881 } 1882 1883 changed = compute_bb_dataflow (bb); 1884 if (changed) 1885 { 1886 FOR_EACH_EDGE (e, ei, bb->succs) 1887 { 1888 if (e->dest == EXIT_BLOCK_PTR) 1889 continue; 1890 1891 if (e->dest == bb) 1892 continue; 1893 1894 if (TEST_BIT (visited, e->dest->index)) 1895 { 1896 if (!TEST_BIT (in_pending, e->dest->index)) 1897 { 1898 /* Send E->DEST to next round. */ 1899 SET_BIT (in_pending, e->dest->index); 1900 fibheap_insert (pending, 1901 bb_order[e->dest->index], 1902 e->dest); 1903 } 1904 } 1905 else if (!TEST_BIT (in_worklist, e->dest->index)) 1906 { 1907 /* Add E->DEST to current round. */ 1908 SET_BIT (in_worklist, e->dest->index); 1909 fibheap_insert (worklist, bb_order[e->dest->index], 1910 e->dest); 1911 } 1912 } 1913 } 1914 } 1915 } 1916 } 1917 1918 free (bb_order); 1919 fibheap_delete (worklist); 1920 fibheap_delete (pending); 1921 sbitmap_free (visited); 1922 sbitmap_free (in_worklist); 1923 sbitmap_free (in_pending); 1924} 1925 1926/* Print the content of the LIST to dump file. */ 1927 1928static void 1929dump_attrs_list (attrs list) 1930{ 1931 for (; list; list = list->next) 1932 { 1933 print_mem_expr (dump_file, list->decl); 1934 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset); 1935 } 1936 fprintf (dump_file, "\n"); 1937} 1938 1939/* Print the information about variable *SLOT to dump file. */ 1940 1941static int 1942dump_variable (void **slot, void *data ATTRIBUTE_UNUSED) 1943{ 1944 variable var = *(variable *) slot; 1945 int i; 1946 location_chain node; 1947 1948 fprintf (dump_file, " name: %s\n", 1949 IDENTIFIER_POINTER (DECL_NAME (var->decl))); 1950 for (i = 0; i < var->n_var_parts; i++) 1951 { 1952 fprintf (dump_file, " offset %ld\n", 1953 (long) var->var_part[i].offset); 1954 for (node = var->var_part[i].loc_chain; node; node = node->next) 1955 { 1956 fprintf (dump_file, " "); 1957 print_rtl_single (dump_file, node->loc); 1958 } 1959 } 1960 1961 /* Continue traversing the hash table. */ 1962 return 1; 1963} 1964 1965/* Print the information about variables from hash table VARS to dump file. */ 1966 1967static void 1968dump_vars (htab_t vars) 1969{ 1970 if (htab_elements (vars) > 0) 1971 { 1972 fprintf (dump_file, "Variables:\n"); 1973 htab_traverse (vars, dump_variable, NULL); 1974 } 1975} 1976 1977/* Print the dataflow set SET to dump file. */ 1978 1979static void 1980dump_dataflow_set (dataflow_set *set) 1981{ 1982 int i; 1983 1984 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n", 1985 set->stack_adjust); 1986 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1987 { 1988 if (set->regs[i]) 1989 { 1990 fprintf (dump_file, "Reg %d:", i); 1991 dump_attrs_list (set->regs[i]); 1992 } 1993 } 1994 dump_vars (set->vars); 1995 fprintf (dump_file, "\n"); 1996} 1997 1998/* Print the IN and OUT sets for each basic block to dump file. */ 1999 2000static void 2001dump_dataflow_sets (void) 2002{ 2003 basic_block bb; 2004 2005 FOR_EACH_BB (bb) 2006 { 2007 fprintf (dump_file, "\nBasic block %d:\n", bb->index); 2008 fprintf (dump_file, "IN:\n"); 2009 dump_dataflow_set (&VTI (bb)->in); 2010 fprintf (dump_file, "OUT:\n"); 2011 dump_dataflow_set (&VTI (bb)->out); 2012 } 2013} 2014 2015/* Add variable VAR to the hash table of changed variables and 2016 if it has no locations delete it from hash table HTAB. */ 2017 2018static void 2019variable_was_changed (variable var, htab_t htab) 2020{ 2021 hashval_t hash = VARIABLE_HASH_VAL (var->decl); 2022 2023 if (emit_notes) 2024 { 2025 variable *slot; 2026 2027 slot = (variable *) htab_find_slot_with_hash (changed_variables, 2028 var->decl, hash, INSERT); 2029 2030 if (htab && var->n_var_parts == 0) 2031 { 2032 variable empty_var; 2033 void **old; 2034 2035 empty_var = pool_alloc (var_pool); 2036 empty_var->decl = var->decl; 2037 empty_var->refcount = 1; 2038 empty_var->n_var_parts = 0; 2039 *slot = empty_var; 2040 2041 old = htab_find_slot_with_hash (htab, var->decl, hash, 2042 NO_INSERT); 2043 if (old) 2044 htab_clear_slot (htab, old); 2045 } 2046 else 2047 { 2048 *slot = var; 2049 } 2050 } 2051 else 2052 { 2053 gcc_assert (htab); 2054 if (var->n_var_parts == 0) 2055 { 2056 void **slot = htab_find_slot_with_hash (htab, var->decl, hash, 2057 NO_INSERT); 2058 if (slot) 2059 htab_clear_slot (htab, slot); 2060 } 2061 } 2062} 2063 2064/* Look for the index in VAR->var_part corresponding to OFFSET. 2065 Return -1 if not found. If INSERTION_POINT is non-NULL, the 2066 referenced int will be set to the index that the part has or should 2067 have, if it should be inserted. */ 2068 2069static inline int 2070find_variable_location_part (variable var, HOST_WIDE_INT offset, 2071 int *insertion_point) 2072{ 2073 int pos, low, high; 2074 2075 /* Find the location part. */ 2076 low = 0; 2077 high = var->n_var_parts; 2078 while (low != high) 2079 { 2080 pos = (low + high) / 2; 2081 if (var->var_part[pos].offset < offset) 2082 low = pos + 1; 2083 else 2084 high = pos; 2085 } 2086 pos = low; 2087 2088 if (insertion_point) 2089 *insertion_point = pos; 2090 2091 if (pos < var->n_var_parts && var->var_part[pos].offset == offset) 2092 return pos; 2093 2094 return -1; 2095} 2096 2097/* Set the part of variable's location in the dataflow set SET. The variable 2098 part is specified by variable's declaration DECL and offset OFFSET and the 2099 part's location by LOC. */ 2100 2101static void 2102set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) 2103{ 2104 int pos; 2105 location_chain node, next; 2106 location_chain *nextp; 2107 variable var; 2108 void **slot; 2109 2110 slot = htab_find_slot_with_hash (set->vars, decl, 2111 VARIABLE_HASH_VAL (decl), INSERT); 2112 if (!*slot) 2113 { 2114 /* Create new variable information. */ 2115 var = pool_alloc (var_pool); 2116 var->decl = decl; 2117 var->refcount = 1; 2118 var->n_var_parts = 1; 2119 var->var_part[0].offset = offset; 2120 var->var_part[0].loc_chain = NULL; 2121 var->var_part[0].cur_loc = NULL; 2122 *slot = var; 2123 pos = 0; 2124 } 2125 else 2126 { 2127 int inspos = 0; 2128 2129 var = (variable) *slot; 2130 2131 pos = find_variable_location_part (var, offset, &inspos); 2132 2133 if (pos >= 0) 2134 { 2135 node = var->var_part[pos].loc_chain; 2136 2137 if (node 2138 && ((REG_P (node->loc) && REG_P (loc) 2139 && REGNO (node->loc) == REGNO (loc)) 2140 || rtx_equal_p (node->loc, loc))) 2141 { 2142 /* LOC is in the beginning of the chain so we have nothing 2143 to do. */ 2144 return; 2145 } 2146 else 2147 { 2148 /* We have to make a copy of a shared variable. */ 2149 if (var->refcount > 1) 2150 var = unshare_variable (set, var); 2151 } 2152 } 2153 else 2154 { 2155 /* We have not found the location part, new one will be created. */ 2156 2157 /* We have to make a copy of the shared variable. */ 2158 if (var->refcount > 1) 2159 var = unshare_variable (set, var); 2160 2161 /* We track only variables whose size is <= MAX_VAR_PARTS bytes 2162 thus there are at most MAX_VAR_PARTS different offsets. */ 2163 gcc_assert (var->n_var_parts < MAX_VAR_PARTS); 2164 2165 /* We have to move the elements of array starting at index 2166 inspos to the next position. */ 2167 for (pos = var->n_var_parts; pos > inspos; pos--) 2168 var->var_part[pos] = var->var_part[pos - 1]; 2169 2170 var->n_var_parts++; 2171 var->var_part[pos].offset = offset; 2172 var->var_part[pos].loc_chain = NULL; 2173 var->var_part[pos].cur_loc = NULL; 2174 } 2175 } 2176 2177 /* Delete the location from the list. */ 2178 nextp = &var->var_part[pos].loc_chain; 2179 for (node = var->var_part[pos].loc_chain; node; node = next) 2180 { 2181 next = node->next; 2182 if ((REG_P (node->loc) && REG_P (loc) 2183 && REGNO (node->loc) == REGNO (loc)) 2184 || rtx_equal_p (node->loc, loc)) 2185 { 2186 pool_free (loc_chain_pool, node); 2187 *nextp = next; 2188 break; 2189 } 2190 else 2191 nextp = &node->next; 2192 } 2193 2194 /* Add the location to the beginning. */ 2195 node = pool_alloc (loc_chain_pool); 2196 node->loc = loc; 2197 node->next = var->var_part[pos].loc_chain; 2198 var->var_part[pos].loc_chain = node; 2199 2200 /* If no location was emitted do so. */ 2201 if (var->var_part[pos].cur_loc == NULL) 2202 { 2203 var->var_part[pos].cur_loc = loc; 2204 variable_was_changed (var, set->vars); 2205 } 2206} 2207 2208/* Remove all recorded register locations for the given variable part 2209 from dataflow set SET, except for those that are identical to loc. 2210 The variable part is specified by variable's declaration DECL and 2211 offset OFFSET. */ 2212 2213static void 2214clobber_variable_part (dataflow_set *set, rtx loc, tree decl, 2215 HOST_WIDE_INT offset) 2216{ 2217 void **slot; 2218 2219 if (! decl || ! DECL_P (decl)) 2220 return; 2221 2222 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), 2223 NO_INSERT); 2224 if (slot) 2225 { 2226 variable var = (variable) *slot; 2227 int pos = find_variable_location_part (var, offset, NULL); 2228 2229 if (pos >= 0) 2230 { 2231 location_chain node, next; 2232 2233 /* Remove the register locations from the dataflow set. */ 2234 next = var->var_part[pos].loc_chain; 2235 for (node = next; node; node = next) 2236 { 2237 next = node->next; 2238 if (node->loc != loc) 2239 { 2240 if (REG_P (node->loc)) 2241 { 2242 attrs anode, anext; 2243 attrs *anextp; 2244 2245 /* Remove the variable part from the register's 2246 list, but preserve any other variable parts 2247 that might be regarded as live in that same 2248 register. */ 2249 anextp = &set->regs[REGNO (node->loc)]; 2250 for (anode = *anextp; anode; anode = anext) 2251 { 2252 anext = anode->next; 2253 if (anode->decl == decl 2254 && anode->offset == offset) 2255 { 2256 pool_free (attrs_pool, anode); 2257 *anextp = anext; 2258 } 2259 } 2260 } 2261 2262 delete_variable_part (set, node->loc, decl, offset); 2263 } 2264 } 2265 } 2266 } 2267} 2268 2269/* Delete the part of variable's location from dataflow set SET. The variable 2270 part is specified by variable's declaration DECL and offset OFFSET and the 2271 part's location by LOC. */ 2272 2273static void 2274delete_variable_part (dataflow_set *set, rtx loc, tree decl, 2275 HOST_WIDE_INT offset) 2276{ 2277 void **slot; 2278 2279 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), 2280 NO_INSERT); 2281 if (slot) 2282 { 2283 variable var = (variable) *slot; 2284 int pos = find_variable_location_part (var, offset, NULL); 2285 2286 if (pos >= 0) 2287 { 2288 location_chain node, next; 2289 location_chain *nextp; 2290 bool changed; 2291 2292 if (var->refcount > 1) 2293 { 2294 /* If the variable contains the location part we have to 2295 make a copy of the variable. */ 2296 for (node = var->var_part[pos].loc_chain; node; 2297 node = node->next) 2298 { 2299 if ((REG_P (node->loc) && REG_P (loc) 2300 && REGNO (node->loc) == REGNO (loc)) 2301 || rtx_equal_p (node->loc, loc)) 2302 { 2303 var = unshare_variable (set, var); 2304 break; 2305 } 2306 } 2307 } 2308 2309 /* Delete the location part. */ 2310 nextp = &var->var_part[pos].loc_chain; 2311 for (node = *nextp; node; node = next) 2312 { 2313 next = node->next; 2314 if ((REG_P (node->loc) && REG_P (loc) 2315 && REGNO (node->loc) == REGNO (loc)) 2316 || rtx_equal_p (node->loc, loc)) 2317 { 2318 pool_free (loc_chain_pool, node); 2319 *nextp = next; 2320 break; 2321 } 2322 else 2323 nextp = &node->next; 2324 } 2325 2326 /* If we have deleted the location which was last emitted 2327 we have to emit new location so add the variable to set 2328 of changed variables. */ 2329 if (var->var_part[pos].cur_loc 2330 && ((REG_P (loc) 2331 && REG_P (var->var_part[pos].cur_loc) 2332 && REGNO (loc) == REGNO (var->var_part[pos].cur_loc)) 2333 || rtx_equal_p (loc, var->var_part[pos].cur_loc))) 2334 { 2335 changed = true; 2336 if (var->var_part[pos].loc_chain) 2337 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc; 2338 } 2339 else 2340 changed = false; 2341 2342 if (var->var_part[pos].loc_chain == NULL) 2343 { 2344 var->n_var_parts--; 2345 while (pos < var->n_var_parts) 2346 { 2347 var->var_part[pos] = var->var_part[pos + 1]; 2348 pos++; 2349 } 2350 } 2351 if (changed) 2352 variable_was_changed (var, set->vars); 2353 } 2354 } 2355} 2356 2357/* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains 2358 additional parameters: WHERE specifies whether the note shall be emitted 2359 before of after instruction INSN. */ 2360 2361static int 2362emit_note_insn_var_location (void **varp, void *data) 2363{ 2364 variable var = *(variable *) varp; 2365 rtx insn = ((emit_note_data *)data)->insn; 2366 enum emit_note_where where = ((emit_note_data *)data)->where; 2367 rtx note; 2368 int i, j, n_var_parts; 2369 bool complete; 2370 HOST_WIDE_INT last_limit; 2371 tree type_size_unit; 2372 HOST_WIDE_INT offsets[MAX_VAR_PARTS]; 2373 rtx loc[MAX_VAR_PARTS]; 2374 2375 gcc_assert (var->decl); 2376 2377 complete = true; 2378 last_limit = 0; 2379 n_var_parts = 0; 2380 for (i = 0; i < var->n_var_parts; i++) 2381 { 2382 enum machine_mode mode, wider_mode; 2383 2384 if (last_limit < var->var_part[i].offset) 2385 { 2386 complete = false; 2387 break; 2388 } 2389 else if (last_limit > var->var_part[i].offset) 2390 continue; 2391 offsets[n_var_parts] = var->var_part[i].offset; 2392 loc[n_var_parts] = var->var_part[i].loc_chain->loc; 2393 mode = GET_MODE (loc[n_var_parts]); 2394 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); 2395 2396 /* Attempt to merge adjacent registers or memory. */ 2397 wider_mode = GET_MODE_WIDER_MODE (mode); 2398 for (j = i + 1; j < var->n_var_parts; j++) 2399 if (last_limit <= var->var_part[j].offset) 2400 break; 2401 if (j < var->n_var_parts 2402 && wider_mode != VOIDmode 2403 && GET_CODE (loc[n_var_parts]) 2404 == GET_CODE (var->var_part[j].loc_chain->loc) 2405 && mode == GET_MODE (var->var_part[j].loc_chain->loc) 2406 && last_limit == var->var_part[j].offset) 2407 { 2408 rtx new_loc = NULL; 2409 rtx loc2 = var->var_part[j].loc_chain->loc; 2410 2411 if (REG_P (loc[n_var_parts]) 2412 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2 2413 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode] 2414 && REGNO (loc[n_var_parts]) 2415 + hard_regno_nregs[REGNO (loc[n_var_parts])][mode] 2416 == REGNO (loc2)) 2417 { 2418 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) 2419 new_loc = simplify_subreg (wider_mode, loc[n_var_parts], 2420 mode, 0); 2421 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN) 2422 new_loc = simplify_subreg (wider_mode, loc2, mode, 0); 2423 if (new_loc) 2424 { 2425 if (!REG_P (new_loc) 2426 || REGNO (new_loc) != REGNO (loc[n_var_parts])) 2427 new_loc = NULL; 2428 else 2429 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); 2430 } 2431 } 2432 else if (MEM_P (loc[n_var_parts]) 2433 && GET_CODE (XEXP (loc2, 0)) == PLUS 2434 && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG 2435 && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT) 2436 { 2437 if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG 2438 && rtx_equal_p (XEXP (loc[n_var_parts], 0), 2439 XEXP (XEXP (loc2, 0), 0)) 2440 && INTVAL (XEXP (XEXP (loc2, 0), 1)) 2441 == GET_MODE_SIZE (mode)) 2442 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS 2443 && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1)) 2444 == CONST_INT 2445 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0), 2446 XEXP (XEXP (loc2, 0), 0)) 2447 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1)) 2448 + GET_MODE_SIZE (mode) 2449 == INTVAL (XEXP (XEXP (loc2, 0), 1)))) 2450 new_loc = adjust_address_nv (loc[n_var_parts], 2451 wider_mode, 0); 2452 } 2453 2454 if (new_loc) 2455 { 2456 loc[n_var_parts] = new_loc; 2457 mode = wider_mode; 2458 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); 2459 i = j; 2460 } 2461 } 2462 ++n_var_parts; 2463 } 2464 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl)); 2465 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) 2466 complete = false; 2467 2468 if (where == EMIT_NOTE_AFTER_INSN) 2469 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); 2470 else 2471 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); 2472 2473 if (!complete) 2474 { 2475 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, 2476 NULL_RTX); 2477 } 2478 else if (n_var_parts == 1) 2479 { 2480 rtx expr_list 2481 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); 2482 2483 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, 2484 expr_list); 2485 } 2486 else if (n_var_parts) 2487 { 2488 rtx parallel; 2489 2490 for (i = 0; i < n_var_parts; i++) 2491 loc[i] 2492 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); 2493 2494 parallel = gen_rtx_PARALLEL (VOIDmode, 2495 gen_rtvec_v (n_var_parts, loc)); 2496 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, 2497 parallel); 2498 } 2499 2500 htab_clear_slot (changed_variables, varp); 2501 2502 /* When there are no location parts the variable has been already 2503 removed from hash table and a new empty variable was created. 2504 Free the empty variable. */ 2505 if (var->n_var_parts == 0) 2506 { 2507 pool_free (var_pool, var); 2508 } 2509 2510 /* Continue traversing the hash table. */ 2511 return 1; 2512} 2513 2514/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain 2515 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes 2516 shall be emitted before of after instruction INSN. */ 2517 2518static void 2519emit_notes_for_changes (rtx insn, enum emit_note_where where) 2520{ 2521 emit_note_data data; 2522 2523 data.insn = insn; 2524 data.where = where; 2525 htab_traverse (changed_variables, emit_note_insn_var_location, &data); 2526} 2527 2528/* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the 2529 same variable in hash table DATA or is not there at all. */ 2530 2531static int 2532emit_notes_for_differences_1 (void **slot, void *data) 2533{ 2534 htab_t new_vars = (htab_t) data; 2535 variable old_var, new_var; 2536 2537 old_var = *(variable *) slot; 2538 new_var = htab_find_with_hash (new_vars, old_var->decl, 2539 VARIABLE_HASH_VAL (old_var->decl)); 2540 2541 if (!new_var) 2542 { 2543 /* Variable has disappeared. */ 2544 variable empty_var; 2545 2546 empty_var = pool_alloc (var_pool); 2547 empty_var->decl = old_var->decl; 2548 empty_var->refcount = 1; 2549 empty_var->n_var_parts = 0; 2550 variable_was_changed (empty_var, NULL); 2551 } 2552 else if (variable_different_p (old_var, new_var, true)) 2553 { 2554 variable_was_changed (new_var, NULL); 2555 } 2556 2557 /* Continue traversing the hash table. */ 2558 return 1; 2559} 2560 2561/* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash 2562 table DATA. */ 2563 2564static int 2565emit_notes_for_differences_2 (void **slot, void *data) 2566{ 2567 htab_t old_vars = (htab_t) data; 2568 variable old_var, new_var; 2569 2570 new_var = *(variable *) slot; 2571 old_var = htab_find_with_hash (old_vars, new_var->decl, 2572 VARIABLE_HASH_VAL (new_var->decl)); 2573 if (!old_var) 2574 { 2575 /* Variable has appeared. */ 2576 variable_was_changed (new_var, NULL); 2577 } 2578 2579 /* Continue traversing the hash table. */ 2580 return 1; 2581} 2582 2583/* Emit notes before INSN for differences between dataflow sets OLD_SET and 2584 NEW_SET. */ 2585 2586static void 2587emit_notes_for_differences (rtx insn, dataflow_set *old_set, 2588 dataflow_set *new_set) 2589{ 2590 htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars); 2591 htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars); 2592 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); 2593} 2594 2595/* Emit the notes for changes of location parts in the basic block BB. */ 2596 2597static void 2598emit_notes_in_bb (basic_block bb) 2599{ 2600 int i; 2601 dataflow_set set; 2602 2603 dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3); 2604 dataflow_set_copy (&set, &VTI (bb)->in); 2605 2606 for (i = 0; i < VTI (bb)->n_mos; i++) 2607 { 2608 rtx insn = VTI (bb)->mos[i].insn; 2609 2610 switch (VTI (bb)->mos[i].type) 2611 { 2612 case MO_CALL: 2613 { 2614 int r; 2615 2616 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 2617 if (TEST_HARD_REG_BIT (call_used_reg_set, r)) 2618 { 2619 var_regno_delete (&set, r); 2620 } 2621 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); 2622 } 2623 break; 2624 2625 case MO_USE: 2626 { 2627 rtx loc = VTI (bb)->mos[i].u.loc; 2628 2629 if (GET_CODE (loc) == REG) 2630 var_reg_set (&set, loc); 2631 else 2632 var_mem_set (&set, loc); 2633 2634 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); 2635 } 2636 break; 2637 2638 case MO_SET: 2639 { 2640 rtx loc = VTI (bb)->mos[i].u.loc; 2641 2642 if (REG_P (loc)) 2643 var_reg_delete_and_set (&set, loc, true); 2644 else 2645 var_mem_delete_and_set (&set, loc, true); 2646 2647 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); 2648 } 2649 break; 2650 2651 case MO_COPY: 2652 { 2653 rtx loc = VTI (bb)->mos[i].u.loc; 2654 2655 if (REG_P (loc)) 2656 var_reg_delete_and_set (&set, loc, false); 2657 else 2658 var_mem_delete_and_set (&set, loc, false); 2659 2660 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); 2661 } 2662 break; 2663 2664 case MO_USE_NO_VAR: 2665 { 2666 rtx loc = VTI (bb)->mos[i].u.loc; 2667 2668 if (REG_P (loc)) 2669 var_reg_delete (&set, loc, false); 2670 else 2671 var_mem_delete (&set, loc, false); 2672 2673 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); 2674 } 2675 break; 2676 2677 case MO_CLOBBER: 2678 { 2679 rtx loc = VTI (bb)->mos[i].u.loc; 2680 2681 if (REG_P (loc)) 2682 var_reg_delete (&set, loc, true); 2683 else 2684 var_mem_delete (&set, loc, true); 2685 2686 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); 2687 } 2688 break; 2689 2690 case MO_ADJUST: 2691 set.stack_adjust += VTI (bb)->mos[i].u.adjust; 2692 break; 2693 } 2694 } 2695 dataflow_set_destroy (&set); 2696} 2697 2698/* Emit notes for the whole function. */ 2699 2700static void 2701vt_emit_notes (void) 2702{ 2703 basic_block bb; 2704 dataflow_set *last_out; 2705 dataflow_set empty; 2706 2707 gcc_assert (!htab_elements (changed_variables)); 2708 2709 /* Enable emitting notes by functions (mainly by set_variable_part and 2710 delete_variable_part). */ 2711 emit_notes = true; 2712 2713 dataflow_set_init (&empty, 7); 2714 last_out = ∅ 2715 2716 FOR_EACH_BB (bb) 2717 { 2718 /* Emit the notes for changes of variable locations between two 2719 subsequent basic blocks. */ 2720 emit_notes_for_differences (BB_HEAD (bb), last_out, &VTI (bb)->in); 2721 2722 /* Emit the notes for the changes in the basic block itself. */ 2723 emit_notes_in_bb (bb); 2724 2725 last_out = &VTI (bb)->out; 2726 } 2727 dataflow_set_destroy (&empty); 2728 emit_notes = false; 2729} 2730 2731/* If there is a declaration and offset associated with register/memory RTL 2732 assign declaration to *DECLP and offset to *OFFSETP, and return true. */ 2733 2734static bool 2735vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) 2736{ 2737 if (REG_P (rtl)) 2738 { 2739 if (REG_ATTRS (rtl)) 2740 { 2741 *declp = REG_EXPR (rtl); 2742 *offsetp = REG_OFFSET (rtl); 2743 return true; 2744 } 2745 } 2746 else if (MEM_P (rtl)) 2747 { 2748 if (MEM_ATTRS (rtl)) 2749 { 2750 *declp = MEM_EXPR (rtl); 2751 *offsetp = INT_MEM_OFFSET (rtl); 2752 return true; 2753 } 2754 } 2755 return false; 2756} 2757 2758/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */ 2759 2760static void 2761vt_add_function_parameters (void) 2762{ 2763 tree parm; 2764 2765 for (parm = DECL_ARGUMENTS (current_function_decl); 2766 parm; parm = TREE_CHAIN (parm)) 2767 { 2768 rtx decl_rtl = DECL_RTL_IF_SET (parm); 2769 rtx incoming = DECL_INCOMING_RTL (parm); 2770 tree decl; 2771 HOST_WIDE_INT offset; 2772 dataflow_set *out; 2773 2774 if (TREE_CODE (parm) != PARM_DECL) 2775 continue; 2776 2777 if (!DECL_NAME (parm)) 2778 continue; 2779 2780 if (!decl_rtl || !incoming) 2781 continue; 2782 2783 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) 2784 continue; 2785 2786 if (!vt_get_decl_and_offset (incoming, &decl, &offset)) 2787 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) 2788 continue; 2789 2790 if (!decl) 2791 continue; 2792 2793 gcc_assert (parm == decl); 2794 2795 out = &VTI (ENTRY_BLOCK_PTR)->out; 2796 2797 if (REG_P (incoming)) 2798 { 2799 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); 2800 attrs_list_insert (&out->regs[REGNO (incoming)], 2801 parm, offset, incoming); 2802 set_variable_part (out, incoming, parm, offset); 2803 } 2804 else if (MEM_P (incoming)) 2805 set_variable_part (out, incoming, parm, offset); 2806 } 2807} 2808 2809/* Allocate and initialize the data structures for variable tracking 2810 and parse the RTL to get the micro operations. */ 2811 2812static void 2813vt_initialize (void) 2814{ 2815 basic_block bb; 2816 2817 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def)); 2818 2819 FOR_EACH_BB (bb) 2820 { 2821 rtx insn; 2822 HOST_WIDE_INT pre, post = 0; 2823 2824 /* Count the number of micro operations. */ 2825 VTI (bb)->n_mos = 0; 2826 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); 2827 insn = NEXT_INSN (insn)) 2828 { 2829 if (INSN_P (insn)) 2830 { 2831 if (!frame_pointer_needed) 2832 { 2833 insn_stack_adjust_offset_pre_post (insn, &pre, &post); 2834 if (pre) 2835 VTI (bb)->n_mos++; 2836 if (post) 2837 VTI (bb)->n_mos++; 2838 } 2839 note_uses (&PATTERN (insn), count_uses_1, insn); 2840 note_stores (PATTERN (insn), count_stores, insn); 2841 if (CALL_P (insn)) 2842 VTI (bb)->n_mos++; 2843 } 2844 } 2845 2846 /* Add the micro-operations to the array. */ 2847 VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos); 2848 VTI (bb)->n_mos = 0; 2849 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); 2850 insn = NEXT_INSN (insn)) 2851 { 2852 if (INSN_P (insn)) 2853 { 2854 int n1, n2; 2855 2856 if (!frame_pointer_needed) 2857 { 2858 insn_stack_adjust_offset_pre_post (insn, &pre, &post); 2859 if (pre) 2860 { 2861 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 2862 2863 mo->type = MO_ADJUST; 2864 mo->u.adjust = pre; 2865 mo->insn = insn; 2866 } 2867 } 2868 2869 n1 = VTI (bb)->n_mos; 2870 note_uses (&PATTERN (insn), add_uses_1, insn); 2871 n2 = VTI (bb)->n_mos - 1; 2872 2873 /* Order the MO_USEs to be before MO_USE_NO_VARs. */ 2874 while (n1 < n2) 2875 { 2876 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE) 2877 n1++; 2878 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR) 2879 n2--; 2880 if (n1 < n2) 2881 { 2882 micro_operation sw; 2883 2884 sw = VTI (bb)->mos[n1]; 2885 VTI (bb)->mos[n1] = VTI (bb)->mos[n2]; 2886 VTI (bb)->mos[n2] = sw; 2887 } 2888 } 2889 2890 if (CALL_P (insn)) 2891 { 2892 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 2893 2894 mo->type = MO_CALL; 2895 mo->insn = insn; 2896 } 2897 2898 n1 = VTI (bb)->n_mos; 2899 /* This will record NEXT_INSN (insn), such that we can 2900 insert notes before it without worrying about any 2901 notes that MO_USEs might emit after the insn. */ 2902 note_stores (PATTERN (insn), add_stores, insn); 2903 n2 = VTI (bb)->n_mos - 1; 2904 2905 /* Order the MO_CLOBBERs to be before MO_SETs. */ 2906 while (n1 < n2) 2907 { 2908 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER) 2909 n1++; 2910 while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET 2911 || VTI (bb)->mos[n2].type == MO_COPY)) 2912 n2--; 2913 if (n1 < n2) 2914 { 2915 micro_operation sw; 2916 2917 sw = VTI (bb)->mos[n1]; 2918 VTI (bb)->mos[n1] = VTI (bb)->mos[n2]; 2919 VTI (bb)->mos[n2] = sw; 2920 } 2921 } 2922 2923 if (!frame_pointer_needed && post) 2924 { 2925 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; 2926 2927 mo->type = MO_ADJUST; 2928 mo->u.adjust = post; 2929 mo->insn = insn; 2930 } 2931 } 2932 } 2933 } 2934 2935 /* Init the IN and OUT sets. */ 2936 FOR_ALL_BB (bb) 2937 { 2938 VTI (bb)->visited = false; 2939 dataflow_set_init (&VTI (bb)->in, 7); 2940 dataflow_set_init (&VTI (bb)->out, 7); 2941 } 2942 2943 attrs_pool = create_alloc_pool ("attrs_def pool", 2944 sizeof (struct attrs_def), 1024); 2945 var_pool = create_alloc_pool ("variable_def pool", 2946 sizeof (struct variable_def), 64); 2947 loc_chain_pool = create_alloc_pool ("location_chain_def pool", 2948 sizeof (struct location_chain_def), 2949 1024); 2950 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, 2951 NULL); 2952 vt_add_function_parameters (); 2953} 2954 2955/* Free the data structures needed for variable tracking. */ 2956 2957static void 2958vt_finalize (void) 2959{ 2960 basic_block bb; 2961 2962 FOR_EACH_BB (bb) 2963 { 2964 free (VTI (bb)->mos); 2965 } 2966 2967 FOR_ALL_BB (bb) 2968 { 2969 dataflow_set_destroy (&VTI (bb)->in); 2970 dataflow_set_destroy (&VTI (bb)->out); 2971 } 2972 free_aux_for_blocks (); 2973 free_alloc_pool (attrs_pool); 2974 free_alloc_pool (var_pool); 2975 free_alloc_pool (loc_chain_pool); 2976 htab_delete (changed_variables); 2977} 2978 2979/* The entry point to variable tracking pass. */ 2980 2981unsigned int 2982variable_tracking_main (void) 2983{ 2984 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20) 2985 return 0; 2986 2987 mark_dfs_back_edges (); 2988 vt_initialize (); 2989 if (!frame_pointer_needed) 2990 { 2991 if (!vt_stack_adjustments ()) 2992 { 2993 vt_finalize (); 2994 return 0; 2995 } 2996 } 2997 2998 vt_find_locations (); 2999 vt_emit_notes (); 3000 3001 if (dump_file && (dump_flags & TDF_DETAILS)) 3002 { 3003 dump_dataflow_sets (); 3004 dump_flow_info (dump_file, dump_flags); 3005 } 3006 3007 vt_finalize (); 3008 return 0; 3009} 3010 3011static bool 3012gate_handle_var_tracking (void) 3013{ 3014 return (flag_var_tracking); 3015} 3016 3017 3018 3019struct tree_opt_pass pass_variable_tracking = 3020{ 3021 "vartrack", /* name */ 3022 gate_handle_var_tracking, /* gate */ 3023 variable_tracking_main, /* execute */ 3024 NULL, /* sub */ 3025 NULL, /* next */ 3026 0, /* static_pass_number */ 3027 TV_VAR_TRACKING, /* tv_id */ 3028 0, /* properties_required */ 3029 0, /* properties_provided */ 3030 0, /* properties_destroyed */ 3031 0, /* todo_flags_start */ 3032 TODO_dump_func, /* todo_flags_finish */ 3033 'V' /* letter */ 3034}; 3035 3036