1/* Variable tracking routines for the GNU compiler. 2 Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 3 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 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. 11 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. 16 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/>. */ 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#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" 117 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. */ 123extern char check_value_val[(int) VALUE == (int) IDENTIFIER_NODE ? 1 : -1]; 124 125/* Type of micro operation. */ 126enum micro_operation_type 127{ 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. */ 140 141}; 142 143static const char * const ATTRIBUTE_UNUSED 144micro_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" 155}; 156 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. */ 160enum emit_note_where 161{ 162 EMIT_NOTE_BEFORE_INSN, 163 EMIT_NOTE_AFTER_INSN, 164 EMIT_NOTE_AFTER_CALL_INSN 165}; 166 167/* Structure holding information about micro operation. */ 168typedef struct micro_operation_def 169{ 170 /* Type of micro operation. */ 171 enum micro_operation_type type; 172 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; 179 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; 188 189 /* Stack adjustment. */ 190 HOST_WIDE_INT adjust; 191 } u; 192} micro_operation; 193 194DEF_VEC_O(micro_operation); 195DEF_VEC_ALLOC_O(micro_operation,heap); 196 197/* A declaration of a variable, or an RTL value being handled like a 198 declaration. */ 199typedef void *decl_or_value; 200 201/* Structure for passing some other parameters to function 202 emit_note_insn_var_location. */ 203typedef struct emit_note_data_def 204{ 205 /* The instruction which the note will be emitted before/after. */ 206 rtx insn; 207 208 /* Where the note will be emitted (before/after insn)? */ 209 enum emit_note_where where; 210 211 /* The variables and values active at this point. */ 212 htab_t vars; 213} emit_note_data; 214 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. */ 219typedef struct attrs_def 220{ 221 /* Pointer to next member of the list. */ 222 struct attrs_def *next; 223 224 /* The rtx of register. */ 225 rtx loc; 226 227 /* The declaration corresponding to LOC. */ 228 decl_or_value dv; 229 230 /* Offset from start of DECL. */ 231 HOST_WIDE_INT offset; 232} *attrs; 233 234/* Structure holding a refcounted hash table. If refcount > 1, 235 it must be first unshared before modified. */ 236typedef struct shared_hash_def 237{ 238 /* Reference count. */ 239 int refcount; 240 241 /* Actual hash table. */ 242 htab_t htab; 243} *shared_hash; 244 245/* Structure holding the IN or OUT set for a basic block. */ 246typedef struct dataflow_set_def 247{ 248 /* Adjustment of stack offset. */ 249 HOST_WIDE_INT stack_adjust; 250 251 /* Attributes for registers (lists of attrs). */ 252 attrs regs[FIRST_PSEUDO_REGISTER]; 253 254 /* Variable locations. */ 255 shared_hash vars; 256 257 /* Vars that is being traversed. */ 258 shared_hash traversed_vars; 259} dataflow_set; 260 261/* The structure (one for each basic block) containing the information 262 needed for variable tracking. */ 263typedef struct variable_tracking_info_def 264{ 265 /* The vector of micro operations. */ 266 VEC(micro_operation, heap) *mos; 267 268 /* The IN and OUT set for dataflow analysis. */ 269 dataflow_set in; 270 dataflow_set out; 271 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; 277 278 /* Has the block been visited in DFS? */ 279 bool visited; 280 281 /* Has the block been flooded in VTA? */ 282 bool flooded; 283 284} *variable_tracking_info; 285 286/* Structure for chaining the locations. */ 287typedef struct location_chain_def 288{ 289 /* Next element in the chain. */ 290 struct location_chain_def *next; 291 292 /* The location (REG, MEM or VALUE). */ 293 rtx loc; 294 295 /* The "value" stored in this location. */ 296 rtx set_src; 297 298 /* Initialized? */ 299 enum var_init_status init; 300} *location_chain; 301 302/* Structure describing one part of variable. */ 303typedef struct variable_part_def 304{ 305 /* Chain of locations of the part. */ 306 location_chain loc_chain; 307 308 /* Location which was last emitted to location list. */ 309 rtx cur_loc; 310 311 /* The offset in the variable. */ 312 HOST_WIDE_INT offset; 313} variable_part; 314 315/* Maximum number of location parts. */ 316#define MAX_VAR_PARTS 16 317 318/* Structure describing where the variable is located. */ 319typedef struct variable_def 320{ 321 /* The declaration of the variable, or an RTL value being handled 322 like a declaration. */ 323 decl_or_value dv; 324 325 /* Reference count. */ 326 int refcount; 327 328 /* Number of variable parts. */ 329 char n_var_parts; 330 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; 335 336 /* True if this variable_def struct is currently in the 337 changed_variables hash table. */ 338 bool in_changed_variables; 339 340 /* The variable parts. */ 341 variable_part var_part[1]; 342} *variable; 343typedef const struct variable_def *const_variable; 344 345/* Structure for chaining backlinks from referenced VALUEs to 346 DVs that are referencing them. */ 347typedef struct value_chain_def 348{ 349 /* Next value_chain entry. */ 350 struct value_chain_def *next; 351 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; 356 357 /* Reference count. */ 358 int refcount; 359} *value_chain; 360typedef const struct value_chain_def *const_value_chain; 361 362/* Pointer to the BB's information specific to variable tracking pass. */ 363#define VTI(BB) ((variable_tracking_info) (BB)->aux) 364 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) 367 368/* Alloc pool for struct attrs_def. */ 369static alloc_pool attrs_pool; 370 371/* Alloc pool for struct variable_def with MAX_VAR_PARTS entries. */ 372static alloc_pool var_pool; 373 374/* Alloc pool for struct variable_def with a single var_part entry. */ 375static alloc_pool valvar_pool; 376 377/* Alloc pool for struct location_chain_def. */ 378static alloc_pool loc_chain_pool; 379 380/* Alloc pool for struct shared_hash_def. */ 381static alloc_pool shared_hash_pool; 382 383/* Alloc pool for struct value_chain_def. */ 384static alloc_pool value_chain_pool; 385 386/* Changed variables, notes will be emitted for them. */ 387static htab_t changed_variables; 388 389/* Links from VALUEs to DVs referencing them in their current loc_chains. */ 390static htab_t value_chains; 391 392/* Shall notes be emitted? */ 393static bool emit_notes; 394 395/* Empty shared hashtable. */ 396static shared_hash empty_shared_hash; 397 398/* Scratch register bitmap used by cselib_expand_value_rtx. */ 399static bitmap scratch_regs = NULL; 400 401/* Variable used to tell whether cselib_process_insn called our hook. */ 402static bool cselib_hook_called; 403 404/* Local function prototypes. */ 405static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, 406 HOST_WIDE_INT *); 407static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, 408 HOST_WIDE_INT *); 409static bool vt_stack_adjustments (void); 410static rtx compute_cfa_pointer (HOST_WIDE_INT); 411static hashval_t variable_htab_hash (const void *); 412static int variable_htab_eq (const void *, const void *); 413static void variable_htab_free (void *); 414 415static void init_attrs_list_set (attrs *); 416static void attrs_list_clear (attrs *); 417static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT); 418static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx); 419static void attrs_list_copy (attrs *, attrs); 420static void attrs_list_union (attrs *, attrs); 421 422static void **unshare_variable (dataflow_set *set, void **slot, variable var, 423 enum var_init_status); 424static void vars_copy (htab_t, htab_t); 425static tree var_debug_decl (tree); 426static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx); 427static void var_reg_delete_and_set (dataflow_set *, rtx, bool, 428 enum var_init_status, rtx); 429static void var_reg_delete (dataflow_set *, rtx, bool); 430static void var_regno_delete (dataflow_set *, int); 431static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx); 432static void var_mem_delete_and_set (dataflow_set *, rtx, bool, 433 enum var_init_status, rtx); 434static void var_mem_delete (dataflow_set *, rtx, bool); 435 436static void dataflow_set_init (dataflow_set *); 437static void dataflow_set_clear (dataflow_set *); 438static void dataflow_set_copy (dataflow_set *, dataflow_set *); 439static int variable_union_info_cmp_pos (const void *, const void *); 440static void dataflow_set_union (dataflow_set *, dataflow_set *); 441static location_chain find_loc_in_1pdv (rtx, variable, htab_t); 442static bool canon_value_cmp (rtx, rtx); 443static int loc_cmp (rtx, rtx); 444static bool variable_part_different_p (variable_part *, variable_part *); 445static bool onepart_variable_different_p (variable, variable); 446static bool variable_different_p (variable, variable); 447static bool dataflow_set_different (dataflow_set *, dataflow_set *); 448static void dataflow_set_destroy (dataflow_set *); 449 450static bool contains_symbol_ref (rtx); 451static bool track_expr_p (tree, bool); 452static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT); 453static int add_uses (rtx *, void *); 454static void add_uses_1 (rtx *, void *); 455static void add_stores (rtx, const_rtx, void *); 456static bool compute_bb_dataflow (basic_block); 457static bool vt_find_locations (void); 458 459static void dump_attrs_list (attrs); 460static int dump_var_slot (void **, void *); 461static void dump_var (variable); 462static void dump_vars (htab_t); 463static void dump_dataflow_set (dataflow_set *); 464static void dump_dataflow_sets (void); 465 466static void variable_was_changed (variable, dataflow_set *); 467static void **set_slot_part (dataflow_set *, rtx, void **, 468 decl_or_value, HOST_WIDE_INT, 469 enum var_init_status, rtx); 470static void set_variable_part (dataflow_set *, rtx, 471 decl_or_value, HOST_WIDE_INT, 472 enum var_init_status, rtx, enum insert_option); 473static void **clobber_slot_part (dataflow_set *, rtx, 474 void **, HOST_WIDE_INT, rtx); 475static void clobber_variable_part (dataflow_set *, rtx, 476 decl_or_value, HOST_WIDE_INT, rtx); 477static void **delete_slot_part (dataflow_set *, rtx, void **, HOST_WIDE_INT); 478static void delete_variable_part (dataflow_set *, rtx, 479 decl_or_value, HOST_WIDE_INT); 480static int emit_note_insn_var_location (void **, void *); 481static void emit_notes_for_changes (rtx, enum emit_note_where, shared_hash); 482static int emit_notes_for_differences_1 (void **, void *); 483static int emit_notes_for_differences_2 (void **, void *); 484static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *); 485static void emit_notes_in_bb (basic_block, dataflow_set *); 486static void vt_emit_notes (void); 487 488static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *); 489static void vt_add_function_parameters (void); 490static bool vt_initialize (void); 491static void vt_finalize (void); 492 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. */ 496 497static void 498stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre, 499 HOST_WIDE_INT *post) 500{ 501 rtx src = SET_SRC (pattern); 502 rtx dest = SET_DEST (pattern); 503 enum rtx_code code; 504 505 if (dest == stack_pointer_rtx) 506 { 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; 513 514 if (code == MINUS) 515 *post += INTVAL (XEXP (src, 1)); 516 else 517 *post -= INTVAL (XEXP (src, 1)); 518 } 519 else if (MEM_P (dest)) 520 { 521 /* (set (mem (pre_dec (reg sp))) (foo)) */ 522 src = XEXP (dest, 0); 523 code = GET_CODE (src); 524 525 switch (code) 526 { 527 case PRE_MODIFY: 528 case POST_MODIFY: 529 if (XEXP (src, 0) == stack_pointer_rtx) 530 { 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)); 535 536 if (code == PRE_MODIFY) 537 *pre -= INTVAL (val); 538 else 539 *post -= INTVAL (val); 540 break; 541 } 542 return; 543 544 case PRE_DEC: 545 if (XEXP (src, 0) == stack_pointer_rtx) 546 { 547 *pre += GET_MODE_SIZE (GET_MODE (dest)); 548 break; 549 } 550 return; 551 552 case POST_DEC: 553 if (XEXP (src, 0) == stack_pointer_rtx) 554 { 555 *post += GET_MODE_SIZE (GET_MODE (dest)); 556 break; 557 } 558 return; 559 560 case PRE_INC: 561 if (XEXP (src, 0) == stack_pointer_rtx) 562 { 563 *pre -= GET_MODE_SIZE (GET_MODE (dest)); 564 break; 565 } 566 return; 567 568 case POST_INC: 569 if (XEXP (src, 0) == stack_pointer_rtx) 570 { 571 *post -= GET_MODE_SIZE (GET_MODE (dest)); 572 break; 573 } 574 return; 575 576 default: 577 return; 578 } 579 } 580} 581 582/* Given an INSN, calculate the amount of stack adjustment it contains 583 PRE- and POST-modifying stack pointer. */ 584 585static void 586insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre, 587 HOST_WIDE_INT *post) 588{ 589 rtx pattern; 590 591 *pre = 0; 592 *post = 0; 593 594 pattern = PATTERN (insn); 595 if (RTX_FRAME_RELATED_P (insn)) 596 { 597 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 598 if (expr) 599 pattern = XEXP (expr, 0); 600 } 601 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) 606 { 607 int i; 608 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); 614 } 615} 616 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. */ 620 621static bool 622vt_stack_adjustments (void) 623{ 624 edge_iterator *stack; 625 int sp; 626 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; 631 632 /* Allocate stack for back-tracking up CFG. */ 633 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1); 634 sp = 0; 635 636 /* Push the first edge on to the stack. */ 637 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs); 638 639 while (sp) 640 { 641 edge_iterator ei; 642 basic_block src; 643 basic_block dest; 644 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; 649 650 /* Check if the edge destination has been visited yet. */ 651 if (!VTI (dest)->visited) 652 { 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; 657 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)) 663 { 664 insn_stack_adjust_offset_pre_post (insn, &pre, &post); 665 offset += pre + post; 666 } 667 668 VTI (dest)->out.stack_adjust = offset; 669 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); 674 } 675 else 676 { 677 /* Check whether the adjustments on the edges are the same. */ 678 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust) 679 { 680 free (stack); 681 return false; 682 } 683 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--; 690 } 691 } 692 693 free (stack); 694 return true; 695} 696 697/* Compute a CFA-based value for the stack pointer. */ 698 699static rtx 700compute_cfa_pointer (HOST_WIDE_INT adjustment) 701{ 702 rtx cfa; 703 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 711 712 return cfa; 713} 714 715/* Adjustment for hard_frame_pointer_rtx to cfa base reg, 716 or -1 if the replacement shouldn't be done. */ 717static HOST_WIDE_INT hard_frame_pointer_adjustment = -1; 718 719/* Data for adjust_mems callback. */ 720 721struct adjust_mem_data 722{ 723 bool store; 724 enum machine_mode mem_mode; 725 HOST_WIDE_INT stack_adjust; 726 rtx side_effects; 727}; 728 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. */ 734 735static int 736use_narrower_mode_test (rtx *loc, void *data) 737{ 738 rtx subreg = (rtx) data; 739 740 if (CONSTANT_P (*loc)) 741 return -1; 742 switch (GET_CODE (*loc)) 743 { 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; 759 } 760} 761 762/* Transform X into narrower mode MODE from wider mode WMODE. */ 763 764static rtx 765use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode) 766{ 767 rtx op0, op1; 768 if (CONSTANT_P (x)) 769 return lowpart_subreg (mode, x, wmode); 770 switch (GET_CODE (x)) 771 { 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 (); 785 } 786} 787 788/* Helper function for adjusting used MEMs. */ 789 790static rtx 791adjust_mems (rtx loc, const_rtx old_rtx, void *data) 792{ 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)) 798 { 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) 815 { 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); 819 } 820 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)) 882 { 883 tem = loc; 884 goto finish_subreg; 885 } 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; 924 } 925 return NULL_RTX; 926} 927 928/* Helper function for replacement of uses. */ 929 930static void 931adjust_mem_uses (rtx *x, void *data) 932{ 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); 936} 937 938/* Helper function for replacement of stores. */ 939 940static void 941adjust_mem_stores (rtx loc, const_rtx expr, void *data) 942{ 943 if (MEM_P (loc)) 944 { 945 rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr), NULL_RTX, 946 adjust_mems, data); 947 if (new_dest != SET_DEST (expr)) 948 { 949 rtx xexpr = CONST_CAST_RTX (expr); 950 validate_change (NULL_RTX, &SET_DEST (xexpr), new_dest, true); 951 } 952 } 953} 954 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. */ 958 959static void 960adjust_insn (basic_block bb, rtx insn) 961{ 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; 967 968 amd.store = true; 969 note_stores (PATTERN (insn), adjust_mem_stores, &amd); 970 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) 975 { 976 rtx body, set0; 977 int i; 978 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 997 { 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))) 1009 { 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); 1018 } 1019 } 1020 } 1021 else 1022 note_uses (&PATTERN (insn), adjust_mem_uses, &amd); 1023 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))) 1028 { 1029 rtx note = find_reg_equal_equiv_note (insn); 1030 1031 if (note && CONSTANT_P (XEXP (note, 0))) 1032 validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true); 1033 } 1034 1035 if (amd.side_effects) 1036 { 1037 rtx *pat, new_pat, s; 1038 int i, oldn, newn; 1039 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); 1059 } 1060} 1061 1062/* Return true if a decl_or_value DV is a DECL or NULL. */ 1063static inline bool 1064dv_is_decl_p (decl_or_value dv) 1065{ 1066 return !dv || (int) TREE_CODE ((tree) dv) != (int) VALUE; 1067} 1068 1069/* Return true if a decl_or_value is a VALUE rtl. */ 1070static inline bool 1071dv_is_value_p (decl_or_value dv) 1072{ 1073 return dv && !dv_is_decl_p (dv); 1074} 1075 1076/* Return the decl in the decl_or_value. */ 1077static inline tree 1078dv_as_decl (decl_or_value dv) 1079{ 1080#ifdef ENABLE_CHECKING 1081 gcc_assert (dv_is_decl_p (dv)); 1082#endif 1083 return (tree) dv; 1084} 1085 1086/* Return the value in the decl_or_value. */ 1087static inline rtx 1088dv_as_value (decl_or_value dv) 1089{ 1090#ifdef ENABLE_CHECKING 1091 gcc_assert (dv_is_value_p (dv)); 1092#endif 1093 return (rtx)dv; 1094} 1095 1096/* Return the opaque pointer in the decl_or_value. */ 1097static inline void * 1098dv_as_opaque (decl_or_value dv) 1099{ 1100 return dv; 1101} 1102 1103/* Return true if a decl_or_value must not have more than one variable 1104 part. */ 1105static inline bool 1106dv_onepart_p (decl_or_value dv) 1107{ 1108 tree decl; 1109 1110 if (!MAY_HAVE_DEBUG_INSNS) 1111 return false; 1112 1113 if (dv_is_value_p (dv)) 1114 return true; 1115 1116 decl = dv_as_decl (dv); 1117 1118 if (!decl) 1119 return true; 1120 1121 if (TREE_CODE (decl) == DEBUG_EXPR_DECL) 1122 return true; 1123 1124 return (target_for_debug_bind (decl) != NULL_TREE); 1125} 1126 1127/* Return the variable pool to be used for dv, depending on whether it 1128 can have multiple parts or not. */ 1129static inline alloc_pool 1130dv_pool (decl_or_value dv) 1131{ 1132 return dv_onepart_p (dv) ? valvar_pool : var_pool; 1133} 1134 1135/* Build a decl_or_value out of a decl. */ 1136static inline decl_or_value 1137dv_from_decl (tree decl) 1138{ 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; 1145} 1146 1147/* Build a decl_or_value out of a value. */ 1148static inline decl_or_value 1149dv_from_value (rtx value) 1150{ 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; 1157} 1158 1159extern void debug_dv (decl_or_value dv); 1160 1161void 1162debug_dv (decl_or_value dv) 1163{ 1164 if (dv_is_value_p (dv)) 1165 debug_rtx (dv_as_value (dv)); 1166 else 1167 debug_generic_stmt (dv_as_decl (dv)); 1168} 1169 1170typedef unsigned int dvuid; 1171 1172/* Return the uid of DV. */ 1173 1174static inline dvuid 1175dv_uid (decl_or_value dv) 1176{ 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)); 1181} 1182 1183/* Compute the hash from the uid. */ 1184 1185static inline hashval_t 1186dv_uid2hash (dvuid uid) 1187{ 1188 return uid; 1189} 1190 1191/* The hash function for a mask table in a shared_htab chain. */ 1192 1193static inline hashval_t 1194dv_htab_hash (decl_or_value dv) 1195{ 1196 return dv_uid2hash (dv_uid (dv)); 1197} 1198 1199/* The hash function for variable_htab, computes the hash value 1200 from the declaration of variable X. */ 1201 1202static hashval_t 1203variable_htab_hash (const void *x) 1204{ 1205 const_variable const v = (const_variable) x; 1206 1207 return dv_htab_hash (v->dv); 1208} 1209 1210/* Compare the declaration of variable X with declaration Y. */ 1211 1212static int 1213variable_htab_eq (const void *x, const void *y) 1214{ 1215 const_variable const v = (const_variable) x; 1216 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y); 1217 1218 return (dv_as_opaque (v->dv) == dv_as_opaque (dv)); 1219} 1220 1221/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */ 1222 1223static void 1224variable_htab_free (void *elem) 1225{ 1226 int i; 1227 variable var = (variable) elem; 1228 location_chain node, next; 1229 1230 gcc_assert (var->refcount > 0); 1231 1232 var->refcount--; 1233 if (var->refcount > 0) 1234 return; 1235 1236 for (i = 0; i < var->n_var_parts; i++) 1237 { 1238 for (node = var->var_part[i].loc_chain; node; node = next) 1239 { 1240 next = node->next; 1241 pool_free (loc_chain_pool, node); 1242 } 1243 var->var_part[i].loc_chain = NULL; 1244 } 1245 pool_free (dv_pool (var->dv), var); 1246} 1247 1248/* The hash function for value_chains htab, computes the hash value 1249 from the VALUE. */ 1250 1251static hashval_t 1252value_chain_htab_hash (const void *x) 1253{ 1254 const_value_chain const v = (const_value_chain) x; 1255 1256 return dv_htab_hash (v->dv); 1257} 1258 1259/* Compare the VALUE X with VALUE Y. */ 1260 1261static int 1262value_chain_htab_eq (const void *x, const void *y) 1263{ 1264 const_value_chain const v = (const_value_chain) x; 1265 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y); 1266 1267 return dv_as_opaque (v->dv) == dv_as_opaque (dv); 1268} 1269 1270/* Initialize the set (array) SET of attrs to empty lists. */ 1271 1272static void 1273init_attrs_list_set (attrs *set) 1274{ 1275 int i; 1276 1277 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1278 set[i] = NULL; 1279} 1280 1281/* Make the list *LISTP empty. */ 1282 1283static void 1284attrs_list_clear (attrs *listp) 1285{ 1286 attrs list, next; 1287 1288 for (list = *listp; list; list = next) 1289 { 1290 next = list->next; 1291 pool_free (attrs_pool, list); 1292 } 1293 *listp = NULL; 1294} 1295 1296/* Return true if the pair of DECL and OFFSET is the member of the LIST. */ 1297 1298static attrs 1299attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset) 1300{ 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; 1305} 1306 1307/* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */ 1308 1309static void 1310attrs_list_insert (attrs *listp, decl_or_value dv, 1311 HOST_WIDE_INT offset, rtx loc) 1312{ 1313 attrs list; 1314 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; 1321} 1322 1323/* Copy all nodes from SRC and create a list *DSTP of the copies. */ 1324 1325static void 1326attrs_list_copy (attrs *dstp, attrs src) 1327{ 1328 attrs n; 1329 1330 attrs_list_clear (dstp); 1331 for (; src; src = src->next) 1332 { 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; 1339 } 1340} 1341 1342/* Add all nodes from SRC which are not in *DSTP to *DSTP. */ 1343 1344static void 1345attrs_list_union (attrs *dstp, attrs src) 1346{ 1347 for (; src; src = src->next) 1348 { 1349 if (!attrs_list_member (*dstp, src->dv, src->offset)) 1350 attrs_list_insert (dstp, src->dv, src->offset, src->loc); 1351 } 1352} 1353 1354/* Combine nodes that are not onepart nodes from SRC and SRC2 into 1355 *DSTP. */ 1356 1357static void 1358attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2) 1359{ 1360 gcc_assert (!*dstp); 1361 for (; src; src = src->next) 1362 { 1363 if (!dv_onepart_p (src->dv)) 1364 attrs_list_insert (dstp, src->dv, src->offset, src->loc); 1365 } 1366 for (src = src2; src; src = src->next) 1367 { 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); 1371 } 1372} 1373 1374/* Shared hashtable support. */ 1375 1376/* Return true if VARS is shared. */ 1377 1378static inline bool 1379shared_hash_shared (shared_hash vars) 1380{ 1381 return vars->refcount > 1; 1382} 1383 1384/* Return the hash table for VARS. */ 1385 1386static inline htab_t 1387shared_hash_htab (shared_hash vars) 1388{ 1389 return vars->htab; 1390} 1391 1392/* Return true if VAR is shared, or maybe because VARS is shared. */ 1393 1394static inline bool 1395shared_var_p (variable var, shared_hash vars) 1396{ 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)); 1400} 1401 1402/* Copy variables into a new hash table. */ 1403 1404static shared_hash 1405shared_hash_unshare (shared_hash vars) 1406{ 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; 1416} 1417 1418/* Increment reference counter on VARS and return it. */ 1419 1420static inline shared_hash 1421shared_hash_copy (shared_hash vars) 1422{ 1423 vars->refcount++; 1424 return vars; 1425} 1426 1427/* Decrement reference counter and destroy hash table if not shared 1428 anymore. */ 1429 1430static void 1431shared_hash_destroy (shared_hash vars) 1432{ 1433 gcc_assert (vars->refcount > 0); 1434 if (--vars->refcount == 0) 1435 { 1436 htab_delete (vars->htab); 1437 pool_free (shared_hash_pool, vars); 1438 } 1439} 1440 1441/* Unshare *PVARS if shared and return slot for DV. If INS is 1442 INSERT, insert it if not already present. */ 1443 1444static inline void ** 1445shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv, 1446 hashval_t dvhash, enum insert_option ins) 1447{ 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); 1451} 1452 1453static inline void ** 1454shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv, 1455 enum insert_option ins) 1456{ 1457 return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins); 1458} 1459 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. */ 1463 1464static inline void ** 1465shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash) 1466{ 1467 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash, 1468 shared_hash_shared (vars) 1469 ? NO_INSERT : INSERT); 1470} 1471 1472static inline void ** 1473shared_hash_find_slot (shared_hash vars, decl_or_value dv) 1474{ 1475 return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv)); 1476} 1477 1478/* Return slot for DV only if it is already present in the hash table. */ 1479 1480static inline void ** 1481shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv, 1482 hashval_t dvhash) 1483{ 1484 return htab_find_slot_with_hash (shared_hash_htab (vars), dv, dvhash, 1485 NO_INSERT); 1486} 1487 1488static inline void ** 1489shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv) 1490{ 1491 return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv)); 1492} 1493 1494/* Return variable for DV or NULL if not already present in the hash 1495 table. */ 1496 1497static inline variable 1498shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash) 1499{ 1500 return (variable) htab_find_with_hash (shared_hash_htab (vars), dv, dvhash); 1501} 1502 1503static inline variable 1504shared_hash_find (shared_hash vars, decl_or_value dv) 1505{ 1506 return shared_hash_find_1 (vars, dv, dv_htab_hash (dv)); 1507} 1508 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. 1516 */ 1517 1518static inline bool 1519canon_value_cmp (rtx tval, rtx cval) 1520{ 1521 return !cval 1522 || CSELIB_VAL_PTR (tval)->uid < CSELIB_VAL_PTR (cval)->uid; 1523} 1524 1525static bool dst_can_be_shared; 1526 1527/* Return a copy of a variable VAR and insert it to dataflow set SET. */ 1528 1529static void ** 1530unshare_variable (dataflow_set *set, void **slot, variable var, 1531 enum var_init_status initialized) 1532{ 1533 variable new_var; 1534 int i; 1535 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; 1544 1545 if (! flag_var_tracking_uninit) 1546 initialized = VAR_INIT_STATUS_INITIALIZED; 1547 1548 for (i = 0; i < var->n_var_parts; i++) 1549 { 1550 location_chain node; 1551 location_chain *nextp; 1552 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) 1556 { 1557 location_chain new_lc; 1558 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; 1570 1571 *nextp = new_lc; 1572 nextp = &new_lc->next; 1573 } 1574 1575 new_var->var_part[i].cur_loc = var->var_part[i].cur_loc; 1576 } 1577 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) 1585 { 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; 1594 } 1595 return slot; 1596} 1597 1598/* Copy all variables from hash table SRC to hash table DST. */ 1599 1600static void 1601vars_copy (htab_t dst, htab_t src) 1602{ 1603 htab_iterator hi; 1604 variable var; 1605 1606 FOR_EACH_HTAB_ELEMENT (src, var, variable, hi) 1607 { 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; 1614 } 1615} 1616 1617/* Map a decl to its main debug decl. */ 1618 1619static inline tree 1620var_debug_decl (tree decl) 1621{ 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); 1626 1627 return decl; 1628} 1629 1630/* Set the register LOC to contain DV, OFFSET. */ 1631 1632static void 1633var_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) 1636{ 1637 attrs node; 1638 bool decl_p = dv_is_decl_p (dv); 1639 1640 if (decl_p) 1641 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv))); 1642 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); 1650} 1651 1652/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ 1653 1654static void 1655var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized, 1656 rtx set_src) 1657{ 1658 tree decl = REG_EXPR (loc); 1659 HOST_WIDE_INT offset = REG_OFFSET (loc); 1660 1661 var_reg_decl_set (set, loc, initialized, 1662 dv_from_decl (decl), offset, set_src, INSERT); 1663} 1664 1665static enum var_init_status 1666get_init_value (dataflow_set *set, rtx loc, decl_or_value dv) 1667{ 1668 variable var; 1669 int i; 1670 enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN; 1671 1672 if (! flag_var_tracking_uninit) 1673 return VAR_INIT_STATUS_INITIALIZED; 1674 1675 var = shared_hash_find (set->vars, dv); 1676 if (var) 1677 { 1678 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++) 1679 { 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)) 1683 { 1684 ret_val = nextp->init; 1685 break; 1686 } 1687 } 1688 } 1689 1690 return ret_val; 1691} 1692 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. */ 1699 1700static void 1701var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify, 1702 enum var_init_status initialized, rtx set_src) 1703{ 1704 tree decl = REG_EXPR (loc); 1705 HOST_WIDE_INT offset = REG_OFFSET (loc); 1706 attrs node, next; 1707 attrs *nextp; 1708 1709 decl = var_debug_decl (decl); 1710 1711 if (initialized == VAR_INIT_STATUS_UNKNOWN) 1712 initialized = get_init_value (set, loc, dv_from_decl (decl)); 1713 1714 nextp = &set->regs[REGNO (loc)]; 1715 for (node = *nextp; node; node = next) 1716 { 1717 next = node->next; 1718 if (dv_as_opaque (node->dv) != decl || node->offset != offset) 1719 { 1720 delete_variable_part (set, node->loc, node->dv, node->offset); 1721 pool_free (attrs_pool, node); 1722 *nextp = next; 1723 } 1724 else 1725 { 1726 node->loc = loc; 1727 nextp = &node->next; 1728 } 1729 } 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); 1733} 1734 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. */ 1739 1740static void 1741var_reg_delete (dataflow_set *set, rtx loc, bool clobber) 1742{ 1743 attrs *nextp = &set->regs[REGNO (loc)]; 1744 attrs node, next; 1745 1746 if (clobber) 1747 { 1748 tree decl = REG_EXPR (loc); 1749 HOST_WIDE_INT offset = REG_OFFSET (loc); 1750 1751 decl = var_debug_decl (decl); 1752 1753 clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL); 1754 } 1755 1756 for (node = *nextp; node; node = next) 1757 { 1758 next = node->next; 1759 if (clobber || !dv_onepart_p (node->dv)) 1760 { 1761 delete_variable_part (set, node->loc, node->dv, node->offset); 1762 pool_free (attrs_pool, node); 1763 *nextp = next; 1764 } 1765 else 1766 nextp = &node->next; 1767 } 1768} 1769 1770/* Delete content of register with number REGNO in dataflow set SET. */ 1771 1772static void 1773var_regno_delete (dataflow_set *set, int regno) 1774{ 1775 attrs *reg = &set->regs[regno]; 1776 attrs node, next; 1777 1778 for (node = *reg; node; node = next) 1779 { 1780 next = node->next; 1781 delete_variable_part (set, node->loc, node->dv, node->offset); 1782 pool_free (attrs_pool, node); 1783 } 1784 *reg = NULL; 1785} 1786 1787/* Set the location of DV, OFFSET as the MEM LOC. */ 1788 1789static void 1790var_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) 1793{ 1794 if (dv_is_decl_p (dv)) 1795 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv))); 1796 1797 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt); 1798} 1799 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. */ 1803 1804static void 1805var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized, 1806 rtx set_src) 1807{ 1808 tree decl = MEM_EXPR (loc); 1809 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 1810 1811 var_mem_decl_set (set, loc, initialized, 1812 dv_from_decl (decl), offset, set_src, INSERT); 1813} 1814 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. */ 1821 1822static void 1823var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify, 1824 enum var_init_status initialized, rtx set_src) 1825{ 1826 tree decl = MEM_EXPR (loc); 1827 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 1828 1829 decl = var_debug_decl (decl); 1830 1831 if (initialized == VAR_INIT_STATUS_UNKNOWN) 1832 initialized = get_init_value (set, loc, dv_from_decl (decl)); 1833 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); 1837} 1838 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. */ 1842 1843static void 1844var_mem_delete (dataflow_set *set, rtx loc, bool clobber) 1845{ 1846 tree decl = MEM_EXPR (loc); 1847 HOST_WIDE_INT offset = INT_MEM_OFFSET (loc); 1848 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); 1853} 1854 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. */ 1858 1859static void 1860val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified) 1861{ 1862 cselib_val *v = CSELIB_VAL_PTR (val); 1863 1864 gcc_assert (cselib_preserved_value_p (v)); 1865 1866 if (dump_file) 1867 { 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) 1873 { 1874 struct elt_loc_list *l; 1875 for (l = v->locs; l; l = l->next) 1876 { 1877 fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn)); 1878 print_inline_rtx (dump_file, l->loc, 0); 1879 } 1880 } 1881 fprintf (dump_file, "\n"); 1882 } 1883 1884 if (REG_P (loc)) 1885 { 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); 1890 } 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); 1897} 1898 1899/* Reset this node, detaching all its equivalences. Return the slot 1900 in the variable hash table that holds dv, if there is one. */ 1901 1902static void 1903val_reset (dataflow_set *set, decl_or_value dv) 1904{ 1905 variable var = shared_hash_find (set->vars, dv) ; 1906 location_chain node; 1907 rtx cval; 1908 1909 if (!var || !var->n_var_parts) 1910 return; 1911 1912 gcc_assert (var->n_var_parts == 1); 1913 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; 1919 1920 for (node = var->var_part[0].loc_chain; node; node = node->next) 1921 if (GET_CODE (node->loc) == VALUE && cval != node->loc) 1922 { 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); 1931 } 1932 1933 if (cval) 1934 { 1935 decl_or_value cdv = dv_from_value (cval); 1936 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) 1940 { 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); 1952 } 1953 } 1954 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); 1959 1960 clobber_variable_part (set, NULL, dv, 0, NULL); 1961 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. */ 1968} 1969 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. */ 1973 1974static void 1975val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn) 1976{ 1977 decl_or_value dv = dv_from_value (val); 1978 1979 if (dump_file && (dump_flags & TDF_DETAILS)) 1980 { 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); 1989 } 1990 1991 val_reset (set, dv); 1992 1993 if (REG_P (loc)) 1994 { 1995 attrs node, found = NULL; 1996 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)) 2000 { 2001 found = node; 2002 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); 2012 } 2013 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); 2019 } 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); 2028} 2029 2030/* Initialize dataflow set SET to be empty. 2031 VARS_SIZE is the initial size of hash table VARS. */ 2032 2033static void 2034dataflow_set_init (dataflow_set *set) 2035{ 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; 2040} 2041 2042/* Delete the contents of dataflow set SET. */ 2043 2044static void 2045dataflow_set_clear (dataflow_set *set) 2046{ 2047 int i; 2048 2049 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2050 attrs_list_clear (&set->regs[i]); 2051 2052 shared_hash_destroy (set->vars); 2053 set->vars = shared_hash_copy (empty_shared_hash); 2054} 2055 2056/* Copy the contents of dataflow set SRC to DST. */ 2057 2058static void 2059dataflow_set_copy (dataflow_set *dst, dataflow_set *src) 2060{ 2061 int i; 2062 2063 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2064 attrs_list_copy (&dst->regs[i], src->regs[i]); 2065 2066 shared_hash_destroy (dst->vars); 2067 dst->vars = shared_hash_copy (src->vars); 2068 dst->stack_adjust = src->stack_adjust; 2069} 2070 2071/* Information for merging lists of locations for a given offset of variable. 2072 */ 2073struct variable_union_info 2074{ 2075 /* Node of the location chain. */ 2076 location_chain lc; 2077 2078 /* The sum of positions in the input chains. */ 2079 int pos; 2080 2081 /* The position in the chain of DST dataflow set. */ 2082 int pos_dst; 2083}; 2084 2085/* Buffer for location list sorting and its allocated size. */ 2086static struct variable_union_info *vui_vec; 2087static int vui_allocated; 2088 2089/* Compare function for qsort, order the structures by POS element. */ 2090 2091static int 2092variable_union_info_cmp_pos (const void *n1, const void *n2) 2093{ 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; 2098 2099 if (i1->pos != i2->pos) 2100 return i1->pos - i2->pos; 2101 2102 return (i1->pos_dst - i2->pos_dst); 2103} 2104 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. */ 2114 2115static int 2116variable_union (variable src, dataflow_set *set) 2117{ 2118 variable dst; 2119 void **dstp; 2120 int i, j, k; 2121 2122 dstp = shared_hash_find_slot (set->vars, src->dv); 2123 if (!dstp || !*dstp) 2124 { 2125 src->refcount++; 2126 2127 dst_can_be_shared = false; 2128 if (!dstp) 2129 dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT); 2130 2131 *dstp = src; 2132 2133 /* Continue traversing the hash table. */ 2134 return 1; 2135 } 2136 else 2137 dst = (variable) *dstp; 2138 2139 gcc_assert (src->n_var_parts); 2140 2141 /* We can combine one-part variables very efficiently, because their 2142 entries are in canonical order. */ 2143 if (dv_onepart_p (src->dv)) 2144 { 2145 location_chain *nodep, dnode, snode; 2146 2147 gcc_assert (src->n_var_parts == 1 2148 && dst->n_var_parts == 1); 2149 2150 snode = src->var_part[0].loc_chain; 2151 gcc_assert (snode); 2152 2153 restart_onepart_unshared: 2154 nodep = &dst->var_part[0].loc_chain; 2155 dnode = *nodep; 2156 gcc_assert (dnode); 2157 2158 while (snode) 2159 { 2160 int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1; 2161 2162 if (r > 0) 2163 { 2164 location_chain nnode; 2165 2166 if (shared_var_p (dst, set->vars)) 2167 { 2168 dstp = unshare_variable (set, dstp, dst, 2169 VAR_INIT_STATUS_INITIALIZED); 2170 dst = (variable)*dstp; 2171 goto restart_onepart_unshared; 2172 } 2173 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; 2183 } 2184#ifdef ENABLE_CHECKING 2185 else if (r == 0) 2186 gcc_assert (rtx_equal_p (dnode->loc, snode->loc)); 2187#endif 2188 2189 if (r >= 0) 2190 snode = snode->next; 2191 2192 nodep = &dnode->next; 2193 dnode = *nodep; 2194 } 2195 2196 return 1; 2197 } 2198 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++) 2202 { 2203 if (src->var_part[i].offset == dst->var_part[j].offset) 2204 { 2205 i++; 2206 j++; 2207 } 2208 else if (src->var_part[i].offset < dst->var_part[j].offset) 2209 i++; 2210 else 2211 j++; 2212 } 2213 k += src->n_var_parts - i; 2214 k += dst->n_var_parts - j; 2215 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); 2219 2220 if (dst->n_var_parts != k && shared_var_p (dst, set->vars)) 2221 { 2222 dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN); 2223 dst = (variable)*dstp; 2224 } 2225 2226 i = src->n_var_parts - 1; 2227 j = dst->n_var_parts - 1; 2228 dst->n_var_parts = k; 2229 2230 for (k--; k >= 0; k--) 2231 { 2232 location_chain node, node2; 2233 2234 if (i >= 0 && j >= 0 2235 && src->var_part[i].offset == dst->var_part[j].offset) 2236 { 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; 2243 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)) 2248 { 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) 2252 { 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))) 2257 { 2258 if (node2->init < node->init) 2259 node2->init = node->init; 2260 break; 2261 } 2262 } 2263 if (node || node2) 2264 { 2265 dstp = unshare_variable (set, dstp, dst, 2266 VAR_INIT_STATUS_UNKNOWN); 2267 dst = (variable)*dstp; 2268 } 2269 } 2270 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++; 2277 2278 if (dst_l == 1) 2279 { 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))) 2290 { 2291 location_chain new_node; 2292 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; 2303 } 2304 node2->next = NULL; 2305 } 2306 else 2307 { 2308 if (src_l + dst_l > vui_allocated) 2309 { 2310 vui_allocated = MAX (vui_allocated * 2, src_l + dst_l); 2311 vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec, 2312 vui_allocated); 2313 } 2314 vui = vui_vec; 2315 2316 /* Fill in the locations from DST. */ 2317 for (node = dst->var_part[j].loc_chain, jj = 0; node; 2318 node = node->next, jj++) 2319 { 2320 vui[jj].lc = node; 2321 vui[jj].pos_dst = jj; 2322 2323 /* Pos plus value larger than a sum of 2 valid positions. */ 2324 vui[jj].pos = jj + src_l + dst_l; 2325 } 2326 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++) 2331 { 2332 /* Find location from NODE. */ 2333 for (jj = 0; jj < dst_l; jj++) 2334 { 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)) 2339 { 2340 vui[jj].pos = jj + ii; 2341 break; 2342 } 2343 } 2344 if (jj >= dst_l) /* The location has not been found. */ 2345 { 2346 location_chain new_node; 2347 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++; 2360 } 2361 } 2362 2363 if (dst_l == 2) 2364 { 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) 2369 { 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) 2374 { 2375 vui[0].lc->next = vui[2].lc; 2376 vui[n - 1].lc->next = NULL; 2377 } 2378 else 2379 vui[0].lc->next = NULL; 2380 ii = 3; 2381 } 2382 else 2383 { 2384 dst->var_part[k].loc_chain = vui[0].lc; 2385 if (n >= 3 && vui[2].pos < vui[1].pos) 2386 { 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) 2391 { 2392 vui[1].lc->next = vui[3].lc; 2393 vui[n - 1].lc->next = NULL; 2394 } 2395 else 2396 vui[1].lc->next = NULL; 2397 ii = 4; 2398 } 2399 else 2400 { 2401 /* Order should be 0, 1, 2... */ 2402 ii = 1; 2403 vui[n - 1].lc->next = NULL; 2404 } 2405 } 2406 for (; ii < n; ii++) 2407 vui[ii - 1].lc->next = vui[ii].lc; 2408 } 2409 else 2410 { 2411 qsort (vui, n, sizeof (struct variable_union_info), 2412 variable_union_info_cmp_pos); 2413 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; 2419 } 2420 2421 dst->var_part[k].offset = dst->var_part[j].offset; 2422 } 2423 i--; 2424 j--; 2425 } 2426 else if ((i >= 0 && j >= 0 2427 && src->var_part[i].offset < dst->var_part[j].offset) 2428 || i < 0) 2429 { 2430 dst->var_part[k] = dst->var_part[j]; 2431 j--; 2432 } 2433 else if ((i >= 0 && j >= 0 2434 && src->var_part[i].offset > dst->var_part[j].offset) 2435 || j < 0) 2436 { 2437 location_chain *nextp; 2438 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) 2442 { 2443 location_chain new_lc; 2444 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; 2453 2454 *nextp = new_lc; 2455 nextp = &new_lc->next; 2456 } 2457 2458 dst->var_part[k].offset = src->var_part[i].offset; 2459 i--; 2460 } 2461 dst->var_part[k].cur_loc = NULL; 2462 } 2463 2464 if (flag_var_tracking_uninit) 2465 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++) 2466 { 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)) 2471 { 2472 if (node->init > node2->init) 2473 node2->init = node->init; 2474 } 2475 } 2476 2477 /* Continue traversing the hash table. */ 2478 return 1; 2479} 2480 2481/* Compute union of dataflow sets SRC and DST and store it to DST. */ 2482 2483static void 2484dataflow_set_union (dataflow_set *dst, dataflow_set *src) 2485{ 2486 int i; 2487 2488 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2489 attrs_list_union (&dst->regs[i], src->regs[i]); 2490 2491 if (dst->vars == empty_shared_hash) 2492 { 2493 shared_hash_destroy (dst->vars); 2494 dst->vars = shared_hash_copy (src->vars); 2495 } 2496 else 2497 { 2498 htab_iterator hi; 2499 variable var; 2500 2501 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (src->vars), var, variable, hi) 2502 variable_union (var, dst); 2503 } 2504} 2505 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) 2514 2515/* Record that DV has been added into resp. removed from changed_variables 2516 hashtable. */ 2517 2518static inline void 2519set_dv_changed (decl_or_value dv, bool newv) 2520{ 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; 2525} 2526 2527/* Return true if DV is present in changed_variables hash table. */ 2528 2529static inline bool 2530dv_changed_p (decl_or_value dv) 2531{ 2532 return (dv_is_value_p (dv) 2533 ? VALUE_CHANGED (dv_as_value (dv)) 2534 : DECL_CHANGED (dv_as_decl (dv))); 2535} 2536 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. */ 2541 2542static location_chain 2543find_loc_in_1pdv (rtx loc, variable var, htab_t vars) 2544{ 2545 location_chain node; 2546 enum rtx_code loc_code; 2547 2548 if (!var) 2549 return NULL; 2550 2551#ifdef ENABLE_CHECKING 2552 gcc_assert (dv_onepart_p (var->dv)); 2553#endif 2554 2555 if (!var->n_var_parts) 2556 return NULL; 2557 2558#ifdef ENABLE_CHECKING 2559 gcc_assert (var->var_part[0].offset == 0); 2560 gcc_assert (loc != dv_as_opaque (var->dv)); 2561#endif 2562 2563 loc_code = GET_CODE (loc); 2564 for (node = var->var_part[0].loc_chain; node; node = node->next) 2565 { 2566 decl_or_value dv; 2567 variable rvar; 2568 2569 if (GET_CODE (node->loc) != loc_code) 2570 { 2571 if (GET_CODE (node->loc) != VALUE) 2572 continue; 2573 } 2574 else if (loc == node->loc) 2575 return node; 2576 else if (loc_code != VALUE) 2577 { 2578 if (rtx_equal_p (loc, node->loc)) 2579 return node; 2580 continue; 2581 } 2582 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))) 2588 { 2589 /* Skip all subsequent VALUEs. */ 2590 while (node->next && GET_CODE (node->next->loc) == VALUE) 2591 { 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; 2599 } 2600 continue; 2601 } 2602 2603#ifdef ENABLE_CHECKING 2604 gcc_assert (node == var->var_part[0].loc_chain); 2605 gcc_assert (!node->next); 2606#endif 2607 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); 2611 } 2612 2613 return NULL; 2614} 2615 2616/* Hash table iteration argument passed to variable_merge. */ 2617struct dfset_merge 2618{ 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; 2627}; 2628 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. */ 2631 2632static void 2633insert_into_intersection (location_chain *nodep, rtx loc, 2634 enum var_init_status status) 2635{ 2636 location_chain node; 2637 int r; 2638 2639 for (node = *nodep; node; nodep = &node->next, node = *nodep) 2640 if ((r = loc_cmp (node->loc, loc)) == 0) 2641 { 2642 node->init = MIN (node->init, status); 2643 return; 2644 } 2645 else if (r > 0) 2646 break; 2647 2648 node = (location_chain) pool_alloc (loc_chain_pool); 2649 2650 node->loc = loc; 2651 node->set_src = NULL; 2652 node->init = status; 2653 node->next = *nodep; 2654 *nodep = node; 2655} 2656 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. */ 2661 2662static void 2663intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm, 2664 location_chain s1node, variable s2var) 2665{ 2666 dataflow_set *s1set = dsm->cur; 2667 dataflow_set *s2set = dsm->src; 2668 location_chain found; 2669 2670 if (s2var) 2671 { 2672 location_chain s2node; 2673 2674#ifdef ENABLE_CHECKING 2675 gcc_assert (dv_onepart_p (s2var->dv)); 2676#endif 2677 2678 if (s2var->n_var_parts) 2679 { 2680#ifdef ENABLE_CHECKING 2681 gcc_assert (s2var->var_part[0].offset == 0); 2682#endif 2683 s2node = s2var->var_part[0].loc_chain; 2684 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)); 2694 } 2695 } 2696 2697 for (; s1node; s1node = s1node->next) 2698 { 2699 if (s1node->loc == val) 2700 continue; 2701 2702 if ((found = find_loc_in_1pdv (s1node->loc, s2var, 2703 shared_hash_htab (s2set->vars)))) 2704 { 2705 insert_into_intersection (dest, s1node->loc, 2706 MIN (s1node->init, found->init)); 2707 continue; 2708 } 2709 2710 if (GET_CODE (s1node->loc) == VALUE 2711 && !VALUE_RECURSED_INTO (s1node->loc)) 2712 { 2713 decl_or_value dv = dv_from_value (s1node->loc); 2714 variable svar = shared_hash_find (s1set->vars, dv); 2715 if (svar) 2716 { 2717 if (svar->n_var_parts == 1) 2718 { 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; 2724 } 2725 } 2726 } 2727 2728 /* ??? if the location is equivalent to any location in src, 2729 searched recursively 2730 2731 add to dst the values needed to represent the equivalence 2732 2733 telling whether locations S is equivalent to another dv's 2734 location list: 2735 2736 for each location D in the list 2737 2738 if S and D satisfy rtx_equal_p, then it is present 2739 2740 else if D is a value, recurse without cycles 2741 2742 else if S and D have the same CODE and MODE 2743 2744 for each operand oS and the corresponding oD 2745 2746 if oS and oD are not equivalent, then S an D are not equivalent 2747 2748 else if they are RTX vectors 2749 2750 if any vector oS element is not equivalent to its respective oD, 2751 then S and D are not equivalent 2752 2753 */ 2754 2755 2756 } 2757} 2758 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. */ 2762 2763static int 2764loc_cmp (rtx x, rtx y) 2765{ 2766 int i, j, r; 2767 RTX_CODE code = GET_CODE (x); 2768 const char *fmt; 2769 2770 if (x == y) 2771 return 0; 2772 2773 if (REG_P (x)) 2774 { 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; 2784 } 2785 2786 if (REG_P (y)) 2787 return 1; 2788 2789 if (MEM_P (x)) 2790 { 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)); 2795 } 2796 2797 if (MEM_P (y)) 2798 return 1; 2799 2800 if (GET_CODE (x) == VALUE) 2801 { 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; 2812 } 2813 2814 if (GET_CODE (y) == VALUE) 2815 return 1; 2816 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; 2823 2824 gcc_assert (GET_MODE (x) == GET_MODE (y)); 2825 2826 if (GET_CODE (x) == DEBUG_EXPR) 2827 { 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; 2836 } 2837 2838 fmt = GET_RTX_FORMAT (code); 2839 for (i = 0; i < GET_RTX_LENGTH (code); i++) 2840 switch (fmt[i]) 2841 { 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; 2849 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; 2858 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; 2868 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; 2874 2875 case 'e': 2876 if ((r = loc_cmp (XEXP (x, i), XEXP (y, i)))) 2877 return r; 2878 break; 2879 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; 2894 2895 case 'u': 2896 /* These are just backpointers, so they don't matter. */ 2897 break; 2898 2899 case '0': 2900 case 't': 2901 break; 2902 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 (); 2908 } 2909 2910 return 0; 2911} 2912 2913/* If decl or value DVP refers to VALUE from *LOC, add backlinks 2914 from VALUE to DVP. */ 2915 2916static int 2917add_value_chain (rtx *loc, void *dvp) 2918{ 2919 decl_or_value dv, ldv; 2920 value_chain vc, nvc; 2921 void **slot; 2922 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; 2929 2930 if (dv_as_opaque (ldv) == dvp) 2931 return 0; 2932 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) 2937 { 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; 2943 } 2944 else 2945 { 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) 2950 { 2951 vc->refcount++; 2952 return 0; 2953 } 2954 } 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; 2962} 2963 2964/* If decl or value DVP refers to VALUEs from within LOC, add backlinks 2965 from those VALUEs to DVP. */ 2966 2967static void 2968add_value_chains (decl_or_value dv, rtx loc) 2969{ 2970 if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR) 2971 { 2972 add_value_chain (&loc, dv_as_opaque (dv)); 2973 return; 2974 } 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)); 2980} 2981 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. */ 2986 2987static void 2988add_cselib_value_chains (decl_or_value dv) 2989{ 2990 struct elt_loc_list **l; 2991 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 2996 { 2997 for_each_rtx (&(*l)->loc, add_value_chain, dv_as_opaque (dv)); 2998 l = &(*l)->next; 2999 } 3000} 3001 3002/* If decl or value DVP refers to VALUE from *LOC, remove backlinks 3003 from VALUE to DVP. */ 3004 3005static int 3006remove_value_chain (rtx *loc, void *dvp) 3007{ 3008 decl_or_value dv, ldv; 3009 value_chain vc; 3010 void **slot; 3011 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; 3018 3019 if (dv_as_opaque (ldv) == dvp) 3020 return 0; 3021 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)) 3027 { 3028 value_chain dvc = vc->next; 3029 gcc_assert (dvc->refcount > 0); 3030 if (--dvc->refcount == 0) 3031 { 3032 vc->next = dvc->next; 3033 pool_free (value_chain_pool, dvc); 3034 if (vc->next == NULL && vc == (value_chain) *slot) 3035 { 3036 pool_free (value_chain_pool, vc); 3037 htab_clear_slot (value_chains, slot); 3038 } 3039 } 3040 return 0; 3041 } 3042 gcc_unreachable (); 3043} 3044 3045/* If decl or value DVP refers to VALUEs from within LOC, remove backlinks 3046 from those VALUEs to DVP. */ 3047 3048static void 3049remove_value_chains (decl_or_value dv, rtx loc) 3050{ 3051 if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR) 3052 { 3053 remove_value_chain (&loc, dv_as_opaque (dv)); 3054 return; 3055 } 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)); 3061} 3062 3063#if ENABLE_CHECKING 3064/* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those 3065 VALUEs to DV. */ 3066 3067static void 3068remove_cselib_value_chains (decl_or_value dv) 3069{ 3070 struct elt_loc_list *l; 3071 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)); 3074} 3075 3076/* Check the order of entries in one-part variables. */ 3077 3078static int 3079canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED) 3080{ 3081 variable var = (variable) *slot; 3082 decl_or_value dv = var->dv; 3083 location_chain node, next; 3084 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 3091 3092 if (!dv_onepart_p (dv)) 3093 return 1; 3094 3095 gcc_assert (var->n_var_parts == 1); 3096 node = var->var_part[0].loc_chain; 3097 gcc_assert (node); 3098 3099 while ((next = node->next)) 3100 { 3101 gcc_assert (loc_cmp (node->loc, next->loc) < 0); 3102 node = next; 3103 } 3104 3105 return 1; 3106} 3107#endif 3108 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. */ 3113 3114static int 3115canonicalize_values_mark (void **slot, void *data) 3116{ 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; 3122 3123 if (!dv_is_value_p (dv)) 3124 return 1; 3125 3126 gcc_assert (var->n_var_parts == 1); 3127 3128 val = dv_as_value (dv); 3129 3130 for (node = var->var_part[0].loc_chain; node; node = node->next) 3131 if (GET_CODE (node->loc) == VALUE) 3132 { 3133 if (canon_value_cmp (node->loc, val)) 3134 VALUE_RECURSED_INTO (val) = true; 3135 else 3136 { 3137 decl_or_value odv = dv_from_value (node->loc); 3138 void **oslot = shared_hash_find_slot_noinsert (set->vars, odv); 3139 3140 oslot = set_slot_part (set, val, oslot, odv, 0, 3141 node->init, NULL_RTX); 3142 3143 VALUE_RECURSED_INTO (node->loc) = true; 3144 } 3145 } 3146 3147 return 1; 3148} 3149 3150/* Remove redundant entries from equivalence lists in onepart 3151 variables, canonicalizing equivalence sets into star shapes. */ 3152 3153static int 3154canonicalize_values_star (void **slot, void *data) 3155{ 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; 3165 3166 if (!dv_onepart_p (dv)) 3167 return 1; 3168 3169 gcc_assert (var->n_var_parts == 1); 3170 3171 if (dv_is_value_p (dv)) 3172 { 3173 cval = dv_as_value (dv); 3174 if (!VALUE_RECURSED_INTO (cval)) 3175 return 1; 3176 VALUE_RECURSED_INTO (cval) = false; 3177 } 3178 else 3179 cval = NULL_RTX; 3180 3181 restart: 3182 val = cval; 3183 has_value = false; 3184 has_marks = false; 3185 3186 gcc_assert (var->n_var_parts == 1); 3187 3188 for (node = var->var_part[0].loc_chain; node; node = node->next) 3189 if (GET_CODE (node->loc) == VALUE) 3190 { 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; 3196 } 3197 3198 if (!has_value) 3199 return 1; 3200 3201 if (cval == val) 3202 { 3203 if (!has_marks || dv_is_decl_p (dv)) 3204 return 1; 3205 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; 3210 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)) 3214 { 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) 3221 { 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; 3227 } 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; 3234 } 3235 3236 VALUE_RECURSED_INTO (val) = false; 3237 3238 return 1; 3239 } 3240 3241 /* Push values to the canonical one. */ 3242 cdv = dv_from_value (cval); 3243 cslot = shared_hash_find_slot_noinsert (set->vars, cdv); 3244 3245 for (node = var->var_part[0].loc_chain; node; node = node->next) 3246 if (node->loc != cval) 3247 { 3248 cslot = set_slot_part (set, node->loc, cslot, cdv, 0, 3249 node->init, NULL_RTX); 3250 if (GET_CODE (node->loc) == VALUE) 3251 { 3252 decl_or_value ndv = dv_from_value (node->loc); 3253 3254 set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX, 3255 NO_INSERT); 3256 3257 if (canon_value_cmp (node->loc, val)) 3258 { 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; 3270 } 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); 3276 } 3277 else if (GET_CODE (node->loc) == REG) 3278 { 3279 attrs list = set->regs[REGNO (node->loc)], *listp; 3280 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. */ 3285 3286 while (list) 3287 { 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; 3292 3293 list = list->next; 3294 } 3295 3296 gcc_assert (list); 3297 if (dv_as_opaque (list->dv) == dv_as_opaque (dv)) 3298 { 3299 list->dv = cdv; 3300 for (listp = &list->next; (list = *listp); listp = &list->next) 3301 { 3302 if (list->offset) 3303 continue; 3304 3305 if (dv_as_opaque (list->dv) == dv_as_opaque (cdv)) 3306 { 3307 *listp = list->next; 3308 pool_free (attrs_pool, list); 3309 list = *listp; 3310 break; 3311 } 3312 3313 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv)); 3314 } 3315 } 3316 else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv)) 3317 { 3318 for (listp = &list->next; (list = *listp); listp = &list->next) 3319 { 3320 if (list->offset) 3321 continue; 3322 3323 if (dv_as_opaque (list->dv) == dv_as_opaque (dv)) 3324 { 3325 *listp = list->next; 3326 pool_free (attrs_pool, list); 3327 list = *listp; 3328 break; 3329 } 3330 3331 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv)); 3332 } 3333 } 3334 else 3335 gcc_unreachable (); 3336 3337#if ENABLE_CHECKING 3338 while (list) 3339 { 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 (); 3344 3345 list = list->next; 3346 } 3347#endif 3348 } 3349 } 3350 3351 if (val) 3352 cslot = set_slot_part (set, val, cslot, cdv, 0, 3353 VAR_INIT_STATUS_INITIALIZED, NULL_RTX); 3354 3355 slot = clobber_slot_part (set, cval, slot, 0, NULL); 3356 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); 3361 3362 if (VALUE_RECURSED_INTO (cval)) 3363 goto restart_with_cval; 3364 3365 return 1; 3366} 3367 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. */ 3374 3375static int 3376canonicalize_vars_star (void **slot, void *data) 3377{ 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; 3387 3388 if (!dv_onepart_p (dv) || dv_is_value_p (dv)) 3389 return 1; 3390 3391 gcc_assert (var->n_var_parts == 1); 3392 3393 node = var->var_part[0].loc_chain; 3394 3395 if (GET_CODE (node->loc) != VALUE) 3396 return 1; 3397 3398 gcc_assert (!node->next); 3399 cval = node->loc; 3400 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); 3408 3409 cnode = cvar->var_part[0].loc_chain; 3410 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; 3416 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; 3421 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); 3425 3426 return 1; 3427} 3428 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. */ 3433 3434static int 3435variable_merge_over_cur (variable s1var, struct dfset_merge *dsm) 3436{ 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; 3445 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); 3451 3452 if (!onepart) 3453 return variable_union (s1var, dst); 3454 3455 gcc_assert (s1var->n_var_parts == 1 3456 && s1var->var_part[0].offset == 0); 3457 3458 dvhash = dv_htab_hash (dv); 3459 if (dv_is_value_p (dv)) 3460 val = dv_as_value (dv); 3461 else 3462 val = NULL; 3463 3464 s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash); 3465 if (!s2var) 3466 { 3467 dst_can_be_shared = false; 3468 return 1; 3469 } 3470 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); 3475 3476 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash); 3477 if (dstslot) 3478 { 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; 3484 } 3485 else 3486 { 3487 nodep = &node; 3488 node = NULL; 3489 } 3490 3491 if (!dstslot && !onepart_variable_different_p (s1var, s2var)) 3492 { 3493 dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv, 3494 dvhash, INSERT); 3495 *dstslot = dvar = s2var; 3496 dvar->refcount++; 3497 } 3498 else 3499 { 3500 dst_can_be_shared = false; 3501 3502 intersect_loc_chains (val, nodep, dsm, 3503 s1var->var_part[0].loc_chain, s2var); 3504 3505 if (!dstslot) 3506 { 3507 if (node) 3508 { 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; 3518 3519 dstslot 3520 = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash, 3521 INSERT); 3522 gcc_assert (!*dstslot); 3523 *dstslot = dvar; 3524 } 3525 else 3526 return 1; 3527 } 3528 } 3529 3530 nodep = &dvar->var_part[0].loc_chain; 3531 while ((node = *nodep)) 3532 { 3533 location_chain *nextp = &node->next; 3534 3535 if (GET_CODE (node->loc) == REG) 3536 { 3537 attrs list; 3538 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; 3543 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) 3550 { 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); 3555 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; 3565 } 3566 } 3567 else 3568 /* Canonicalization puts registers first, so we don't have to 3569 walk it all. */ 3570 break; 3571 nodep = nextp; 3572 } 3573 3574 if (dvar != (variable)*dstslot) 3575 dvar = (variable)*dstslot; 3576 nodep = &dvar->var_part[0].loc_chain; 3577 3578 if (val) 3579 { 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) 3585 { 3586 VALUE_RECURSED_INTO (node->loc) = true; 3587 set_variable_part (dst, val, dv_from_value (node->loc), 0, 3588 node->init, NULL, INSERT); 3589 } 3590 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; 3599 } 3600 else 3601 { 3602 bool has_value = false, has_other = false; 3603 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) 3608 { 3609 if (GET_CODE (node->loc) == VALUE) 3610 { 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; 3618 } 3619 else 3620 { 3621 has_other = true; 3622 if (has_value) 3623 break; 3624 } 3625 } 3626 3627 if (has_value && has_other) 3628 { 3629 for (node = *nodep; node; node = node->next) 3630 { 3631 if (GET_CODE (node->loc) == VALUE) 3632 { 3633 decl_or_value dv = dv_from_value (node->loc); 3634 void **slot = NULL; 3635 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) 3642 { 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; 3653 } 3654 3655 VALUE_RECURSED_INTO (node->loc) = true; 3656 } 3657 } 3658 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; 3668 } 3669 } 3670 3671 if (!onepart_variable_different_p (dvar, s2var)) 3672 { 3673 variable_htab_free (dvar); 3674 *dstslot = dvar = s2var; 3675 dvar->refcount++; 3676 } 3677 else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var)) 3678 { 3679 variable_htab_free (dvar); 3680 *dstslot = dvar = s1var; 3681 dvar->refcount++; 3682 dst_can_be_shared = false; 3683 } 3684 else 3685 dst_can_be_shared = false; 3686 3687 return 1; 3688} 3689 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(). */ 3694 3695static int 3696variable_merge_over_src (variable s2var, struct dfset_merge *dsm) 3697{ 3698 dataflow_set *dst = dsm->dst; 3699 decl_or_value dv = s2var->dv; 3700 bool onepart = dv_onepart_p (dv); 3701 3702 if (!onepart) 3703 { 3704 void **dstp = shared_hash_find_slot (dst->vars, dv); 3705 *dstp = s2var; 3706 s2var->refcount++; 3707 return 1; 3708 } 3709 3710 dsm->src_onepart_cnt++; 3711 return 1; 3712} 3713 3714/* Combine dataflow set information from SRC2 into DST, using PDST 3715 to carry over information across passes. */ 3716 3717static void 3718dataflow_set_merge (dataflow_set *dst, dataflow_set *src2) 3719{ 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; 3727 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); 3738 3739 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 3740 attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]); 3741 3742 dsm.dst = dst; 3743 dsm.src = src2; 3744 dsm.cur = src1; 3745 dsm.src_onepart_cnt = 0; 3746 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); 3751 3752 if (dsm.src_onepart_cnt) 3753 dst_can_be_shared = false; 3754 3755 dataflow_set_destroy (src1); 3756} 3757 3758/* Mark register equivalences. */ 3759 3760static void 3761dataflow_set_equiv_regs (dataflow_set *set) 3762{ 3763 int i; 3764 attrs list, *listp; 3765 3766 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 3767 { 3768 rtx canon[NUM_MACHINE_MODES]; 3769 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; 3774 3775 memset (canon, 0, sizeof (canon)); 3776 3777 for (list = set->regs[i]; list; list = list->next) 3778 if (list->offset == 0 && dv_is_value_p (list->dv)) 3779 { 3780 rtx val = dv_as_value (list->dv); 3781 rtx *cvalp = &canon[(int)GET_MODE (val)]; 3782 rtx cval = *cvalp; 3783 3784 if (canon_value_cmp (val, cval)) 3785 *cvalp = val; 3786 } 3787 3788 for (list = set->regs[i]; list; list = list->next) 3789 if (list->offset == 0 && dv_onepart_p (list->dv)) 3790 { 3791 rtx cval = canon[(int)GET_MODE (list->loc)]; 3792 3793 if (!cval) 3794 continue; 3795 3796 if (dv_is_value_p (list->dv)) 3797 { 3798 rtx val = dv_as_value (list->dv); 3799 3800 if (val == cval) 3801 continue; 3802 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); 3807 } 3808 3809 VALUE_RECURSED_INTO (cval) = true; 3810 set_variable_part (set, cval, list->dv, 0, 3811 VAR_INIT_STATUS_INITIALIZED, NULL, NO_INSERT); 3812 } 3813 3814 for (listp = &set->regs[i]; (list = *listp); 3815 listp = list ? &list->next : listp) 3816 if (list->offset == 0 && dv_onepart_p (list->dv)) 3817 { 3818 rtx cval = canon[(int)GET_MODE (list->loc)]; 3819 void **slot; 3820 3821 if (!cval) 3822 continue; 3823 3824 if (dv_is_value_p (list->dv)) 3825 { 3826 rtx val = dv_as_value (list->dv); 3827 if (!VALUE_RECURSED_INTO (val)) 3828 continue; 3829 } 3830 3831 slot = shared_hash_find_slot_noinsert (set->vars, list->dv); 3832 canonicalize_values_star (slot, set); 3833 if (*listp != list) 3834 list = NULL; 3835 } 3836 } 3837} 3838 3839/* Remove any redundant values in the location list of VAR, which must 3840 be unshared and 1-part. */ 3841 3842static void 3843remove_duplicate_values (variable var) 3844{ 3845 location_chain node, *nodep; 3846 3847 gcc_assert (dv_onepart_p (var->dv)); 3848 gcc_assert (var->n_var_parts == 1); 3849 gcc_assert (var->refcount == 1); 3850 3851 for (nodep = &var->var_part[0].loc_chain; (node = *nodep); ) 3852 { 3853 if (GET_CODE (node->loc) == VALUE) 3854 { 3855 if (VALUE_RECURSED_INTO (node->loc)) 3856 { 3857 /* Remove duplicate value node. */ 3858 *nodep = node->next; 3859 pool_free (loc_chain_pool, node); 3860 continue; 3861 } 3862 else 3863 VALUE_RECURSED_INTO (node->loc) = true; 3864 } 3865 nodep = &node->next; 3866 } 3867 3868 for (node = var->var_part[0].loc_chain; node; node = node->next) 3869 if (GET_CODE (node->loc) == VALUE) 3870 { 3871 gcc_assert (VALUE_RECURSED_INTO (node->loc)); 3872 VALUE_RECURSED_INTO (node->loc) = false; 3873 } 3874} 3875 3876 3877/* Hash table iteration argument passed to variable_post_merge. */ 3878struct dfset_post_merge 3879{ 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; 3885}; 3886 3887/* Create values for incoming expressions associated with one-part 3888 variables that don't have value numbers for them. */ 3889 3890static int 3891variable_post_merge_new_vals (void **slot, void *info) 3892{ 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; 3897 3898 if (!dv_onepart_p (var->dv) || !var->n_var_parts) 3899 return 1; 3900 3901 gcc_assert (var->n_var_parts == 1); 3902 3903 if (dv_is_decl_p (var->dv)) 3904 { 3905 bool check_dupes = false; 3906 3907 restart: 3908 for (node = var->var_part[0].loc_chain; node; node = node->next) 3909 { 3910 if (GET_CODE (node->loc) == VALUE) 3911 gcc_assert (!VALUE_RECURSED_INTO (node->loc)); 3912 else if (GET_CODE (node->loc) == REG) 3913 { 3914 attrs att, *attp, *curp = NULL; 3915 3916 if (var->refcount != 1) 3917 { 3918 slot = unshare_variable (set, slot, var, 3919 VAR_INIT_STATUS_INITIALIZED); 3920 var = (variable)*slot; 3921 goto restart; 3922 } 3923 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)) 3928 { 3929 if (dv_is_value_p (att->dv)) 3930 { 3931 rtx cval = dv_as_value (att->dv); 3932 node->loc = cval; 3933 check_dupes = true; 3934 break; 3935 } 3936 else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv)) 3937 curp = attp; 3938 } 3939 3940 if (!curp) 3941 { 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); 3951 } 3952 3953 if (!att) 3954 { 3955 decl_or_value cdv; 3956 rtx cval; 3957 3958 if (!*dfpm->permp) 3959 { 3960 *dfpm->permp = XNEW (dataflow_set); 3961 dataflow_set_init (*dfpm->permp); 3962 } 3963 3964 for (att = (*dfpm->permp)->regs[REGNO (node->loc)]; 3965 att; att = att->next) 3966 if (GET_MODE (att->loc) == GET_MODE (node->loc)) 3967 { 3968 gcc_assert (att->offset == 0 3969 && dv_is_value_p (att->dv)); 3970 val_reset (set, att->dv); 3971 break; 3972 } 3973 3974 if (att) 3975 { 3976 cdv = att->dv; 3977 cval = dv_as_value (cdv); 3978 } 3979 else 3980 { 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)); 3996 } 3997 3998 var_reg_decl_set (*dfpm->permp, node->loc, 3999 VAR_INIT_STATUS_INITIALIZED, 4000 cdv, 0, NULL, INSERT); 4001 4002 node->loc = cval; 4003 check_dupes = true; 4004 } 4005 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); 4012 } 4013 } 4014 4015 if (check_dupes) 4016 remove_duplicate_values (var); 4017 } 4018 4019 return 1; 4020} 4021 4022/* Reset values in the permanent set that are not associated with the 4023 chosen expression. */ 4024 4025static int 4026variable_post_merge_perm_vals (void **pslot, void *info) 4027{ 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; 4034 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)); 4041 4042 dv = pvar->dv; 4043 4044 var = shared_hash_find (set->vars, dv); 4045 if (var) 4046 { 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); 4056 } 4057 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; 4063 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)) 4067 { 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); 4072 } 4073 else if (!att) 4074 { 4075 attrs_list_insert (&set->regs[REGNO (pnode->loc)], 4076 dv, 0, pnode->loc); 4077 variable_union (pvar, set); 4078 } 4079 4080 return 1; 4081} 4082 4083/* Just checking stuff and registering register attributes for 4084 now. */ 4085 4086static void 4087dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp) 4088{ 4089 struct dfset_post_merge dfpm; 4090 4091 dfpm.set = set; 4092 dfpm.permp = permp; 4093 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); 4101} 4102 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. */ 4106 4107static location_chain 4108find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars) 4109{ 4110 location_chain node; 4111 decl_or_value dv; 4112 variable var; 4113 location_chain where = NULL; 4114 4115 if (!val) 4116 return NULL; 4117 4118 gcc_assert (GET_CODE (val) == VALUE 4119 && !VALUE_RECURSED_INTO (val)); 4120 4121 dv = dv_from_value (val); 4122 var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv)); 4123 4124 if (!var) 4125 return NULL; 4126 4127 gcc_assert (dv_onepart_p (var->dv)); 4128 4129 if (!var->n_var_parts) 4130 return NULL; 4131 4132 gcc_assert (var->var_part[0].offset == 0); 4133 4134 VALUE_RECURSED_INTO (val) = true; 4135 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) 4139 { 4140 where = node; 4141 break; 4142 } 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; 4147 4148 VALUE_RECURSED_INTO (val) = false; 4149 4150 return where; 4151} 4152 4153/* Return TRUE if the value of MEM may vary across a call. */ 4154 4155static bool 4156mem_dies_at_call (rtx mem) 4157{ 4158 tree expr = MEM_EXPR (mem); 4159 tree decl; 4160 4161 if (!expr) 4162 return true; 4163 4164 decl = get_base_address (expr); 4165 4166 if (!decl) 4167 return true; 4168 4169 if (!DECL_P (decl)) 4170 return true; 4171 4172 return (may_be_aliased (decl) 4173 || (!TREE_READONLY (decl) && is_global_var (decl))); 4174} 4175 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. */ 4179 4180static int 4181dataflow_set_preserve_mem_locs (void **slot, void *data) 4182{ 4183 dataflow_set *set = (dataflow_set *) data; 4184 variable var = (variable) *slot; 4185 4186 if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv)) 4187 { 4188 tree decl = dv_as_decl (var->dv); 4189 location_chain loc, *locp; 4190 bool changed = false; 4191 4192 if (!var->n_var_parts) 4193 return 1; 4194 4195 gcc_assert (var->n_var_parts == 1); 4196 4197 if (shared_var_p (var, set->vars)) 4198 { 4199 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) 4200 { 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; 4213 } 4214 4215 if (!loc) 4216 return 1; 4217 4218 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN); 4219 var = (variable)*slot; 4220 gcc_assert (var->n_var_parts == 1); 4221 } 4222 4223 for (locp = &var->var_part[0].loc_chain, loc = *locp; 4224 loc; loc = *locp) 4225 { 4226 rtx old_loc = loc->loc; 4227 if (GET_CODE (old_loc) == VALUE) 4228 { 4229 location_chain mem_node 4230 = find_mem_expr_in_1pdv (decl, loc->loc, 4231 shared_hash_htab (set->vars)); 4232 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) 4240 { 4241 loc->loc = mem_node->loc; 4242 loc->set_src = mem_node->set_src; 4243 loc->init = MIN (loc->init, mem_node->init); 4244 } 4245 } 4246 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)) 4251 { 4252 if (old_loc != loc->loc && emit_notes) 4253 { 4254 if (old_loc == var->var_part[0].cur_loc) 4255 { 4256 changed = true; 4257 var->var_part[0].cur_loc = NULL; 4258 var->cur_loc_changed = true; 4259 } 4260 add_value_chains (var->dv, loc->loc); 4261 remove_value_chains (var->dv, old_loc); 4262 } 4263 locp = &loc->next; 4264 continue; 4265 } 4266 4267 if (emit_notes) 4268 { 4269 remove_value_chains (var->dv, old_loc); 4270 if (old_loc == var->var_part[0].cur_loc) 4271 { 4272 changed = true; 4273 var->var_part[0].cur_loc = NULL; 4274 var->cur_loc_changed = true; 4275 } 4276 } 4277 *locp = loc->next; 4278 pool_free (loc_chain_pool, loc); 4279 } 4280 4281 if (!var->var_part[0].loc_chain) 4282 { 4283 var->n_var_parts--; 4284 changed = true; 4285 } 4286 if (changed) 4287 variable_was_changed (var, set); 4288 } 4289 4290 return 1; 4291} 4292 4293/* Remove all MEMs from the location list of a hash table entry for a 4294 value. */ 4295 4296static int 4297dataflow_set_remove_mem_locs (void **slot, void *data) 4298{ 4299 dataflow_set *set = (dataflow_set *) data; 4300 variable var = (variable) *slot; 4301 4302 if (dv_is_value_p (var->dv)) 4303 { 4304 location_chain loc, *locp; 4305 bool changed = false; 4306 4307 gcc_assert (var->n_var_parts == 1); 4308 4309 if (shared_var_p (var, set->vars)) 4310 { 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; 4315 4316 if (!loc) 4317 return 1; 4318 4319 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN); 4320 var = (variable)*slot; 4321 gcc_assert (var->n_var_parts == 1); 4322 } 4323 4324 for (locp = &var->var_part[0].loc_chain, loc = *locp; 4325 loc; loc = *locp) 4326 { 4327 if (GET_CODE (loc->loc) != MEM 4328 || !mem_dies_at_call (loc->loc)) 4329 { 4330 locp = &loc->next; 4331 continue; 4332 } 4333 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) 4341 { 4342 changed = true; 4343 var->var_part[0].cur_loc = NULL; 4344 var->cur_loc_changed = true; 4345 } 4346 pool_free (loc_chain_pool, loc); 4347 } 4348 4349 if (!var->var_part[0].loc_chain) 4350 { 4351 var->n_var_parts--; 4352 changed = true; 4353 } 4354 if (changed) 4355 variable_was_changed (var, set); 4356 } 4357 4358 return 1; 4359} 4360 4361/* Remove all variable-location information about call-clobbered 4362 registers, as well as associations between MEMs and VALUEs. */ 4363 4364static void 4365dataflow_set_clear_at_call (dataflow_set *set) 4366{ 4367 int r; 4368 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); 4372 4373 if (MAY_HAVE_DEBUG_INSNS) 4374 { 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; 4382 } 4383} 4384 4385static bool 4386variable_part_different_p (variable_part *vp1, variable_part *vp2) 4387{ 4388 location_chain lc1, lc2; 4389 4390 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next) 4391 { 4392 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next) 4393 { 4394 if (REG_P (lc1->loc) && REG_P (lc2->loc)) 4395 { 4396 if (REGNO (lc1->loc) == REGNO (lc2->loc)) 4397 break; 4398 } 4399 if (rtx_equal_p (lc1->loc, lc2->loc)) 4400 break; 4401 } 4402 if (!lc2) 4403 return true; 4404 } 4405 return false; 4406} 4407 4408/* Return true if one-part variables VAR1 and VAR2 are different. 4409 They must be in canonical order. */ 4410 4411static bool 4412onepart_variable_different_p (variable var1, variable var2) 4413{ 4414 location_chain lc1, lc2; 4415 4416 if (var1 == var2) 4417 return false; 4418 4419 gcc_assert (var1->n_var_parts == 1 4420 && var2->n_var_parts == 1); 4421 4422 lc1 = var1->var_part[0].loc_chain; 4423 lc2 = var2->var_part[0].loc_chain; 4424 4425 gcc_assert (lc1 && lc2); 4426 4427 while (lc1 && lc2) 4428 { 4429 if (loc_cmp (lc1->loc, lc2->loc)) 4430 return true; 4431 lc1 = lc1->next; 4432 lc2 = lc2->next; 4433 } 4434 4435 return lc1 != lc2; 4436} 4437 4438/* Return true if variables VAR1 and VAR2 are different. */ 4439 4440static bool 4441variable_different_p (variable var1, variable var2) 4442{ 4443 int i; 4444 4445 if (var1 == var2) 4446 return false; 4447 4448 if (var1->n_var_parts != var2->n_var_parts) 4449 return true; 4450 4451 for (i = 0; i < var1->n_var_parts; i++) 4452 { 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)) 4457 { 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); 4461 } 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; 4466 } 4467 return false; 4468} 4469 4470/* Return true if dataflow sets OLD_SET and NEW_SET differ. */ 4471 4472static bool 4473dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set) 4474{ 4475 htab_iterator hi; 4476 variable var1; 4477 4478 if (old_set->vars == new_set->vars) 4479 return false; 4480 4481 if (htab_elements (shared_hash_htab (old_set->vars)) 4482 != htab_elements (shared_hash_htab (new_set->vars))) 4483 return true; 4484 4485 FOR_EACH_HTAB_ELEMENT (shared_hash_htab (old_set->vars), var1, variable, hi) 4486 { 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) 4491 { 4492 if (dump_file && (dump_flags & TDF_DETAILS)) 4493 { 4494 fprintf (dump_file, "dataflow difference found: removal of:\n"); 4495 dump_var (var1); 4496 } 4497 return true; 4498 } 4499 4500 if (variable_different_p (var1, var2)) 4501 { 4502 if (dump_file && (dump_flags & TDF_DETAILS)) 4503 { 4504 fprintf (dump_file, "dataflow difference found: " 4505 "old and new follow:\n"); 4506 dump_var (var1); 4507 dump_var (var2); 4508 } 4509 return true; 4510 } 4511 } 4512 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; 4517} 4518 4519/* Free the contents of dataflow set SET. */ 4520 4521static void 4522dataflow_set_destroy (dataflow_set *set) 4523{ 4524 int i; 4525 4526 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 4527 attrs_list_clear (&set->regs[i]); 4528 4529 shared_hash_destroy (set->vars); 4530 set->vars = NULL; 4531} 4532 4533/* Return true if RTL X contains a SYMBOL_REF. */ 4534 4535static bool 4536contains_symbol_ref (rtx x) 4537{ 4538 const char *fmt; 4539 RTX_CODE code; 4540 int i; 4541 4542 if (!x) 4543 return false; 4544 4545 code = GET_CODE (x); 4546 if (code == SYMBOL_REF) 4547 return true; 4548 4549 fmt = GET_RTX_FORMAT (code); 4550 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 4551 { 4552 if (fmt[i] == 'e') 4553 { 4554 if (contains_symbol_ref (XEXP (x, i))) 4555 return true; 4556 } 4557 else if (fmt[i] == 'E') 4558 { 4559 int j; 4560 for (j = 0; j < XVECLEN (x, i); j++) 4561 if (contains_symbol_ref (XVECEXP (x, i, j))) 4562 return true; 4563 } 4564 } 4565 4566 return false; 4567} 4568 4569/* Shall EXPR be tracked? */ 4570 4571static bool 4572track_expr_p (tree expr, bool need_rtl) 4573{ 4574 rtx decl_rtl; 4575 tree realdecl; 4576 4577 if (TREE_CODE (expr) == DEBUG_EXPR_DECL) 4578 return DECL_RTL_SET_P (expr); 4579 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; 4583 4584 /* It also must have a name... */ 4585 if (!DECL_NAME (expr) && need_rtl) 4586 return 0; 4587 4588 /* ... and a RTL assigned to it. */ 4589 decl_rtl = DECL_RTL_IF_SET (expr); 4590 if (!decl_rtl && need_rtl) 4591 return 0; 4592 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)) 4598 { 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; 4604 } 4605 4606 /* Do not track EXPR if REALDECL it should be ignored for debugging 4607 purposes. */ 4608 if (DECL_IGNORED_P (realdecl)) 4609 return 0; 4610 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; 4615 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. 4619 4620 Example: 4621 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv"))); 4622 char **_dl_argv; 4623 */ 4624 if (decl_rtl && MEM_P (decl_rtl) 4625 && contains_symbol_ref (XEXP (decl_rtl, 0))) 4626 return 0; 4627 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)) 4631 { 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; 4639 } 4640 4641 DECL_CHANGED (expr) = 0; 4642 DECL_CHANGED (realdecl) = 0; 4643 return 1; 4644} 4645 4646/* Determine whether a given LOC refers to the same variable part as 4647 EXPR+OFFSET. */ 4648 4649static bool 4650same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) 4651{ 4652 tree expr2; 4653 HOST_WIDE_INT offset2; 4654 4655 if (! DECL_P (expr)) 4656 return false; 4657 4658 if (REG_P (loc)) 4659 { 4660 expr2 = REG_EXPR (loc); 4661 offset2 = REG_OFFSET (loc); 4662 } 4663 else if (MEM_P (loc)) 4664 { 4665 expr2 = MEM_EXPR (loc); 4666 offset2 = INT_MEM_OFFSET (loc); 4667 } 4668 else 4669 return false; 4670 4671 if (! expr2 || ! DECL_P (expr2)) 4672 return false; 4673 4674 expr = var_debug_decl (expr); 4675 expr2 = var_debug_decl (expr2); 4676 4677 return (expr == expr2 && offset == offset2); 4678} 4679 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. 4684 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). */ 4689 4690static bool 4691track_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) 4693{ 4694 enum machine_mode mode; 4695 4696 if (expr == NULL || !track_expr_p (expr, true)) 4697 return false; 4698 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))) 4703 { 4704 enum machine_mode pseudo_mode; 4705 4706 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc)); 4707 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode)) 4708 { 4709 offset += byte_lowpart_offset (pseudo_mode, mode); 4710 mode = pseudo_mode; 4711 } 4712 } 4713 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) 4726 { 4727 mode = DECL_MODE (expr); 4728 offset = 0; 4729 } 4730 4731 if (offset < 0 || offset >= MAX_VAR_PARTS) 4732 return false; 4733 4734 if (mode_out) 4735 *mode_out = mode; 4736 if (offset_out) 4737 *offset_out = offset; 4738 return true; 4739} 4740 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. */ 4744 4745static rtx 4746var_lowpart (enum machine_mode mode, rtx loc) 4747{ 4748 unsigned int offset, reg_offset, regno; 4749 4750 if (!REG_P (loc) && !MEM_P (loc)) 4751 return NULL; 4752 4753 if (GET_MODE (loc) == mode) 4754 return loc; 4755 4756 offset = byte_lowpart_offset (mode, GET_MODE (loc)); 4757 4758 if (MEM_P (loc)) 4759 return adjust_address_nv (loc, mode, offset); 4760 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); 4765} 4766 4767/* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or 4768 hard_frame_pointer_rtx is being mapped to it. */ 4769static rtx cfa_base_rtx; 4770 4771/* Carry information about uses and stores while walking rtx. */ 4772 4773struct count_use_info 4774{ 4775 /* The insn where the RTX is. */ 4776 rtx insn; 4777 4778 /* The basic block where insn is. */ 4779 basic_block bb; 4780 4781 /* The array of n_sets sets in the insn, as determined by cselib. */ 4782 struct cselib_set *sets; 4783 int n_sets; 4784 4785 /* True if we're counting stores, false otherwise. */ 4786 bool store_p; 4787}; 4788 4789/* Find a VALUE corresponding to X. */ 4790 4791static inline cselib_val * 4792find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui) 4793{ 4794 int i; 4795 4796 if (cui->sets) 4797 { 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) 4804 { 4805 for (i = 0; i < cui->n_sets; i++) 4806 if (cui->sets[i].dest == x) 4807 return cui->sets[i].src_elt; 4808 } 4809 else 4810 return cselib_lookup (x, mode, 0); 4811 } 4812 4813 return NULL; 4814} 4815 4816/* Helper function to get mode of MEM's address. */ 4817 4818static inline enum machine_mode 4819get_address_mode (rtx mem) 4820{ 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)); 4825} 4826 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. */ 4830 4831static rtx 4832replace_expr_with_values (rtx loc) 4833{ 4834 if (REG_P (loc)) 4835 return NULL; 4836 else if (MEM_P (loc)) 4837 { 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; 4844 } 4845 else 4846 return cselib_subst_to_values (loc); 4847} 4848 4849/* Determine what kind of micro operation to choose for a USE. Return 4850 MO_CLOBBER if no micro operation is to be generated. */ 4851 4852static enum micro_operation_type 4853use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep) 4854{ 4855 tree expr; 4856 4857 if (cui && cui->sets) 4858 { 4859 if (GET_CODE (loc) == VAR_LOCATION) 4860 { 4861 if (track_expr_p (PAT_VAR_LOCATION_DECL (loc), false)) 4862 { 4863 rtx ploc = PAT_VAR_LOCATION_LOC (loc); 4864 if (! VAR_LOC_UNKNOWN_P (ploc)) 4865 { 4866 cselib_val *val = cselib_lookup (ploc, GET_MODE (loc), 1); 4867 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); 4872 } 4873 return MO_VAL_LOC; 4874 } 4875 else 4876 return MO_CLOBBER; 4877 } 4878 4879 if (REG_P (loc) || MEM_P (loc)) 4880 { 4881 if (modep) 4882 *modep = GET_MODE (loc); 4883 if (cui->store_p) 4884 { 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; 4890 } 4891 else 4892 { 4893 cselib_val *val = find_use_val (loc, GET_MODE (loc), cui); 4894 4895 if (val && !cselib_preserved_value_p (val)) 4896 return MO_VAL_USE; 4897 } 4898 } 4899 } 4900 4901 if (REG_P (loc)) 4902 { 4903 gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER); 4904 4905 if (loc == cfa_base_rtx) 4906 return MO_CLOBBER; 4907 expr = REG_EXPR (loc); 4908 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; 4918 } 4919 else if (MEM_P (loc)) 4920 { 4921 expr = MEM_EXPR (loc); 4922 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; 4932 } 4933 4934 return MO_CLOBBER; 4935} 4936 4937/* Log to OUT information about micro-operation MOPT involving X in 4938 INSN of BB. */ 4939 4940static inline void 4941log_op_type (rtx x, basic_block bb, rtx insn, 4942 enum micro_operation_type mopt, FILE *out) 4943{ 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); 4949} 4950 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) 4972 4973/* All preserved VALUEs. */ 4974static VEC (rtx, heap) *preserved_values; 4975 4976/* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */ 4977 4978static void 4979preserve_value (cselib_val *val) 4980{ 4981 cselib_preserve_value (val); 4982 VEC_safe_push (rtx, heap, preserved_values, val->val_rtx); 4983} 4984 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. */ 4988 4989static int 4990non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED) 4991{ 4992 if (*x == NULL_RTX) 4993 return 0; 4994 4995 switch (GET_CODE (*x)) 4996 { 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; 5009 } 5010} 5011 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. */ 5014 5015static int 5016add_uses (rtx *ploc, void *data) 5017{ 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); 5022 5023 if (type != MO_CLOBBER) 5024 { 5025 basic_block bb = cui->bb; 5026 micro_operation mo; 5027 5028 mo.type = type; 5029 mo.u.loc = type == MO_USE ? var_lowpart (mode, loc) : loc; 5030 mo.insn = cui->insn; 5031 5032 if (type == MO_VAL_LOC) 5033 { 5034 rtx oloc = loc; 5035 rtx vloc = PAT_VAR_LOCATION_LOC (oloc); 5036 cselib_val *val; 5037 5038 gcc_assert (cui->sets); 5039 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)))) 5046 { 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); 5051 5052 if (val && !cselib_preserved_value_p (val)) 5053 { 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); 5065 } 5066 } 5067 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))) 5074 { 5075 enum machine_mode mode2; 5076 enum micro_operation_type type2; 5077 rtx nloc = replace_expr_with_values (vloc); 5078 5079 if (nloc) 5080 { 5081 oloc = shallow_copy_rtx (oloc); 5082 PAT_VAR_LOCATION_LOC (oloc) = nloc; 5083 } 5084 5085 oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc); 5086 5087 type2 = use_type (vloc, 0, &mode2); 5088 5089 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR 5090 || type2 == MO_CLOBBER); 5091 5092 if (type2 == MO_CLOBBER 5093 && !cselib_preserved_value_p (val)) 5094 { 5095 VAL_NEEDS_RESOLUTION (oloc) = 1; 5096 preserve_value (val); 5097 } 5098 } 5099 else if (!VAR_LOC_UNKNOWN_P (vloc)) 5100 { 5101 oloc = shallow_copy_rtx (oloc); 5102 PAT_VAR_LOCATION_LOC (oloc) = gen_rtx_UNKNOWN_VAR_LOC (); 5103 } 5104 5105 mo.u.loc = oloc; 5106 } 5107 else if (type == MO_VAL_USE) 5108 { 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; 5113 5114 gcc_assert (cui->sets); 5115 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)))) 5122 { 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); 5127 5128 if (val && !cselib_preserved_value_p (val)) 5129 { 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); 5141 } 5142 } 5143 5144 type2 = use_type (loc, 0, &mode2); 5145 5146 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR 5147 || type2 == MO_CLOBBER); 5148 5149 if (type2 == MO_USE) 5150 vloc = var_lowpart (mode2, loc); 5151 else 5152 vloc = oloc; 5153 5154 /* The loc of a MO_VAL_USE may have two forms: 5155 5156 (concat val src): val is at src, a value-based 5157 representation. 5158 5159 (concat (concat val use) src): same as above, with use as 5160 the MO_USE tracked value, if it differs from src. 5161 5162 */ 5163 5164 nloc = replace_expr_with_values (loc); 5165 if (!nloc) 5166 nloc = oloc; 5167 5168 if (vloc != nloc) 5169 oloc = gen_rtx_CONCAT (mode2, val->val_rtx, vloc); 5170 else 5171 oloc = val->val_rtx; 5172 5173 mo.u.loc = gen_rtx_CONCAT (mode, oloc, nloc); 5174 5175 if (type2 == MO_USE) 5176 VAL_HOLDS_TRACK_EXPR (mo.u.loc) = 1; 5177 if (!cselib_preserved_value_p (val)) 5178 { 5179 VAL_NEEDS_RESOLUTION (mo.u.loc) = 1; 5180 preserve_value (val); 5181 } 5182 } 5183 else 5184 gcc_assert (type == MO_USE || type == MO_USE_NO_VAR); 5185 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); 5189 } 5190 5191 return 0; 5192} 5193 5194/* Helper function for finding all uses of REG/MEM in X in insn INSN. */ 5195 5196static void 5197add_uses_1 (rtx *x, void *cui) 5198{ 5199 for_each_rtx (x, add_uses, cui); 5200} 5201 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. */ 5205 5206static rtx 5207reverse_op (rtx val, const_rtx expr) 5208{ 5209 rtx src, arg, ret; 5210 cselib_val *v; 5211 enum rtx_code code; 5212 5213 if (GET_CODE (expr) != SET) 5214 return NULL_RTX; 5215 5216 if (!REG_P (SET_DEST (expr)) || GET_MODE (val) != GET_MODE (SET_DEST (expr))) 5217 return NULL_RTX; 5218 5219 src = SET_SRC (expr); 5220 switch (GET_CODE (src)) 5221 { 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; 5232 } 5233 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; 5238 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; 5242 5243 switch (GET_CODE (src)) 5244 { 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) 5269 { 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; 5275 } 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 (); 5285 } 5286 5287 return gen_rtx_CONCAT (GET_MODE (v->val_rtx), v->val_rtx, ret); 5288} 5289 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. */ 5293 5294static void 5295add_stores (rtx loc, const_rtx expr, void *cuip) 5296{ 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; 5307 5308 if (type == MO_CLOBBER) 5309 return; 5310 5311 mode2 = mode; 5312 5313 if (REG_P (loc)) 5314 { 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) 5319 { 5320 mo.type = MO_CLOBBER; 5321 mo.u.loc = loc; 5322 } 5323 else 5324 { 5325 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc) 5326 src = var_lowpart (mode2, SET_SRC (expr)); 5327 loc = var_lowpart (mode2, loc); 5328 5329 if (src == NULL) 5330 { 5331 mo.type = MO_SET; 5332 mo.u.loc = loc; 5333 } 5334 else 5335 { 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; 5342 } 5343 } 5344 mo.insn = cui->insn; 5345 } 5346 else if (MEM_P (loc) 5347 && ((track_p = use_type (loc, NULL, &mode2) == MO_USE) 5348 || cui->sets)) 5349 { 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)))) 5356 { 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); 5361 5362 if (val && !cselib_preserved_value_p (val)) 5363 { 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); 5373 } 5374 } 5375 5376 if (GET_CODE (expr) == CLOBBER || !track_p) 5377 { 5378 mo.type = MO_CLOBBER; 5379 mo.u.loc = track_p ? var_lowpart (mode2, loc) : loc; 5380 } 5381 else 5382 { 5383 if (GET_CODE (expr) == SET && SET_DEST (expr) == loc) 5384 src = var_lowpart (mode2, SET_SRC (expr)); 5385 loc = var_lowpart (mode2, loc); 5386 5387 if (src == NULL) 5388 { 5389 mo.type = MO_SET; 5390 mo.u.loc = loc; 5391 } 5392 else 5393 { 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; 5402 } 5403 } 5404 mo.insn = cui->insn; 5405 } 5406 else 5407 return; 5408 5409 if (type != MO_VAL_SET) 5410 goto log_and_return; 5411 5412 v = find_use_val (oloc, mode, cui); 5413 5414 if (!v) 5415 goto log_and_return; 5416 5417 resolve = preserve = !cselib_preserved_value_p (v); 5418 5419 nloc = replace_expr_with_values (oloc); 5420 if (nloc) 5421 oloc = nloc; 5422 5423 if (GET_CODE (PATTERN (cui->insn)) == COND_EXEC) 5424 { 5425 cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0); 5426 5427 gcc_assert (oval != v); 5428 gcc_assert (REG_P (oloc) || MEM_P (oloc)); 5429 5430 if (!cselib_preserved_value_p (oval)) 5431 { 5432 micro_operation moa; 5433 5434 preserve_value (oval); 5435 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; 5440 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); 5445 } 5446 5447 resolve = false; 5448 } 5449 else if (resolve && GET_CODE (mo.u.loc) == SET) 5450 { 5451 nloc = replace_expr_with_values (SET_SRC (expr)); 5452 5453 /* Avoid the mode mismatch between oexpr and expr. */ 5454 if (!nloc && mode != mode2) 5455 { 5456 nloc = SET_SRC (expr); 5457 gcc_assert (oloc == SET_DEST (expr)); 5458 } 5459 5460 if (nloc) 5461 oloc = gen_rtx_SET (GET_MODE (mo.u.loc), oloc, nloc); 5462 else 5463 { 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; 5469 } 5470 } 5471 else if (!resolve) 5472 { 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; 5477 } 5478 else 5479 resolve = false; 5480 5481 loc = gen_rtx_CONCAT (mode, v->val_rtx, oloc); 5482 5483 if (mo.u.loc != oloc) 5484 loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, mo.u.loc); 5485 5486 /* The loc of a MO_VAL_SET may have various forms: 5487 5488 (concat val dst): dst now holds val 5489 5490 (concat val (set dst src)): dst now holds val, copied from src 5491 5492 (concat (concat val dstv) dst): dst now holds val; dstv is dst 5493 after replacing mems and non-top-level regs with values. 5494 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. 5499 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. 5503 5504 */ 5505 5506 if (GET_CODE (PATTERN (cui->insn)) != COND_EXEC) 5507 { 5508 reverse = reverse_op (v->val_rtx, expr); 5509 if (reverse) 5510 { 5511 loc = gen_rtx_CONCAT (GET_MODE (mo.u.loc), loc, reverse); 5512 VAL_EXPR_HAS_REVERSE (loc) = 1; 5513 } 5514 } 5515 5516 mo.u.loc = loc; 5517 5518 if (track_p) 5519 VAL_HOLDS_TRACK_EXPR (loc) = 1; 5520 if (preserve) 5521 { 5522 VAL_NEEDS_RESOLUTION (loc) = resolve; 5523 preserve_value (v); 5524 } 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; 5529 5530 mo.type = MO_VAL_SET; 5531 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); 5536} 5537 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). */ 5544 5545static void 5546add_with_sets (rtx insn, struct cselib_set *sets, int n_sets) 5547{ 5548 basic_block bb = BLOCK_FOR_INSN (insn); 5549 int n1, n2; 5550 struct count_use_info cui; 5551 micro_operation *mos; 5552 5553 cselib_hook_called = true; 5554 5555 cui.insn = insn; 5556 cui.bb = bb; 5557 cui.sets = sets; 5558 cui.n_sets = n_sets; 5559 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); 5565 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) 5569 { 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) 5575 { 5576 micro_operation sw; 5577 5578 sw = mos[n1]; 5579 mos[n1] = mos[n2]; 5580 mos[n2] = sw; 5581 } 5582 } 5583 5584 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1; 5585 while (n1 < n2) 5586 { 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) 5592 { 5593 micro_operation sw; 5594 5595 sw = mos[n1]; 5596 mos[n1] = mos[n2]; 5597 mos[n2] = sw; 5598 } 5599 } 5600 5601 if (CALL_P (insn)) 5602 { 5603 micro_operation mo; 5604 5605 mo.type = MO_CALL; 5606 mo.insn = insn; 5607 mo.u.loc = NULL_RTX; 5608 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); 5612 } 5613 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); 5622 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) 5627 { 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) 5633 { 5634 micro_operation sw; 5635 5636 sw = mos[n1]; 5637 mos[n1] = mos[n2]; 5638 mos[n2] = sw; 5639 } 5640 } 5641 5642 n2 = VEC_length (micro_operation, VTI (bb)->mos) - 1; 5643 while (n1 < n2) 5644 { 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) 5650 { 5651 micro_operation sw; 5652 5653 sw = mos[n1]; 5654 mos[n1] = mos[n2]; 5655 mos[n2] = sw; 5656 } 5657 } 5658} 5659 5660static enum var_init_status 5661find_src_status (dataflow_set *in, rtx src) 5662{ 5663 tree decl = NULL_TREE; 5664 enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED; 5665 5666 if (! flag_var_tracking_uninit) 5667 status = VAR_INIT_STATUS_INITIALIZED; 5668 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)); 5673 5674 if (src && decl) 5675 status = get_init_value (in, src, dv_from_decl (decl)); 5676 5677 return status; 5678} 5679 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. */ 5683 5684static rtx 5685find_src_set_src (dataflow_set *set, rtx src) 5686{ 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; 5693 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)); 5698 5699 if (src && decl) 5700 { 5701 decl_or_value dv = dv_from_decl (decl); 5702 5703 var = shared_hash_find (set->vars, dv); 5704 if (var) 5705 { 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)) 5711 { 5712 set_src = nextp->set_src; 5713 found = true; 5714 } 5715 5716 } 5717 } 5718 5719 return set_src; 5720} 5721 5722/* Compute the changes of variable locations in the basic block BB. */ 5723 5724static bool 5725compute_bb_dataflow (basic_block bb) 5726{ 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; 5733 5734 dataflow_set_init (&old_out); 5735 dataflow_set_copy (&old_out, out); 5736 dataflow_set_copy (out, in); 5737 5738 for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++) 5739 { 5740 rtx insn = mo->insn; 5741 5742 switch (mo->type) 5743 { 5744 case MO_CALL: 5745 dataflow_set_clear_at_call (out); 5746 break; 5747 5748 case MO_USE: 5749 { 5750 rtx loc = mo->u.loc; 5751 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); 5756 } 5757 break; 5758 5759 case MO_VAL_LOC: 5760 { 5761 rtx loc = mo->u.loc; 5762 rtx val, vloc; 5763 tree var; 5764 5765 if (GET_CODE (loc) == CONCAT) 5766 { 5767 val = XEXP (loc, 0); 5768 vloc = XEXP (loc, 1); 5769 } 5770 else 5771 { 5772 val = NULL_RTX; 5773 vloc = loc; 5774 } 5775 5776 var = PAT_VAR_LOCATION_DECL (vloc); 5777 5778 clobber_variable_part (out, NULL_RTX, 5779 dv_from_decl (var), 0, NULL_RTX); 5780 if (val) 5781 { 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); 5787 } 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); 5793 } 5794 break; 5795 5796 case MO_VAL_USE: 5797 { 5798 rtx loc = mo->u.loc; 5799 rtx val, vloc, uloc; 5800 5801 vloc = uloc = XEXP (loc, 1); 5802 val = XEXP (loc, 0); 5803 5804 if (GET_CODE (val) == CONCAT) 5805 { 5806 uloc = XEXP (val, 1); 5807 val = XEXP (val, 0); 5808 } 5809 5810 if (VAL_NEEDS_RESOLUTION (loc)) 5811 val_resolve (out, val, vloc, insn); 5812 else 5813 val_store (out, val, uloc, insn, false); 5814 5815 if (VAL_HOLDS_TRACK_EXPR (loc)) 5816 { 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); 5823 } 5824 } 5825 break; 5826 5827 case MO_VAL_SET: 5828 { 5829 rtx loc = mo->u.loc; 5830 rtx val, vloc, uloc, reverse = NULL_RTX; 5831 5832 vloc = loc; 5833 if (VAL_EXPR_HAS_REVERSE (loc)) 5834 { 5835 reverse = XEXP (loc, 1); 5836 vloc = XEXP (loc, 0); 5837 } 5838 uloc = XEXP (vloc, 1); 5839 val = XEXP (vloc, 0); 5840 vloc = uloc; 5841 5842 if (GET_CODE (val) == CONCAT) 5843 { 5844 vloc = XEXP (val, 1); 5845 val = XEXP (val, 0); 5846 } 5847 5848 if (GET_CODE (vloc) == SET) 5849 { 5850 rtx vsrc = SET_SRC (vloc); 5851 5852 gcc_assert (val != vsrc); 5853 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc)); 5854 5855 vloc = SET_DEST (vloc); 5856 5857 if (VAL_NEEDS_RESOLUTION (loc)) 5858 val_resolve (out, val, vsrc, insn); 5859 } 5860 else if (VAL_NEEDS_RESOLUTION (loc)) 5861 { 5862 gcc_assert (GET_CODE (uloc) == SET 5863 && GET_CODE (SET_SRC (uloc)) == REG); 5864 val_resolve (out, val, SET_SRC (uloc), insn); 5865 } 5866 5867 if (VAL_HOLDS_TRACK_EXPR (loc)) 5868 { 5869 if (VAL_EXPR_IS_CLOBBERED (loc)) 5870 { 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); 5875 } 5876 else 5877 { 5878 bool copied_p = VAL_EXPR_IS_COPIED (loc); 5879 rtx set_src = NULL; 5880 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED; 5881 5882 if (GET_CODE (uloc) == SET) 5883 { 5884 set_src = SET_SRC (uloc); 5885 uloc = SET_DEST (uloc); 5886 } 5887 5888 if (copied_p) 5889 { 5890 if (flag_var_tracking_uninit) 5891 { 5892 status = find_src_status (in, set_src); 5893 5894 if (status == VAR_INIT_STATUS_UNKNOWN) 5895 status = find_src_status (out, set_src); 5896 } 5897 5898 set_src = find_src_set_src (in, set_src); 5899 } 5900 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); 5907 } 5908 } 5909 else if (REG_P (uloc)) 5910 var_regno_delete (out, REGNO (uloc)); 5911 5912 val_store (out, val, vloc, insn, true); 5913 5914 if (reverse) 5915 val_store (out, XEXP (reverse, 0), XEXP (reverse, 1), 5916 insn, false); 5917 } 5918 break; 5919 5920 case MO_SET: 5921 { 5922 rtx loc = mo->u.loc; 5923 rtx set_src = NULL; 5924 5925 if (GET_CODE (loc) == SET) 5926 { 5927 set_src = SET_SRC (loc); 5928 loc = SET_DEST (loc); 5929 } 5930 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); 5937 } 5938 break; 5939 5940 case MO_COPY: 5941 { 5942 rtx loc = mo->u.loc; 5943 enum var_init_status src_status; 5944 rtx set_src = NULL; 5945 5946 if (GET_CODE (loc) == SET) 5947 { 5948 set_src = SET_SRC (loc); 5949 loc = SET_DEST (loc); 5950 } 5951 5952 if (! flag_var_tracking_uninit) 5953 src_status = VAR_INIT_STATUS_INITIALIZED; 5954 else 5955 { 5956 src_status = find_src_status (in, set_src); 5957 5958 if (src_status == VAR_INIT_STATUS_UNKNOWN) 5959 src_status = find_src_status (out, set_src); 5960 } 5961 5962 set_src = find_src_set_src (in, set_src); 5963 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); 5968 } 5969 break; 5970 5971 case MO_USE_NO_VAR: 5972 { 5973 rtx loc = mo->u.loc; 5974 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); 5979 } 5980 break; 5981 5982 case MO_CLOBBER: 5983 { 5984 rtx loc = mo->u.loc; 5985 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); 5990 } 5991 break; 5992 5993 case MO_ADJUST: 5994 out->stack_adjust += mo->u.adjust; 5995 break; 5996 } 5997 } 5998 5999 if (MAY_HAVE_DEBUG_INSNS) 6000 { 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 6010 } 6011 changed = dataflow_set_different (&old_out, out); 6012 dataflow_set_destroy (&old_out); 6013 return changed; 6014} 6015 6016/* Find the locations of variables in the whole function. */ 6017 6018static bool 6019vt_find_locations (void) 6020{ 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; 6031 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); 6040 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); 6047 6048 FOR_EACH_BB (bb) 6049 fibheap_insert (pending, bb_order[bb->index], bb); 6050 sbitmap_ones (in_pending); 6051 6052 while (success && !fibheap_empty (pending)) 6053 { 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; 6060 6061 sbitmap_zero (visited); 6062 6063 while (!fibheap_empty (worklist)) 6064 { 6065 bb = (basic_block) fibheap_extract_min (worklist); 6066 RESET_BIT (in_worklist, bb->index); 6067 if (!TEST_BIT (visited, bb->index)) 6068 { 6069 bool changed; 6070 edge_iterator ei; 6071 int oldinsz, oldoutsz; 6072 6073 SET_BIT (visited, bb->index); 6074 6075 if (VTI (bb)->in.vars) 6076 { 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)); 6084 } 6085 else 6086 oldinsz = oldoutsz = 0; 6087 6088 if (MAY_HAVE_DEBUG_INSNS) 6089 { 6090 dataflow_set *in = &VTI (bb)->in, *first_out = NULL; 6091 bool first = true, adjust = false; 6092 6093 /* Calculate the IN set as the intersection of 6094 predecessor OUT sets. */ 6095 6096 dataflow_set_clear (in); 6097 dst_can_be_shared = true; 6098 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) 6104 { 6105 dataflow_set_copy (in, &VTI (e->src)->out); 6106 first_out = &VTI (e->src)->out; 6107 first = false; 6108 } 6109 else 6110 { 6111 dataflow_set_merge (in, &VTI (e->src)->out); 6112 adjust = true; 6113 } 6114 6115 if (adjust) 6116 { 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) 6126 { 6127 shared_hash_destroy (in->vars); 6128 in->vars = shared_hash_copy (first_out->vars); 6129 } 6130 } 6131 6132 VTI (bb)->flooded = true; 6133 } 6134 else 6135 { 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); 6140 } 6141 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))); 6145 6146 if (htabmax && htabsz > htabmax) 6147 { 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; 6157 } 6158 6159 if (changed) 6160 { 6161 FOR_EACH_EDGE (e, ei, bb->succs) 6162 { 6163 if (e->dest == EXIT_BLOCK_PTR) 6164 continue; 6165 6166 if (TEST_BIT (visited, e->dest->index)) 6167 { 6168 if (!TEST_BIT (in_pending, e->dest->index)) 6169 { 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); 6175 } 6176 } 6177 else if (!TEST_BIT (in_worklist, e->dest->index)) 6178 { 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); 6183 } 6184 } 6185 } 6186 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); 6196 6197 if (dump_file && (dump_flags & TDF_DETAILS)) 6198 { 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); 6203 } 6204 } 6205 } 6206 } 6207 6208 if (success && MAY_HAVE_DEBUG_INSNS) 6209 FOR_EACH_BB (bb) 6210 gcc_assert (VTI (bb)->flooded); 6211 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); 6218 6219 return success; 6220} 6221 6222/* Print the content of the LIST to dump file. */ 6223 6224static void 6225dump_attrs_list (attrs list) 6226{ 6227 for (; list; list = list->next) 6228 { 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); 6234 } 6235 fprintf (dump_file, "\n"); 6236} 6237 6238/* Print the information about variable *SLOT to dump file. */ 6239 6240static int 6241dump_var_slot (void **slot, void *data ATTRIBUTE_UNUSED) 6242{ 6243 variable var = (variable) *slot; 6244 6245 dump_var (var); 6246 6247 /* Continue traversing the hash table. */ 6248 return 1; 6249} 6250 6251/* Print the information about variable VAR to dump file. */ 6252 6253static void 6254dump_var (variable var) 6255{ 6256 int i; 6257 location_chain node; 6258 6259 if (dv_is_decl_p (var->dv)) 6260 { 6261 const_tree decl = dv_as_decl (var->dv); 6262 6263 if (DECL_NAME (decl)) 6264 { 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)); 6269 } 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"); 6275 } 6276 else 6277 { 6278 fputc (' ', dump_file); 6279 print_rtl_single (dump_file, dv_as_value (var->dv)); 6280 } 6281 6282 for (i = 0; i < var->n_var_parts; i++) 6283 { 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) 6287 { 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); 6292 } 6293 } 6294} 6295 6296/* Print the information about variables from hash table VARS to dump file. */ 6297 6298static void 6299dump_vars (htab_t vars) 6300{ 6301 if (htab_elements (vars) > 0) 6302 { 6303 fprintf (dump_file, "Variables:\n"); 6304 htab_traverse (vars, dump_var_slot, NULL); 6305 } 6306} 6307 6308/* Print the dataflow set SET to dump file. */ 6309 6310static void 6311dump_dataflow_set (dataflow_set *set) 6312{ 6313 int i; 6314 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++) 6318 { 6319 if (set->regs[i]) 6320 { 6321 fprintf (dump_file, "Reg %d:", i); 6322 dump_attrs_list (set->regs[i]); 6323 } 6324 } 6325 dump_vars (shared_hash_htab (set->vars)); 6326 fprintf (dump_file, "\n"); 6327} 6328 6329/* Print the IN and OUT sets for each basic block to dump file. */ 6330 6331static void 6332dump_dataflow_sets (void) 6333{ 6334 basic_block bb; 6335 6336 FOR_EACH_BB (bb) 6337 { 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); 6343 } 6344} 6345 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. */ 6348 6349static void 6350variable_was_changed (variable var, dataflow_set *set) 6351{ 6352 hashval_t hash = dv_htab_hash (var->dv); 6353 6354 if (emit_notes) 6355 { 6356 void **slot; 6357 bool old_cur_loc_changed = false; 6358 6359 /* Remember this decl or VALUE has been added to changed_variables. */ 6360 set_dv_changed (var->dv, true); 6361 6362 slot = htab_find_slot_with_hash (changed_variables, 6363 var->dv, 6364 hash, INSERT); 6365 6366 if (*slot) 6367 { 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); 6373 } 6374 if (set && var->n_var_parts == 0) 6375 { 6376 variable empty_var; 6377 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; 6386 } 6387 else 6388 { 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; 6396 } 6397 } 6398 else 6399 { 6400 gcc_assert (set); 6401 if (var->n_var_parts == 0) 6402 { 6403 void **slot; 6404 6405 drop_var: 6406 slot = shared_hash_find_slot_noinsert (set->vars, var->dv); 6407 if (slot) 6408 { 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); 6413 } 6414 } 6415 } 6416} 6417 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. */ 6422 6423static inline int 6424find_variable_location_part (variable var, HOST_WIDE_INT offset, 6425 int *insertion_point) 6426{ 6427 int pos, low, high; 6428 6429 /* Find the location part. */ 6430 low = 0; 6431 high = var->n_var_parts; 6432 while (low != high) 6433 { 6434 pos = (low + high) / 2; 6435 if (var->var_part[pos].offset < offset) 6436 low = pos + 1; 6437 else 6438 high = pos; 6439 } 6440 pos = low; 6441 6442 if (insertion_point) 6443 *insertion_point = pos; 6444 6445 if (pos < var->n_var_parts && var->var_part[pos].offset == offset) 6446 return pos; 6447 6448 return -1; 6449} 6450 6451static void ** 6452set_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) 6455{ 6456 int pos; 6457 location_chain node, next; 6458 location_chain *nextp; 6459 variable var; 6460 bool onepart = dv_onepart_p (dv); 6461 6462 gcc_assert (offset == 0 || !onepart); 6463 gcc_assert (loc != dv_as_opaque (dv)); 6464 6465 var = (variable) *slot; 6466 6467 if (! flag_var_tracking_uninit) 6468 initialized = VAR_INIT_STATUS_INITIALIZED; 6469 6470 if (!var) 6471 { 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; 6485 } 6486 else if (onepart) 6487 { 6488 int r = -1, c = 0; 6489 6490 gcc_assert (dv_as_opaque (var->dv) == dv_as_opaque (dv)); 6491 6492 pos = 0; 6493 6494 if (GET_CODE (loc) == VALUE) 6495 { 6496 for (nextp = &var->var_part[0].loc_chain; (node = *nextp); 6497 nextp = &node->next) 6498 if (GET_CODE (node->loc) == VALUE) 6499 { 6500 if (node->loc == loc) 6501 { 6502 r = 0; 6503 break; 6504 } 6505 if (canon_value_cmp (node->loc, loc)) 6506 c++; 6507 else 6508 { 6509 r = 1; 6510 break; 6511 } 6512 } 6513 else if (REG_P (node->loc) || MEM_P (node->loc)) 6514 c++; 6515 else 6516 { 6517 r = 1; 6518 break; 6519 } 6520 } 6521 else if (REG_P (loc)) 6522 { 6523 for (nextp = &var->var_part[0].loc_chain; (node = *nextp); 6524 nextp = &node->next) 6525 if (REG_P (node->loc)) 6526 { 6527 if (REGNO (node->loc) < REGNO (loc)) 6528 c++; 6529 else 6530 { 6531 if (REGNO (node->loc) == REGNO (loc)) 6532 r = 0; 6533 else 6534 r = 1; 6535 break; 6536 } 6537 } 6538 else 6539 { 6540 r = 1; 6541 break; 6542 } 6543 } 6544 else if (MEM_P (loc)) 6545 { 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)) 6551 { 6552 if ((r = loc_cmp (XEXP (node->loc, 0), XEXP (loc, 0))) >= 0) 6553 break; 6554 else 6555 c++; 6556 } 6557 else 6558 { 6559 r = 1; 6560 break; 6561 } 6562 } 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++; 6570 6571 if (r == 0) 6572 return slot; 6573 6574 if (shared_var_p (var, set->vars)) 6575 { 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); 6582 } 6583 } 6584 else 6585 { 6586 int inspos = 0; 6587 6588 gcc_assert (dv_as_decl (var->dv) == dv_as_decl (dv)); 6589 6590 pos = find_variable_location_part (var, offset, &inspos); 6591 6592 if (pos >= 0) 6593 { 6594 node = var->var_part[pos].loc_chain; 6595 6596 if (node 6597 && ((REG_P (node->loc) && REG_P (loc) 6598 && REGNO (node->loc) == REGNO (loc)) 6599 || rtx_equal_p (node->loc, loc))) 6600 { 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; 6607 6608 return slot; 6609 } 6610 else 6611 { 6612 /* We have to make a copy of a shared variable. */ 6613 if (shared_var_p (var, set->vars)) 6614 { 6615 slot = unshare_variable (set, slot, var, initialized); 6616 var = (variable)*slot; 6617 } 6618 } 6619 } 6620 else 6621 { 6622 /* We have not found the location part, new one will be created. */ 6623 6624 /* We have to make a copy of the shared variable. */ 6625 if (shared_var_p (var, set->vars)) 6626 { 6627 slot = unshare_variable (set, slot, var, initialized); 6628 var = (variable)*slot; 6629 } 6630 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))); 6635 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]; 6640 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; 6645 } 6646 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) 6650 { 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)) 6655 { 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) 6663 { 6664 var->var_part[pos].cur_loc = NULL; 6665 var->cur_loc_changed = true; 6666 } 6667 pool_free (loc_chain_pool, node); 6668 *nextp = next; 6669 break; 6670 } 6671 else 6672 nextp = &node->next; 6673 } 6674 6675 nextp = &var->var_part[pos].loc_chain; 6676 } 6677 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; 6685 6686 if (onepart && emit_notes) 6687 add_value_chains (var->dv, loc); 6688 6689 /* If no location was emitted do so. */ 6690 if (var->var_part[pos].cur_loc == NULL) 6691 variable_was_changed (var, set); 6692 6693 return slot; 6694} 6695 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. */ 6701 6702static void 6703set_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) 6707{ 6708 void **slot; 6709 6710 if (iopt == NO_INSERT) 6711 slot = shared_hash_find_slot_noinsert (set->vars, dv); 6712 else 6713 { 6714 slot = shared_hash_find_slot (set->vars, dv); 6715 if (!slot) 6716 slot = shared_hash_find_slot_unshare (&set->vars, dv, iopt); 6717 } 6718 slot = set_slot_part (set, loc, slot, dv, offset, initialized, set_src); 6719} 6720 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. */ 6725 6726static void ** 6727clobber_slot_part (dataflow_set *set, rtx loc, void **slot, 6728 HOST_WIDE_INT offset, rtx set_src) 6729{ 6730 variable var = (variable) *slot; 6731 int pos = find_variable_location_part (var, offset, NULL); 6732 6733 if (pos >= 0) 6734 { 6735 location_chain node, next; 6736 6737 /* Remove the register locations from the dataflow set. */ 6738 next = var->var_part[pos].loc_chain; 6739 for (node = next; node; node = next) 6740 { 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))) 6747 { 6748 if (REG_P (node->loc)) 6749 { 6750 attrs anode, anext; 6751 attrs *anextp; 6752 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) 6759 { 6760 anext = anode->next; 6761 if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv) 6762 && anode->offset == offset) 6763 { 6764 pool_free (attrs_pool, anode); 6765 *anextp = anext; 6766 } 6767 else 6768 anextp = &anode->next; 6769 } 6770 } 6771 6772 slot = delete_slot_part (set, node->loc, slot, offset); 6773 } 6774 } 6775 } 6776 6777 return slot; 6778} 6779 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. */ 6784 6785static void 6786clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, 6787 HOST_WIDE_INT offset, rtx set_src) 6788{ 6789 void **slot; 6790 6791 if (!dv_as_opaque (dv) 6792 || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv)))) 6793 return; 6794 6795 slot = shared_hash_find_slot_noinsert (set->vars, dv); 6796 if (!slot) 6797 return; 6798 6799 slot = clobber_slot_part (set, loc, slot, offset, set_src); 6800} 6801 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. */ 6805 6806static void ** 6807delete_slot_part (dataflow_set *set, rtx loc, void **slot, 6808 HOST_WIDE_INT offset) 6809{ 6810 variable var = (variable) *slot; 6811 int pos = find_variable_location_part (var, offset, NULL); 6812 6813 if (pos >= 0) 6814 { 6815 location_chain node, next; 6816 location_chain *nextp; 6817 bool changed; 6818 6819 if (shared_var_p (var, set->vars)) 6820 { 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) 6825 { 6826 if ((REG_P (node->loc) && REG_P (loc) 6827 && REGNO (node->loc) == REGNO (loc)) 6828 || rtx_equal_p (node->loc, loc)) 6829 { 6830 slot = unshare_variable (set, slot, var, 6831 VAR_INIT_STATUS_UNKNOWN); 6832 var = (variable)*slot; 6833 break; 6834 } 6835 } 6836 } 6837 6838 /* Delete the location part. */ 6839 changed = false; 6840 nextp = &var->var_part[pos].loc_chain; 6841 for (node = *nextp; node; node = next) 6842 { 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)) 6847 { 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) 6854 { 6855 changed = true; 6856 var->var_part[pos].cur_loc = NULL; 6857 var->cur_loc_changed = true; 6858 } 6859 pool_free (loc_chain_pool, node); 6860 *nextp = next; 6861 break; 6862 } 6863 else 6864 nextp = &node->next; 6865 } 6866 6867 if (var->var_part[pos].loc_chain == NULL) 6868 { 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) 6874 { 6875 var->var_part[pos] = var->var_part[pos + 1]; 6876 pos++; 6877 } 6878 } 6879 if (changed) 6880 variable_was_changed (var, set); 6881 } 6882 6883 return slot; 6884} 6885 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. */ 6889 6890static void 6891delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, 6892 HOST_WIDE_INT offset) 6893{ 6894 void **slot = shared_hash_find_slot_noinsert (set->vars, dv); 6895 if (!slot) 6896 return; 6897 6898 slot = delete_slot_part (set, loc, slot, offset); 6899} 6900 6901/* Structure for passing some other parameters to function 6902 vt_expand_loc_callback. */ 6903struct expand_loc_callback_data 6904{ 6905 /* The variables and values active at this point. */ 6906 htab_t vars; 6907 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; 6914 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; 6920}; 6921 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. */ 6925 6926static rtx 6927vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data) 6928{ 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; 6937 6938 switch (GET_CODE (x)) 6939 { 6940 case SUBREG: 6941 if (dummy) 6942 { 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; 6949 } 6950 6951 subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs, 6952 max_depth - 1, 6953 vt_expand_loc_callback, data); 6954 6955 if (!subreg) 6956 return NULL; 6957 6958 result = simplify_gen_subreg (GET_MODE (x), subreg, 6959 GET_MODE (SUBREG_REG (x)), 6960 SUBREG_BYTE (x)); 6961 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)); 6966 6967 return result; 6968 6969 case DEBUG_EXPR: 6970 dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x)); 6971 xret = NULL; 6972 break; 6973 6974 case VALUE: 6975 dv = dv_from_value (x); 6976 xret = x; 6977 break; 6978 6979 default: 6980 return x; 6981 } 6982 6983 if (VALUE_RECURSED_INTO (x)) 6984 return NULL; 6985 6986 var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv)); 6987 6988 if (!var) 6989 { 6990 if (dummy && dv_changed_p (dv)) 6991 elcd->cur_loc_changed = true; 6992 return xret; 6993 } 6994 6995 if (var->n_var_parts == 0) 6996 { 6997 if (dummy) 6998 elcd->cur_loc_changed = true; 6999 return xret; 7000 } 7001 7002 gcc_assert (var->n_var_parts == 1); 7003 7004 VALUE_RECURSED_INTO (x) = true; 7005 result = NULL; 7006 7007 if (var->var_part[0].cur_loc) 7008 { 7009 if (dummy) 7010 { 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; 7015 } 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); 7022 } 7023 if (!result && dv_changed_p (dv)) 7024 { 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) 7030 { 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)) 7035 { 7036 result = pc_rtx; 7037 break; 7038 } 7039 } 7040 else 7041 { 7042 result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth, 7043 vt_expand_loc_callback, data); 7044 if (result) 7045 break; 7046 } 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; 7050 } 7051 if (dummy) 7052 { 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; 7057 } 7058 7059 VALUE_RECURSED_INTO (x) = false; 7060 if (result) 7061 return result; 7062 else 7063 return xret; 7064} 7065 7066/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence 7067 tables. */ 7068 7069static rtx 7070vt_expand_loc (rtx loc, htab_t vars) 7071{ 7072 struct expand_loc_callback_data data; 7073 7074 if (!MAY_HAVE_DEBUG_INSNS) 7075 return loc; 7076 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); 7082 7083 if (loc && MEM_P (loc)) 7084 loc = targetm.delegitimize_address (loc); 7085 return loc; 7086} 7087 7088/* Like vt_expand_loc, but only return true/false (whether vt_expand_loc 7089 would succeed or not, without actually allocating new rtxes. */ 7090 7091static bool 7092vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed) 7093{ 7094 struct expand_loc_callback_data data; 7095 bool ret; 7096 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; 7105} 7106 7107#ifdef ENABLE_RTL_CHECKING 7108/* Used to verify that cur_loc_changed updating is safe. */ 7109static struct pointer_map_t *emitted_notes; 7110#endif 7111 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. */ 7115 7116static int 7117emit_note_insn_var_location (void **varp, void *data) 7118{ 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; 7133 7134 if (dv_is_value_p (var->dv)) 7135 goto value_or_debug_decl; 7136 7137 decl = dv_as_decl (var->dv); 7138 7139 if (TREE_CODE (decl) == DEBUG_EXPR_DECL) 7140 goto value_or_debug_decl; 7141 7142 complete = true; 7143 last_limit = 0; 7144 n_var_parts = 0; 7145 if (!MAY_HAVE_DEBUG_INSNS) 7146 { 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) 7149 { 7150 var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc; 7151 var->cur_loc_changed = true; 7152 } 7153 if (var->n_var_parts == 0) 7154 var->cur_loc_changed = true; 7155 } 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++) 7161 { 7162 enum machine_mode mode, wider_mode; 7163 rtx loc2; 7164 7165 if (last_limit < var->var_part[i].offset) 7166 { 7167 complete = false; 7168 break; 7169 } 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) 7174 { 7175 complete = false; 7176 continue; 7177 } 7178 loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars); 7179 if (!loc2) 7180 { 7181 complete = false; 7182 continue; 7183 } 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) 7190 { 7191 initialized = lc->init; 7192 break; 7193 } 7194 gcc_assert (lc); 7195 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); 7196 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)) 7210 { 7211 rtx new_loc = NULL; 7212 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)) 7218 { 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) 7225 { 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]); 7231 } 7232 } 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))) 7237 { 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); 7252 } 7253 7254 if (new_loc) 7255 { 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; 7260 } 7261 } 7262 ++n_var_parts; 7263 } 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; 7267 7268 if (! flag_var_tracking_uninit) 7269 initialized = VAR_INIT_STATUS_INITIALIZED; 7270 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) 7276 { 7277 rtx expr_list; 7278 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]; 7283 7284 note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list, 7285 (int) initialized); 7286 } 7287 else if (n_var_parts) 7288 { 7289 rtx parallel; 7290 7291 for (i = 0; i < n_var_parts; i++) 7292 loc[i] 7293 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); 7294 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); 7299 } 7300 7301#ifdef ENABLE_RTL_CHECKING 7302 if (note_vl) 7303 { 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))) 7307 { 7308 gcc_assert (pnote); 7309 gcc_assert (rtx_equal_p (PAT_VAR_LOCATION_LOC (pnote), 7310 PAT_VAR_LOCATION_LOC (note_vl))); 7311 } 7312 *note_slot = (void *) note_vl; 7313 } 7314 if (!var->cur_loc_changed) 7315 goto clear; 7316#endif 7317 7318 if (where != EMIT_NOTE_BEFORE_INSN) 7319 { 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; 7323 } 7324 else 7325 { 7326 /* Make sure that the call related notes come first. */ 7327 while (NEXT_INSN (insn) 7328 && NOTE_P (insn) 7329 && NOTE_DURING_CALL_P (insn)) 7330 insn = NEXT_INSN (insn); 7331 if (NOTE_P (insn) && NOTE_DURING_CALL_P (insn)) 7332 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); 7333 else 7334 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn); 7335 } 7336 NOTE_VAR_LOCATION (note) = note_vl; 7337 7338 clear: 7339 set_dv_changed (var->dv, false); 7340 var->cur_loc_changed = false; 7341 gcc_assert (var->in_changed_variables); 7342 var->in_changed_variables = false; 7343 htab_clear_slot (changed_variables, varp); 7344 7345 /* Continue traversing the hash table. */ 7346 return 1; 7347 7348 value_or_debug_decl: 7349 if (dv_changed_p (var->dv) && var->n_var_parts) 7350 { 7351 location_chain lc; 7352 bool cur_loc_changed; 7353 7354 if (var->var_part[0].cur_loc 7355 && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars, 7356 &cur_loc_changed)) 7357 goto clear; 7358 for (lc = var->var_part[0].loc_chain; lc; lc = lc->next) 7359 if (lc->loc != var->var_part[0].cur_loc 7360 && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed)) 7361 break; 7362 var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX; 7363 } 7364 goto clear; 7365} 7366 7367DEF_VEC_P (variable); 7368DEF_VEC_ALLOC_P (variable, heap); 7369 7370/* Stack of variable_def pointers that need processing with 7371 check_changed_vars_2. */ 7372 7373static VEC (variable, heap) *changed_variables_stack; 7374 7375/* VALUEs with no variables that need set_dv_changed (val, false) 7376 called before check_changed_vars_3. */ 7377 7378static VEC (rtx, heap) *changed_values_stack; 7379 7380/* Helper function for check_changed_vars_1 and check_changed_vars_2. */ 7381 7382static void 7383check_changed_vars_0 (decl_or_value dv, htab_t htab) 7384{ 7385 value_chain vc 7386 = (value_chain) htab_find_with_hash (value_chains, dv, dv_htab_hash (dv)); 7387 7388 if (vc == NULL) 7389 return; 7390 for (vc = vc->next; vc; vc = vc->next) 7391 if (!dv_changed_p (vc->dv)) 7392 { 7393 variable vcvar 7394 = (variable) htab_find_with_hash (htab, vc->dv, 7395 dv_htab_hash (vc->dv)); 7396 if (vcvar) 7397 { 7398 set_dv_changed (vc->dv, true); 7399 VEC_safe_push (variable, heap, changed_variables_stack, vcvar); 7400 } 7401 else if (dv_is_value_p (vc->dv)) 7402 { 7403 set_dv_changed (vc->dv, true); 7404 VEC_safe_push (rtx, heap, changed_values_stack, 7405 dv_as_value (vc->dv)); 7406 check_changed_vars_0 (vc->dv, htab); 7407 } 7408 } 7409} 7410 7411/* Populate changed_variables_stack with variable_def pointers 7412 that need variable_was_changed called on them. */ 7413 7414static int 7415check_changed_vars_1 (void **slot, void *data) 7416{ 7417 variable var = (variable) *slot; 7418 htab_t htab = (htab_t) data; 7419 7420 if (dv_is_value_p (var->dv) 7421 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL) 7422 check_changed_vars_0 (var->dv, htab); 7423 return 1; 7424} 7425 7426/* Add VAR to changed_variables and also for VALUEs add recursively 7427 all DVs that aren't in changed_variables yet but reference the 7428 VALUE from its loc_chain. */ 7429 7430static void 7431check_changed_vars_2 (variable var, htab_t htab) 7432{ 7433 variable_was_changed (var, NULL); 7434 if (dv_is_value_p (var->dv) 7435 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL) 7436 check_changed_vars_0 (var->dv, htab); 7437} 7438 7439/* For each changed decl (except DEBUG_EXPR_DECLs) recompute 7440 cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs 7441 it needs and are also in changed variables) and track whether 7442 cur_loc (or anything it uses to compute location) had to change 7443 during the current emit_notes_for_changes call. */ 7444 7445static int 7446check_changed_vars_3 (void **slot, void *data) 7447{ 7448 variable var = (variable) *slot; 7449 htab_t vars = (htab_t) data; 7450 int i; 7451 location_chain lc; 7452 bool cur_loc_changed; 7453 7454 if (dv_is_value_p (var->dv) 7455 || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL) 7456 return 1; 7457 7458 for (i = 0; i < var->n_var_parts; i++) 7459 { 7460 if (var->var_part[i].cur_loc 7461 && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars, 7462 &cur_loc_changed)) 7463 { 7464 if (cur_loc_changed) 7465 var->cur_loc_changed = true; 7466 continue; 7467 } 7468 for (lc = var->var_part[i].loc_chain; lc; lc = lc->next) 7469 if (lc->loc != var->var_part[i].cur_loc 7470 && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed)) 7471 break; 7472 if (lc || var->var_part[i].cur_loc) 7473 var->cur_loc_changed = true; 7474 var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX; 7475 } 7476 if (var->n_var_parts == 0) 7477 var->cur_loc_changed = true; 7478 return 1; 7479} 7480 7481/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain 7482 CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes 7483 shall be emitted before of after instruction INSN. */ 7484 7485static void 7486emit_notes_for_changes (rtx insn, enum emit_note_where where, 7487 shared_hash vars) 7488{ 7489 emit_note_data data; 7490 htab_t htab = shared_hash_htab (vars); 7491 7492 if (!htab_elements (changed_variables)) 7493 return; 7494 7495 if (MAY_HAVE_DEBUG_INSNS) 7496 { 7497 /* Unfortunately this has to be done in two steps, because 7498 we can't traverse a hashtab into which we are inserting 7499 through variable_was_changed. */ 7500 htab_traverse (changed_variables, check_changed_vars_1, htab); 7501 while (VEC_length (variable, changed_variables_stack) > 0) 7502 check_changed_vars_2 (VEC_pop (variable, changed_variables_stack), 7503 htab); 7504 while (VEC_length (rtx, changed_values_stack) > 0) 7505 set_dv_changed (dv_from_value (VEC_pop (rtx, changed_values_stack)), 7506 false); 7507 htab_traverse (changed_variables, check_changed_vars_3, htab); 7508 } 7509 7510 data.insn = insn; 7511 data.where = where; 7512 data.vars = htab; 7513 7514 htab_traverse (changed_variables, emit_note_insn_var_location, &data); 7515} 7516 7517/* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the 7518 same variable in hash table DATA or is not there at all. */ 7519 7520static int 7521emit_notes_for_differences_1 (void **slot, void *data) 7522{ 7523 htab_t new_vars = (htab_t) data; 7524 variable old_var, new_var; 7525 7526 old_var = (variable) *slot; 7527 new_var = (variable) htab_find_with_hash (new_vars, old_var->dv, 7528 dv_htab_hash (old_var->dv)); 7529 7530 if (!new_var) 7531 { 7532 /* Variable has disappeared. */ 7533 variable empty_var; 7534 7535 empty_var = (variable) pool_alloc (dv_pool (old_var->dv)); 7536 empty_var->dv = old_var->dv; 7537 empty_var->refcount = 0; 7538 empty_var->n_var_parts = 0; 7539 empty_var->cur_loc_changed = false; 7540 empty_var->in_changed_variables = false; 7541 if (dv_onepart_p (old_var->dv)) 7542 { 7543 location_chain lc; 7544 7545 gcc_assert (old_var->n_var_parts == 1); 7546 for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next) 7547 remove_value_chains (old_var->dv, lc->loc); 7548 } 7549 variable_was_changed (empty_var, NULL); 7550 /* Continue traversing the hash table. */ 7551 return 1; 7552 } 7553 if (variable_different_p (old_var, new_var)) 7554 { 7555 if (dv_onepart_p (old_var->dv)) 7556 { 7557 location_chain lc1, lc2; 7558 7559 gcc_assert (old_var->n_var_parts == 1 7560 && new_var->n_var_parts == 1); 7561 lc1 = old_var->var_part[0].loc_chain; 7562 lc2 = new_var->var_part[0].loc_chain; 7563 while (lc1 7564 && lc2 7565 && ((REG_P (lc1->loc) && REG_P (lc2->loc)) 7566 || rtx_equal_p (lc1->loc, lc2->loc))) 7567 { 7568 lc1 = lc1->next; 7569 lc2 = lc2->next; 7570 } 7571 for (; lc2; lc2 = lc2->next) 7572 add_value_chains (old_var->dv, lc2->loc); 7573 for (; lc1; lc1 = lc1->next) 7574 remove_value_chains (old_var->dv, lc1->loc); 7575 } 7576 variable_was_changed (new_var, NULL); 7577 } 7578 /* Update cur_loc. */ 7579 if (old_var != new_var) 7580 { 7581 int i; 7582 for (i = 0; i < new_var->n_var_parts; i++) 7583 { 7584 new_var->var_part[i].cur_loc = NULL; 7585 if (old_var->n_var_parts != new_var->n_var_parts 7586 || old_var->var_part[i].offset != new_var->var_part[i].offset) 7587 new_var->cur_loc_changed = true; 7588 else if (old_var->var_part[i].cur_loc != NULL) 7589 { 7590 location_chain lc; 7591 rtx cur_loc = old_var->var_part[i].cur_loc; 7592 7593 for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next) 7594 if (lc->loc == cur_loc 7595 || rtx_equal_p (cur_loc, lc->loc)) 7596 { 7597 new_var->var_part[i].cur_loc = lc->loc; 7598 break; 7599 } 7600 if (lc == NULL) 7601 new_var->cur_loc_changed = true; 7602 } 7603 } 7604 } 7605 7606 /* Continue traversing the hash table. */ 7607 return 1; 7608} 7609 7610/* Add variable *SLOT to the chain CHANGED_VARIABLES if it is not in hash 7611 table DATA. */ 7612 7613static int 7614emit_notes_for_differences_2 (void **slot, void *data) 7615{ 7616 htab_t old_vars = (htab_t) data; 7617 variable old_var, new_var; 7618 7619 new_var = (variable) *slot; 7620 old_var = (variable) htab_find_with_hash (old_vars, new_var->dv, 7621 dv_htab_hash (new_var->dv)); 7622 if (!old_var) 7623 { 7624 int i; 7625 /* Variable has appeared. */ 7626 if (dv_onepart_p (new_var->dv)) 7627 { 7628 location_chain lc; 7629 7630 gcc_assert (new_var->n_var_parts == 1); 7631 for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next) 7632 add_value_chains (new_var->dv, lc->loc); 7633 } 7634 for (i = 0; i < new_var->n_var_parts; i++) 7635 new_var->var_part[i].cur_loc = NULL; 7636 variable_was_changed (new_var, NULL); 7637 } 7638 7639 /* Continue traversing the hash table. */ 7640 return 1; 7641} 7642 7643/* Emit notes before INSN for differences between dataflow sets OLD_SET and 7644 NEW_SET. */ 7645 7646static void 7647emit_notes_for_differences (rtx insn, dataflow_set *old_set, 7648 dataflow_set *new_set) 7649{ 7650 htab_traverse (shared_hash_htab (old_set->vars), 7651 emit_notes_for_differences_1, 7652 shared_hash_htab (new_set->vars)); 7653 htab_traverse (shared_hash_htab (new_set->vars), 7654 emit_notes_for_differences_2, 7655 shared_hash_htab (old_set->vars)); 7656 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars); 7657} 7658 7659/* Emit the notes for changes of location parts in the basic block BB. */ 7660 7661static void 7662emit_notes_in_bb (basic_block bb, dataflow_set *set) 7663{ 7664 unsigned int i; 7665 micro_operation *mo; 7666 7667 dataflow_set_clear (set); 7668 dataflow_set_copy (set, &VTI (bb)->in); 7669 7670 for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++) 7671 { 7672 rtx insn = mo->insn; 7673 7674 switch (mo->type) 7675 { 7676 case MO_CALL: 7677 dataflow_set_clear_at_call (set); 7678 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars); 7679 break; 7680 7681 case MO_USE: 7682 { 7683 rtx loc = mo->u.loc; 7684 7685 if (REG_P (loc)) 7686 var_reg_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); 7687 else 7688 var_mem_set (set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); 7689 7690 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars); 7691 } 7692 break; 7693 7694 case MO_VAL_LOC: 7695 { 7696 rtx loc = mo->u.loc; 7697 rtx val, vloc; 7698 tree var; 7699 7700 if (GET_CODE (loc) == CONCAT) 7701 { 7702 val = XEXP (loc, 0); 7703 vloc = XEXP (loc, 1); 7704 } 7705 else 7706 { 7707 val = NULL_RTX; 7708 vloc = loc; 7709 } 7710 7711 var = PAT_VAR_LOCATION_DECL (vloc); 7712 7713 clobber_variable_part (set, NULL_RTX, 7714 dv_from_decl (var), 0, NULL_RTX); 7715 if (val) 7716 { 7717 if (VAL_NEEDS_RESOLUTION (loc)) 7718 val_resolve (set, val, PAT_VAR_LOCATION_LOC (vloc), insn); 7719 set_variable_part (set, val, dv_from_decl (var), 0, 7720 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, 7721 INSERT); 7722 } 7723 else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc))) 7724 set_variable_part (set, PAT_VAR_LOCATION_LOC (vloc), 7725 dv_from_decl (var), 0, 7726 VAR_INIT_STATUS_INITIALIZED, NULL_RTX, 7727 INSERT); 7728 7729 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars); 7730 } 7731 break; 7732 7733 case MO_VAL_USE: 7734 { 7735 rtx loc = mo->u.loc; 7736 rtx val, vloc, uloc; 7737 7738 vloc = uloc = XEXP (loc, 1); 7739 val = XEXP (loc, 0); 7740 7741 if (GET_CODE (val) == CONCAT) 7742 { 7743 uloc = XEXP (val, 1); 7744 val = XEXP (val, 0); 7745 } 7746 7747 if (VAL_NEEDS_RESOLUTION (loc)) 7748 val_resolve (set, val, vloc, insn); 7749 else 7750 val_store (set, val, uloc, insn, false); 7751 7752 if (VAL_HOLDS_TRACK_EXPR (loc)) 7753 { 7754 if (GET_CODE (uloc) == REG) 7755 var_reg_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED, 7756 NULL); 7757 else if (GET_CODE (uloc) == MEM) 7758 var_mem_set (set, uloc, VAR_INIT_STATUS_UNINITIALIZED, 7759 NULL); 7760 } 7761 7762 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, set->vars); 7763 } 7764 break; 7765 7766 case MO_VAL_SET: 7767 { 7768 rtx loc = mo->u.loc; 7769 rtx val, vloc, uloc, reverse = NULL_RTX; 7770 7771 vloc = loc; 7772 if (VAL_EXPR_HAS_REVERSE (loc)) 7773 { 7774 reverse = XEXP (loc, 1); 7775 vloc = XEXP (loc, 0); 7776 } 7777 uloc = XEXP (vloc, 1); 7778 val = XEXP (vloc, 0); 7779 vloc = uloc; 7780 7781 if (GET_CODE (val) == CONCAT) 7782 { 7783 vloc = XEXP (val, 1); 7784 val = XEXP (val, 0); 7785 } 7786 7787 if (GET_CODE (vloc) == SET) 7788 { 7789 rtx vsrc = SET_SRC (vloc); 7790 7791 gcc_assert (val != vsrc); 7792 gcc_assert (vloc == uloc || VAL_NEEDS_RESOLUTION (loc)); 7793 7794 vloc = SET_DEST (vloc); 7795 7796 if (VAL_NEEDS_RESOLUTION (loc)) 7797 val_resolve (set, val, vsrc, insn); 7798 } 7799 else if (VAL_NEEDS_RESOLUTION (loc)) 7800 { 7801 gcc_assert (GET_CODE (uloc) == SET 7802 && GET_CODE (SET_SRC (uloc)) == REG); 7803 val_resolve (set, val, SET_SRC (uloc), insn); 7804 } 7805 7806 if (VAL_HOLDS_TRACK_EXPR (loc)) 7807 { 7808 if (VAL_EXPR_IS_CLOBBERED (loc)) 7809 { 7810 if (REG_P (uloc)) 7811 var_reg_delete (set, uloc, true); 7812 else if (MEM_P (uloc)) 7813 var_mem_delete (set, uloc, true); 7814 } 7815 else 7816 { 7817 bool copied_p = VAL_EXPR_IS_COPIED (loc); 7818 rtx set_src = NULL; 7819 enum var_init_status status = VAR_INIT_STATUS_INITIALIZED; 7820 7821 if (GET_CODE (uloc) == SET) 7822 { 7823 set_src = SET_SRC (uloc); 7824 uloc = SET_DEST (uloc); 7825 } 7826 7827 if (copied_p) 7828 { 7829 status = find_src_status (set, set_src); 7830 7831 set_src = find_src_set_src (set, set_src); 7832 } 7833 7834 if (REG_P (uloc)) 7835 var_reg_delete_and_set (set, uloc, !copied_p, 7836 status, set_src); 7837 else if (MEM_P (uloc)) 7838 var_mem_delete_and_set (set, uloc, !copied_p, 7839 status, set_src); 7840 } 7841 } 7842 else if (REG_P (uloc)) 7843 var_regno_delete (set, REGNO (uloc)); 7844 7845 val_store (set, val, vloc, insn, true); 7846 7847 if (reverse) 7848 val_store (set, XEXP (reverse, 0), XEXP (reverse, 1), 7849 insn, false); 7850 7851 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN, 7852 set->vars); 7853 } 7854 break; 7855 7856 case MO_SET: 7857 { 7858 rtx loc = mo->u.loc; 7859 rtx set_src = NULL; 7860 7861 if (GET_CODE (loc) == SET) 7862 { 7863 set_src = SET_SRC (loc); 7864 loc = SET_DEST (loc); 7865 } 7866 7867 if (REG_P (loc)) 7868 var_reg_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED, 7869 set_src); 7870 else 7871 var_mem_delete_and_set (set, loc, true, VAR_INIT_STATUS_INITIALIZED, 7872 set_src); 7873 7874 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN, 7875 set->vars); 7876 } 7877 break; 7878 7879 case MO_COPY: 7880 { 7881 rtx loc = mo->u.loc; 7882 enum var_init_status src_status; 7883 rtx set_src = NULL; 7884 7885 if (GET_CODE (loc) == SET) 7886 { 7887 set_src = SET_SRC (loc); 7888 loc = SET_DEST (loc); 7889 } 7890 7891 src_status = find_src_status (set, set_src); 7892 set_src = find_src_set_src (set, set_src); 7893 7894 if (REG_P (loc)) 7895 var_reg_delete_and_set (set, loc, false, src_status, set_src); 7896 else 7897 var_mem_delete_and_set (set, loc, false, src_status, set_src); 7898 7899 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN, 7900 set->vars); 7901 } 7902 break; 7903 7904 case MO_USE_NO_VAR: 7905 { 7906 rtx loc = mo->u.loc; 7907 7908 if (REG_P (loc)) 7909 var_reg_delete (set, loc, false); 7910 else 7911 var_mem_delete (set, loc, false); 7912 7913 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars); 7914 } 7915 break; 7916 7917 case MO_CLOBBER: 7918 { 7919 rtx loc = mo->u.loc; 7920 7921 if (REG_P (loc)) 7922 var_reg_delete (set, loc, true); 7923 else 7924 var_mem_delete (set, loc, true); 7925 7926 emit_notes_for_changes (NEXT_INSN (insn), EMIT_NOTE_BEFORE_INSN, 7927 set->vars); 7928 } 7929 break; 7930 7931 case MO_ADJUST: 7932 set->stack_adjust += mo->u.adjust; 7933 break; 7934 } 7935 } 7936} 7937 7938/* Emit notes for the whole function. */ 7939 7940static void 7941vt_emit_notes (void) 7942{ 7943 basic_block bb; 7944 dataflow_set cur; 7945 7946#ifdef ENABLE_RTL_CHECKING 7947 emitted_notes = pointer_map_create (); 7948#endif 7949 gcc_assert (!htab_elements (changed_variables)); 7950 7951 /* Free memory occupied by the out hash tables, as they aren't used 7952 anymore. */ 7953 FOR_EACH_BB (bb) 7954 dataflow_set_clear (&VTI (bb)->out); 7955 7956 /* Enable emitting notes by functions (mainly by set_variable_part and 7957 delete_variable_part). */ 7958 emit_notes = true; 7959 7960 if (MAY_HAVE_DEBUG_INSNS) 7961 { 7962 unsigned int i; 7963 rtx val; 7964 7965 for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++) 7966 add_cselib_value_chains (dv_from_value (val)); 7967 changed_variables_stack = VEC_alloc (variable, heap, 40); 7968 changed_values_stack = VEC_alloc (rtx, heap, 40); 7969 } 7970 7971 dataflow_set_init (&cur); 7972 7973 FOR_EACH_BB (bb) 7974 { 7975 /* Emit the notes for changes of variable locations between two 7976 subsequent basic blocks. */ 7977 emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in); 7978 7979 /* Emit the notes for the changes in the basic block itself. */ 7980 emit_notes_in_bb (bb, &cur); 7981 7982 /* Free memory occupied by the in hash table, we won't need it 7983 again. */ 7984 dataflow_set_clear (&VTI (bb)->in); 7985 } 7986#ifdef ENABLE_CHECKING 7987 htab_traverse (shared_hash_htab (cur.vars), 7988 emit_notes_for_differences_1, 7989 shared_hash_htab (empty_shared_hash)); 7990 if (MAY_HAVE_DEBUG_INSNS) 7991 { 7992 unsigned int i; 7993 rtx val; 7994 7995 for (i = 0; VEC_iterate (rtx, preserved_values, i, val); i++) 7996 remove_cselib_value_chains (dv_from_value (val)); 7997 gcc_assert (htab_elements (value_chains) == 0); 7998 } 7999#endif 8000 dataflow_set_destroy (&cur); 8001 8002 if (MAY_HAVE_DEBUG_INSNS) 8003 { 8004 VEC_free (variable, heap, changed_variables_stack); 8005 VEC_free (rtx, heap, changed_values_stack); 8006 } 8007 8008#ifdef ENABLE_RTL_CHECKING 8009 pointer_map_destroy (emitted_notes); 8010#endif 8011 emit_notes = false; 8012} 8013 8014/* If there is a declaration and offset associated with register/memory RTL 8015 assign declaration to *DECLP and offset to *OFFSETP, and return true. */ 8016 8017static bool 8018vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) 8019{ 8020 if (REG_P (rtl)) 8021 { 8022 if (REG_ATTRS (rtl)) 8023 { 8024 *declp = REG_EXPR (rtl); 8025 *offsetp = REG_OFFSET (rtl); 8026 return true; 8027 } 8028 } 8029 else if (MEM_P (rtl)) 8030 { 8031 if (MEM_ATTRS (rtl)) 8032 { 8033 *declp = MEM_EXPR (rtl); 8034 *offsetp = INT_MEM_OFFSET (rtl); 8035 return true; 8036 } 8037 } 8038 return false; 8039} 8040 8041/* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */ 8042 8043static void 8044vt_add_function_parameters (void) 8045{ 8046 tree parm; 8047 8048 for (parm = DECL_ARGUMENTS (current_function_decl); 8049 parm; parm = TREE_CHAIN (parm)) 8050 { 8051 rtx decl_rtl = DECL_RTL_IF_SET (parm); 8052 rtx incoming = DECL_INCOMING_RTL (parm); 8053 tree decl; 8054 enum machine_mode mode; 8055 HOST_WIDE_INT offset; 8056 dataflow_set *out; 8057 decl_or_value dv; 8058 8059 if (TREE_CODE (parm) != PARM_DECL) 8060 continue; 8061 8062 if (!DECL_NAME (parm)) 8063 continue; 8064 8065 if (!decl_rtl || !incoming) 8066 continue; 8067 8068 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) 8069 continue; 8070 8071 if (!vt_get_decl_and_offset (incoming, &decl, &offset)) 8072 { 8073 if (REG_P (incoming) || MEM_P (incoming)) 8074 { 8075 /* This means argument is passed by invisible reference. */ 8076 offset = 0; 8077 decl = parm; 8078 incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming); 8079 } 8080 else 8081 { 8082 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) 8083 continue; 8084 offset += byte_lowpart_offset (GET_MODE (incoming), 8085 GET_MODE (decl_rtl)); 8086 } 8087 } 8088 8089 if (!decl) 8090 continue; 8091 8092 if (parm != decl) 8093 { 8094 /* Assume that DECL_RTL was a pseudo that got spilled to 8095 memory. The spill slot sharing code will force the 8096 memory to reference spill_slot_decl (%sfp), so we don't 8097 match above. That's ok, the pseudo must have referenced 8098 the entire parameter, so just reset OFFSET. */ 8099 gcc_assert (decl == get_spill_slot_decl (false)); 8100 offset = 0; 8101 } 8102 8103 if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) 8104 continue; 8105 8106 out = &VTI (ENTRY_BLOCK_PTR)->out; 8107 8108 dv = dv_from_decl (parm); 8109 8110 if (target_for_debug_bind (parm) 8111 /* We can't deal with these right now, because this kind of 8112 variable is single-part. ??? We could handle parallels 8113 that describe multiple locations for the same single 8114 value, but ATM we don't. */ 8115 && GET_CODE (incoming) != PARALLEL) 8116 { 8117 cselib_val *val; 8118 8119 /* ??? We shouldn't ever hit this, but it may happen because 8120 arguments passed by invisible reference aren't dealt with 8121 above: incoming-rtl will have Pmode rather than the 8122 expected mode for the type. */ 8123 if (offset) 8124 continue; 8125 8126 val = cselib_lookup (var_lowpart (mode, incoming), mode, true); 8127 8128 /* ??? Float-typed values in memory are not handled by 8129 cselib. */ 8130 if (val) 8131 { 8132 preserve_value (val); 8133 set_variable_part (out, val->val_rtx, dv, offset, 8134 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); 8135 dv = dv_from_value (val->val_rtx); 8136 } 8137 } 8138 8139 if (REG_P (incoming)) 8140 { 8141 incoming = var_lowpart (mode, incoming); 8142 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); 8143 attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, 8144 incoming); 8145 set_variable_part (out, incoming, dv, offset, 8146 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); 8147 } 8148 else if (MEM_P (incoming)) 8149 { 8150 incoming = var_lowpart (mode, incoming); 8151 set_variable_part (out, incoming, dv, offset, 8152 VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); 8153 } 8154 } 8155 8156 if (MAY_HAVE_DEBUG_INSNS) 8157 { 8158 cselib_preserve_only_values (); 8159 cselib_reset_table (cselib_get_next_uid ()); 8160 } 8161 8162} 8163 8164/* Return true if INSN in the prologue initializes hard_frame_pointer_rtx. */ 8165 8166static bool 8167fp_setter (rtx insn) 8168{ 8169 rtx pat = PATTERN (insn); 8170 if (RTX_FRAME_RELATED_P (insn)) 8171 { 8172 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 8173 if (expr) 8174 pat = XEXP (expr, 0); 8175 } 8176 if (GET_CODE (pat) == SET) 8177 return SET_DEST (pat) == hard_frame_pointer_rtx; 8178 else if (GET_CODE (pat) == PARALLEL) 8179 { 8180 int i; 8181 for (i = XVECLEN (pat, 0) - 1; i >= 0; i--) 8182 if (GET_CODE (XVECEXP (pat, 0, i)) == SET 8183 && SET_DEST (XVECEXP (pat, 0, i)) == hard_frame_pointer_rtx) 8184 return true; 8185 } 8186 return false; 8187} 8188 8189/* Initialize cfa_base_rtx, create a preserved VALUE for it and 8190 ensure it isn't flushed during cselib_reset_table. 8191 Can be called only if frame_pointer_rtx resp. arg_pointer_rtx 8192 has been eliminated. */ 8193 8194static void 8195vt_init_cfa_base (void) 8196{ 8197 cselib_val *val; 8198 8199#ifdef FRAME_POINTER_CFA_OFFSET 8200 cfa_base_rtx = frame_pointer_rtx; 8201#else 8202 cfa_base_rtx = arg_pointer_rtx; 8203#endif 8204 if (cfa_base_rtx == hard_frame_pointer_rtx 8205 || !fixed_regs[REGNO (cfa_base_rtx)]) 8206 { 8207 cfa_base_rtx = NULL_RTX; 8208 return; 8209 } 8210 if (!MAY_HAVE_DEBUG_INSNS) 8211 return; 8212 8213 val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1, 8214 get_insns ()); 8215 preserve_value (val); 8216 cselib_preserve_cfa_base_value (val, REGNO (cfa_base_rtx)); 8217 var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx, 8218 VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx), 8219 0, NULL_RTX, INSERT); 8220} 8221 8222/* Allocate and initialize the data structures for variable tracking 8223 and parse the RTL to get the micro operations. */ 8224 8225static bool 8226vt_initialize (void) 8227{ 8228 basic_block bb, prologue_bb = NULL; 8229 HOST_WIDE_INT fp_cfa_offset = -1; 8230 8231 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def)); 8232 8233 attrs_pool = create_alloc_pool ("attrs_def pool", 8234 sizeof (struct attrs_def), 1024); 8235 var_pool = create_alloc_pool ("variable_def pool", 8236 sizeof (struct variable_def) 8237 + (MAX_VAR_PARTS - 1) 8238 * sizeof (((variable)NULL)->var_part[0]), 64); 8239 loc_chain_pool = create_alloc_pool ("location_chain_def pool", 8240 sizeof (struct location_chain_def), 8241 1024); 8242 shared_hash_pool = create_alloc_pool ("shared_hash_def pool", 8243 sizeof (struct shared_hash_def), 256); 8244 empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool); 8245 empty_shared_hash->refcount = 1; 8246 empty_shared_hash->htab 8247 = htab_create (1, variable_htab_hash, variable_htab_eq, 8248 variable_htab_free); 8249 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, 8250 variable_htab_free); 8251 if (MAY_HAVE_DEBUG_INSNS) 8252 { 8253 value_chain_pool = create_alloc_pool ("value_chain_def pool", 8254 sizeof (struct value_chain_def), 8255 1024); 8256 value_chains = htab_create (32, value_chain_htab_hash, 8257 value_chain_htab_eq, NULL); 8258 } 8259 8260 /* Init the IN and OUT sets. */ 8261 FOR_ALL_BB (bb) 8262 { 8263 VTI (bb)->visited = false; 8264 VTI (bb)->flooded = false; 8265 dataflow_set_init (&VTI (bb)->in); 8266 dataflow_set_init (&VTI (bb)->out); 8267 VTI (bb)->permp = NULL; 8268 } 8269 8270 if (MAY_HAVE_DEBUG_INSNS) 8271 { 8272 cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS); 8273 scratch_regs = BITMAP_ALLOC (NULL); 8274 valvar_pool = create_alloc_pool ("small variable_def pool", 8275 sizeof (struct variable_def), 256); 8276 preserved_values = VEC_alloc (rtx, heap, 256); 8277 } 8278 else 8279 { 8280 scratch_regs = NULL; 8281 valvar_pool = NULL; 8282 } 8283 8284 if (!frame_pointer_needed) 8285 { 8286 rtx reg, elim; 8287 8288 if (!vt_stack_adjustments ()) 8289 return false; 8290 8291#ifdef FRAME_POINTER_CFA_OFFSET 8292 reg = frame_pointer_rtx; 8293#else 8294 reg = arg_pointer_rtx; 8295#endif 8296 elim = eliminate_regs (reg, VOIDmode, NULL_RTX); 8297 if (elim != reg) 8298 { 8299 if (GET_CODE (elim) == PLUS) 8300 elim = XEXP (elim, 0); 8301 if (elim == stack_pointer_rtx) 8302 vt_init_cfa_base (); 8303 } 8304 } 8305 else if (!crtl->stack_realign_tried) 8306 { 8307 rtx reg, elim; 8308 8309#ifdef FRAME_POINTER_CFA_OFFSET 8310 reg = frame_pointer_rtx; 8311 fp_cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl); 8312#else 8313 reg = arg_pointer_rtx; 8314 fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl); 8315#endif 8316 elim = eliminate_regs (reg, VOIDmode, NULL_RTX); 8317 if (elim != reg) 8318 { 8319 if (GET_CODE (elim) == PLUS) 8320 { 8321 fp_cfa_offset -= INTVAL (XEXP (elim, 1)); 8322 elim = XEXP (elim, 0); 8323 } 8324 if (elim != hard_frame_pointer_rtx) 8325 fp_cfa_offset = -1; 8326 else 8327 prologue_bb = single_succ (ENTRY_BLOCK_PTR); 8328 } 8329 } 8330 8331 hard_frame_pointer_adjustment = -1; 8332 8333 FOR_EACH_BB (bb) 8334 { 8335 rtx insn; 8336 HOST_WIDE_INT pre, post = 0; 8337 basic_block first_bb, last_bb; 8338 8339 if (MAY_HAVE_DEBUG_INSNS) 8340 { 8341 cselib_record_sets_hook = add_with_sets; 8342 if (dump_file && (dump_flags & TDF_DETAILS)) 8343 fprintf (dump_file, "first value: %i\n", 8344 cselib_get_next_uid ()); 8345 } 8346 8347 first_bb = bb; 8348 for (;;) 8349 { 8350 edge e; 8351 if (bb->next_bb == EXIT_BLOCK_PTR 8352 || ! single_pred_p (bb->next_bb)) 8353 break; 8354 e = find_edge (bb, bb->next_bb); 8355 if (! e || (e->flags & EDGE_FALLTHRU) == 0) 8356 break; 8357 bb = bb->next_bb; 8358 } 8359 last_bb = bb; 8360 8361 /* Add the micro-operations to the vector. */ 8362 FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb) 8363 { 8364 HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust; 8365 VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust; 8366 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); 8367 insn = NEXT_INSN (insn)) 8368 { 8369 if (INSN_P (insn)) 8370 { 8371 if (!frame_pointer_needed) 8372 { 8373 insn_stack_adjust_offset_pre_post (insn, &pre, &post); 8374 if (pre) 8375 { 8376 micro_operation mo; 8377 mo.type = MO_ADJUST; 8378 mo.u.adjust = pre; 8379 mo.insn = insn; 8380 if (dump_file && (dump_flags & TDF_DETAILS)) 8381 log_op_type (PATTERN (insn), bb, insn, 8382 MO_ADJUST, dump_file); 8383 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, 8384 &mo); 8385 VTI (bb)->out.stack_adjust += pre; 8386 } 8387 } 8388 8389 cselib_hook_called = false; 8390 adjust_insn (bb, insn); 8391 if (MAY_HAVE_DEBUG_INSNS) 8392 { 8393 cselib_process_insn (insn); 8394 if (dump_file && (dump_flags & TDF_DETAILS)) 8395 { 8396 print_rtl_single (dump_file, insn); 8397 dump_cselib_table (dump_file); 8398 } 8399 } 8400 if (!cselib_hook_called) 8401 add_with_sets (insn, 0, 0); 8402 cancel_changes (0); 8403 8404 if (!frame_pointer_needed && post) 8405 { 8406 micro_operation mo; 8407 mo.type = MO_ADJUST; 8408 mo.u.adjust = post; 8409 mo.insn = insn; 8410 if (dump_file && (dump_flags & TDF_DETAILS)) 8411 log_op_type (PATTERN (insn), bb, insn, 8412 MO_ADJUST, dump_file); 8413 VEC_safe_push (micro_operation, heap, VTI (bb)->mos, 8414 &mo); 8415 VTI (bb)->out.stack_adjust += post; 8416 } 8417 8418 if (bb == prologue_bb 8419 && hard_frame_pointer_adjustment == -1 8420 && RTX_FRAME_RELATED_P (insn) 8421 && fp_setter (insn)) 8422 { 8423 vt_init_cfa_base (); 8424 hard_frame_pointer_adjustment = fp_cfa_offset; 8425 } 8426 } 8427 } 8428 gcc_assert (offset == VTI (bb)->out.stack_adjust); 8429 } 8430 8431 bb = last_bb; 8432 8433 if (MAY_HAVE_DEBUG_INSNS) 8434 { 8435 cselib_preserve_only_values (); 8436 cselib_reset_table (cselib_get_next_uid ()); 8437 cselib_record_sets_hook = NULL; 8438 } 8439 } 8440 8441 hard_frame_pointer_adjustment = -1; 8442 VTI (ENTRY_BLOCK_PTR)->flooded = true; 8443 vt_add_function_parameters (); 8444 cfa_base_rtx = NULL_RTX; 8445 return true; 8446} 8447 8448/* Get rid of all debug insns from the insn stream. */ 8449 8450static void 8451delete_debug_insns (void) 8452{ 8453 basic_block bb; 8454 rtx insn, next; 8455 8456 if (!MAY_HAVE_DEBUG_INSNS) 8457 return; 8458 8459 FOR_EACH_BB (bb) 8460 { 8461 FOR_BB_INSNS_SAFE (bb, insn, next) 8462 if (DEBUG_INSN_P (insn)) 8463 delete_insn (insn); 8464 } 8465} 8466 8467/* Run a fast, BB-local only version of var tracking, to take care of 8468 information that we don't do global analysis on, such that not all 8469 information is lost. If SKIPPED holds, we're skipping the global 8470 pass entirely, so we should try to use information it would have 8471 handled as well.. */ 8472 8473static void 8474vt_debug_insns_local (bool skipped ATTRIBUTE_UNUSED) 8475{ 8476 /* ??? Just skip it all for now. */ 8477 delete_debug_insns (); 8478} 8479 8480/* Free the data structures needed for variable tracking. */ 8481 8482static void 8483vt_finalize (void) 8484{ 8485 basic_block bb; 8486 8487 FOR_EACH_BB (bb) 8488 { 8489 VEC_free (micro_operation, heap, VTI (bb)->mos); 8490 } 8491 8492 FOR_ALL_BB (bb) 8493 { 8494 dataflow_set_destroy (&VTI (bb)->in); 8495 dataflow_set_destroy (&VTI (bb)->out); 8496 if (VTI (bb)->permp) 8497 { 8498 dataflow_set_destroy (VTI (bb)->permp); 8499 XDELETE (VTI (bb)->permp); 8500 } 8501 } 8502 free_aux_for_blocks (); 8503 htab_delete (empty_shared_hash->htab); 8504 htab_delete (changed_variables); 8505 free_alloc_pool (attrs_pool); 8506 free_alloc_pool (var_pool); 8507 free_alloc_pool (loc_chain_pool); 8508 free_alloc_pool (shared_hash_pool); 8509 8510 if (MAY_HAVE_DEBUG_INSNS) 8511 { 8512 htab_delete (value_chains); 8513 free_alloc_pool (value_chain_pool); 8514 free_alloc_pool (valvar_pool); 8515 VEC_free (rtx, heap, preserved_values); 8516 cselib_finish (); 8517 BITMAP_FREE (scratch_regs); 8518 scratch_regs = NULL; 8519 } 8520 8521 if (vui_vec) 8522 XDELETEVEC (vui_vec); 8523 vui_vec = NULL; 8524 vui_allocated = 0; 8525} 8526 8527/* The entry point to variable tracking pass. */ 8528 8529static inline unsigned int 8530variable_tracking_main_1 (void) 8531{ 8532 bool success; 8533 8534 if (flag_var_tracking_assignments < 0) 8535 { 8536 delete_debug_insns (); 8537 return 0; 8538 } 8539 8540 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20) 8541 { 8542 vt_debug_insns_local (true); 8543 return 0; 8544 } 8545 8546 mark_dfs_back_edges (); 8547 if (!vt_initialize ()) 8548 { 8549 vt_finalize (); 8550 vt_debug_insns_local (true); 8551 return 0; 8552 } 8553 8554 success = vt_find_locations (); 8555 8556 if (!success && flag_var_tracking_assignments > 0) 8557 { 8558 vt_finalize (); 8559 8560 delete_debug_insns (); 8561 8562 /* This is later restored by our caller. */ 8563 flag_var_tracking_assignments = 0; 8564 8565 success = vt_initialize (); 8566 gcc_assert (success); 8567 8568 success = vt_find_locations (); 8569 } 8570 8571 if (!success) 8572 { 8573 vt_finalize (); 8574 vt_debug_insns_local (false); 8575 return 0; 8576 } 8577 8578 if (dump_file && (dump_flags & TDF_DETAILS)) 8579 { 8580 dump_dataflow_sets (); 8581 dump_flow_info (dump_file, dump_flags); 8582 } 8583 8584 vt_emit_notes (); 8585 8586 vt_finalize (); 8587 vt_debug_insns_local (false); 8588 return 0; 8589} 8590 8591unsigned int 8592variable_tracking_main (void) 8593{ 8594 unsigned int ret; 8595 int save = flag_var_tracking_assignments; 8596 8597 ret = variable_tracking_main_1 (); 8598 8599 flag_var_tracking_assignments = save; 8600 8601 return ret; 8602} 8603 8604static bool 8605gate_handle_var_tracking (void) 8606{ 8607 return (flag_var_tracking); 8608} 8609 8610 8611 8612struct rtl_opt_pass pass_variable_tracking = 8613{ 8614 { 8615 RTL_PASS, 8616 "vartrack", /* name */ 8617 gate_handle_var_tracking, /* gate */ 8618 variable_tracking_main, /* execute */ 8619 NULL, /* sub */ 8620 NULL, /* next */ 8621 0, /* static_pass_number */ 8622 TV_VAR_TRACKING, /* tv_id */ 8623 0, /* properties_required */ 8624 0, /* properties_provided */ 8625 0, /* properties_destroyed */ 8626 0, /* todo_flags_start */ 8627 TODO_dump_func | TODO_verify_rtl_sharing/* todo_flags_finish */ 8628 } 8629}; 8630