00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #include "config.h"
00090 #include "system.h"
00091 #include "coretypes.h"
00092 #include "tm.h"
00093 #include "rtl.h"
00094 #include "tree.h"
00095 #include "hard-reg-set.h"
00096 #include "basic-block.h"
00097 #include "flags.h"
00098 #include "output.h"
00099 #include "insn-config.h"
00100 #include "reload.h"
00101 #include "sbitmap.h"
00102 #include "alloc-pool.h"
00103 #include "fibheap.h"
00104 #include "hashtab.h"
00105 #include "regs.h"
00106 #include "expr.h"
00107 #include "timevar.h"
00108 #include "tree-pass.h"
00109
00110
00111 enum micro_operation_type
00112 {
00113 MO_USE,
00114 MO_USE_NO_VAR,
00115
00116 MO_SET,
00117 MO_COPY,
00118
00119 MO_CLOBBER,
00120 MO_CALL,
00121 MO_ADJUST
00122 };
00123
00124
00125 enum emit_note_where
00126 {
00127 EMIT_NOTE_BEFORE_INSN,
00128 EMIT_NOTE_AFTER_INSN
00129 };
00130
00131
00132 typedef struct micro_operation_def
00133 {
00134
00135 enum micro_operation_type type;
00136
00137 union {
00138
00139 rtx loc;
00140
00141
00142 HOST_WIDE_INT adjust;
00143 } u;
00144
00145
00146
00147
00148
00149
00150 rtx insn;
00151 } micro_operation;
00152
00153
00154
00155 typedef struct emit_note_data_def
00156 {
00157
00158 rtx insn;
00159
00160
00161 enum emit_note_where where;
00162 } emit_note_data;
00163
00164
00165
00166
00167
00168 typedef struct attrs_def
00169 {
00170
00171 struct attrs_def *next;
00172
00173
00174 rtx loc;
00175
00176
00177 tree decl;
00178
00179
00180 HOST_WIDE_INT offset;
00181 } *attrs;
00182
00183
00184 typedef struct dataflow_set_def
00185 {
00186
00187 HOST_WIDE_INT stack_adjust;
00188
00189
00190 attrs regs[FIRST_PSEUDO_REGISTER];
00191
00192
00193 htab_t vars;
00194 } dataflow_set;
00195
00196
00197
00198 typedef struct variable_tracking_info_def
00199 {
00200
00201 int n_mos;
00202
00203
00204 micro_operation *mos;
00205
00206
00207 dataflow_set in;
00208 dataflow_set out;
00209
00210
00211 bool visited;
00212 } *variable_tracking_info;
00213
00214
00215 typedef struct location_chain_def
00216 {
00217
00218 struct location_chain_def *next;
00219
00220
00221 rtx loc;
00222 } *location_chain;
00223
00224
00225 typedef struct variable_part_def
00226 {
00227
00228 location_chain loc_chain;
00229
00230
00231 rtx cur_loc;
00232
00233
00234 HOST_WIDE_INT offset;
00235 } variable_part;
00236
00237
00238 #define MAX_VAR_PARTS 16
00239
00240
00241 typedef struct variable_def
00242 {
00243
00244 tree decl;
00245
00246
00247 int refcount;
00248
00249
00250 int n_var_parts;
00251
00252
00253 variable_part var_part[MAX_VAR_PARTS];
00254 } *variable;
00255
00256
00257 #define VARIABLE_HASH_VAL(decl) (DECL_UID (decl))
00258
00259
00260 #define VTI(BB) ((variable_tracking_info) (BB)->aux)
00261
00262
00263 static alloc_pool attrs_pool;
00264
00265
00266 static alloc_pool var_pool;
00267
00268
00269 static alloc_pool loc_chain_pool;
00270
00271
00272 static htab_t changed_variables;
00273
00274
00275 static bool emit_notes;
00276
00277
00278 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
00279 HOST_WIDE_INT *);
00280 static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
00281 HOST_WIDE_INT *);
00282 static void bb_stack_adjust_offset (basic_block);
00283 static bool vt_stack_adjustments (void);
00284 static rtx adjust_stack_reference (rtx, HOST_WIDE_INT);
00285 static hashval_t variable_htab_hash (const void *);
00286 static int variable_htab_eq (const void *, const void *);
00287 static void variable_htab_free (void *);
00288
00289 static void init_attrs_list_set (attrs *);
00290 static void attrs_list_clear (attrs *);
00291 static attrs attrs_list_member (attrs, tree, HOST_WIDE_INT);
00292 static void attrs_list_insert (attrs *, tree, HOST_WIDE_INT, rtx);
00293 static void attrs_list_copy (attrs *, attrs);
00294 static void attrs_list_union (attrs *, attrs);
00295
00296 static void vars_clear (htab_t);
00297 static variable unshare_variable (dataflow_set *set, variable var);
00298 static int vars_copy_1 (void **, void *);
00299 static void vars_copy (htab_t, htab_t);
00300 static tree var_debug_decl (tree);
00301 static void var_reg_set (dataflow_set *, rtx);
00302 static void var_reg_delete_and_set (dataflow_set *, rtx, bool);
00303 static void var_reg_delete (dataflow_set *, rtx, bool);
00304 static void var_regno_delete (dataflow_set *, int);
00305 static void var_mem_set (dataflow_set *, rtx);
00306 static void var_mem_delete_and_set (dataflow_set *, rtx, bool);
00307 static void var_mem_delete (dataflow_set *, rtx, bool);
00308
00309 static void dataflow_set_init (dataflow_set *, int);
00310 static void dataflow_set_clear (dataflow_set *);
00311 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
00312 static int variable_union_info_cmp_pos (const void *, const void *);
00313 static int variable_union (void **, void *);
00314 static void dataflow_set_union (dataflow_set *, dataflow_set *);
00315 static bool variable_part_different_p (variable_part *, variable_part *);
00316 static bool variable_different_p (variable, variable, bool);
00317 static int dataflow_set_different_1 (void **, void *);
00318 static int dataflow_set_different_2 (void **, void *);
00319 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
00320 static void dataflow_set_destroy (dataflow_set *);
00321
00322 static bool contains_symbol_ref (rtx);
00323 static bool track_expr_p (tree);
00324 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
00325 static int count_uses (rtx *, void *);
00326 static void count_uses_1 (rtx *, void *);
00327 static void count_stores (rtx, rtx, void *);
00328 static int add_uses (rtx *, void *);
00329 static void add_uses_1 (rtx *, void *);
00330 static void add_stores (rtx, rtx, void *);
00331 static bool compute_bb_dataflow (basic_block);
00332 static void vt_find_locations (void);
00333
00334 static void dump_attrs_list (attrs);
00335 static int dump_variable (void **, void *);
00336 static void dump_vars (htab_t);
00337 static void dump_dataflow_set (dataflow_set *);
00338 static void dump_dataflow_sets (void);
00339
00340 static void variable_was_changed (variable, htab_t);
00341 static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
00342 static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
00343 static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT);
00344 static int emit_note_insn_var_location (void **, void *);
00345 static void emit_notes_for_changes (rtx, enum emit_note_where);
00346 static int emit_notes_for_differences_1 (void **, void *);
00347 static int emit_notes_for_differences_2 (void **, void *);
00348 static void emit_notes_for_differences (rtx, dataflow_set *, dataflow_set *);
00349 static void emit_notes_in_bb (basic_block);
00350 static void vt_emit_notes (void);
00351
00352 static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
00353 static void vt_add_function_parameters (void);
00354 static void vt_initialize (void);
00355 static void vt_finalize (void);
00356
00357
00358
00359
00360
00361 static void
00362 stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
00363 HOST_WIDE_INT *post)
00364 {
00365 rtx src = SET_SRC (pattern);
00366 rtx dest = SET_DEST (pattern);
00367 enum rtx_code code;
00368
00369 if (dest == stack_pointer_rtx)
00370 {
00371
00372 code = GET_CODE (src);
00373 if (! (code == PLUS || code == MINUS)
00374 || XEXP (src, 0) != stack_pointer_rtx
00375 || GET_CODE (XEXP (src, 1)) != CONST_INT)
00376 return;
00377
00378 if (code == MINUS)
00379 *post += INTVAL (XEXP (src, 1));
00380 else
00381 *post -= INTVAL (XEXP (src, 1));
00382 }
00383 else if (MEM_P (dest))
00384 {
00385
00386 src = XEXP (dest, 0);
00387 code = GET_CODE (src);
00388
00389 switch (code)
00390 {
00391 case PRE_MODIFY:
00392 case POST_MODIFY:
00393 if (XEXP (src, 0) == stack_pointer_rtx)
00394 {
00395 rtx val = XEXP (XEXP (src, 1), 1);
00396
00397 gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
00398 GET_CODE (val) == CONST_INT);
00399
00400 if (code == PRE_MODIFY)
00401 *pre -= INTVAL (val);
00402 else
00403 *post -= INTVAL (val);
00404 break;
00405 }
00406 return;
00407
00408 case PRE_DEC:
00409 if (XEXP (src, 0) == stack_pointer_rtx)
00410 {
00411 *pre += GET_MODE_SIZE (GET_MODE (dest));
00412 break;
00413 }
00414 return;
00415
00416 case POST_DEC:
00417 if (XEXP (src, 0) == stack_pointer_rtx)
00418 {
00419 *post += GET_MODE_SIZE (GET_MODE (dest));
00420 break;
00421 }
00422 return;
00423
00424 case PRE_INC:
00425 if (XEXP (src, 0) == stack_pointer_rtx)
00426 {
00427 *pre -= GET_MODE_SIZE (GET_MODE (dest));
00428 break;
00429 }
00430 return;
00431
00432 case POST_INC:
00433 if (XEXP (src, 0) == stack_pointer_rtx)
00434 {
00435 *post -= GET_MODE_SIZE (GET_MODE (dest));
00436 break;
00437 }
00438 return;
00439
00440 default:
00441 return;
00442 }
00443 }
00444 }
00445
00446
00447
00448
00449 static void
00450 insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
00451 HOST_WIDE_INT *post)
00452 {
00453 *pre = 0;
00454 *post = 0;
00455
00456 if (GET_CODE (PATTERN (insn)) == SET)
00457 stack_adjust_offset_pre_post (PATTERN (insn), pre, post);
00458 else if (GET_CODE (PATTERN (insn)) == PARALLEL
00459 || GET_CODE (PATTERN (insn)) == SEQUENCE)
00460 {
00461 int i;
00462
00463
00464
00465 for ( i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
00466 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
00467 stack_adjust_offset_pre_post (XVECEXP (PATTERN (insn), 0, i),
00468 pre, post);
00469 }
00470 }
00471
00472
00473
00474 static void
00475 bb_stack_adjust_offset (basic_block bb)
00476 {
00477 HOST_WIDE_INT offset;
00478 int i;
00479
00480 offset = VTI (bb)->in.stack_adjust;
00481 for (i = 0; i < VTI (bb)->n_mos; i++)
00482 {
00483 if (VTI (bb)->mos[i].type == MO_ADJUST)
00484 offset += VTI (bb)->mos[i].u.adjust;
00485 else if (VTI (bb)->mos[i].type != MO_CALL)
00486 {
00487 if (MEM_P (VTI (bb)->mos[i].u.loc))
00488 {
00489 VTI (bb)->mos[i].u.loc
00490 = adjust_stack_reference (VTI (bb)->mos[i].u.loc, -offset);
00491 }
00492 }
00493 }
00494 VTI (bb)->out.stack_adjust = offset;
00495 }
00496
00497
00498
00499
00500
00501 static bool
00502 vt_stack_adjustments (void)
00503 {
00504 edge_iterator *stack;
00505 int sp;
00506
00507
00508 VTI (ENTRY_BLOCK_PTR)->visited = true;
00509 VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET;
00510
00511
00512 stack = XNEWVEC (edge_iterator, n_basic_blocks + 1);
00513 sp = 0;
00514
00515
00516 stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
00517
00518 while (sp)
00519 {
00520 edge_iterator ei;
00521 basic_block src;
00522 basic_block dest;
00523
00524
00525 ei = stack[sp - 1];
00526 src = ei_edge (ei)->src;
00527 dest = ei_edge (ei)->dest;
00528
00529
00530 if (!VTI (dest)->visited)
00531 {
00532 VTI (dest)->visited = true;
00533 VTI (dest)->in.stack_adjust = VTI (src)->out.stack_adjust;
00534 bb_stack_adjust_offset (dest);
00535
00536 if (EDGE_COUNT (dest->succs) > 0)
00537
00538
00539 stack[sp++] = ei_start (dest->succs);
00540 }
00541 else
00542 {
00543
00544 if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
00545 {
00546 free (stack);
00547 return false;
00548 }
00549
00550 if (! ei_one_before_end_p (ei))
00551
00552 ei_next (&stack[sp - 1]);
00553 else
00554
00555 sp--;
00556 }
00557 }
00558
00559 free (stack);
00560 return true;
00561 }
00562
00563
00564
00565
00566 static rtx
00567 adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
00568 {
00569 rtx addr, cfa, tmp;
00570
00571 #ifdef FRAME_POINTER_CFA_OFFSET
00572 adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
00573 cfa = plus_constant (frame_pointer_rtx, adjustment);
00574 #else
00575 adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
00576 cfa = plus_constant (arg_pointer_rtx, adjustment);
00577 #endif
00578
00579 addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
00580 tmp = simplify_rtx (addr);
00581 if (tmp)
00582 addr = tmp;
00583
00584 return replace_equiv_address_nv (mem, addr);
00585 }
00586
00587
00588
00589
00590 static hashval_t
00591 variable_htab_hash (const void *x)
00592 {
00593 const variable v = (const variable) x;
00594
00595 return (VARIABLE_HASH_VAL (v->decl));
00596 }
00597
00598
00599
00600 static int
00601 variable_htab_eq (const void *x, const void *y)
00602 {
00603 const variable v = (const variable) x;
00604 const tree decl = (const tree) y;
00605
00606 return (VARIABLE_HASH_VAL (v->decl) == VARIABLE_HASH_VAL (decl));
00607 }
00608
00609
00610
00611 static void
00612 variable_htab_free (void *elem)
00613 {
00614 int i;
00615 variable var = (variable) elem;
00616 location_chain node, next;
00617
00618 gcc_assert (var->refcount > 0);
00619
00620 var->refcount--;
00621 if (var->refcount > 0)
00622 return;
00623
00624 for (i = 0; i < var->n_var_parts; i++)
00625 {
00626 for (node = var->var_part[i].loc_chain; node; node = next)
00627 {
00628 next = node->next;
00629 pool_free (loc_chain_pool, node);
00630 }
00631 var->var_part[i].loc_chain = NULL;
00632 }
00633 pool_free (var_pool, var);
00634 }
00635
00636
00637
00638 static void
00639 init_attrs_list_set (attrs *set)
00640 {
00641 int i;
00642
00643 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00644 set[i] = NULL;
00645 }
00646
00647
00648
00649 static void
00650 attrs_list_clear (attrs *listp)
00651 {
00652 attrs list, next;
00653
00654 for (list = *listp; list; list = next)
00655 {
00656 next = list->next;
00657 pool_free (attrs_pool, list);
00658 }
00659 *listp = NULL;
00660 }
00661
00662
00663
00664 static attrs
00665 attrs_list_member (attrs list, tree decl, HOST_WIDE_INT offset)
00666 {
00667 for (; list; list = list->next)
00668 if (list->decl == decl && list->offset == offset)
00669 return list;
00670 return NULL;
00671 }
00672
00673
00674
00675 static void
00676 attrs_list_insert (attrs *listp, tree decl, HOST_WIDE_INT offset, rtx loc)
00677 {
00678 attrs list;
00679
00680 list = pool_alloc (attrs_pool);
00681 list->loc = loc;
00682 list->decl = decl;
00683 list->offset = offset;
00684 list->next = *listp;
00685 *listp = list;
00686 }
00687
00688
00689
00690 static void
00691 attrs_list_copy (attrs *dstp, attrs src)
00692 {
00693 attrs n;
00694
00695 attrs_list_clear (dstp);
00696 for (; src; src = src->next)
00697 {
00698 n = pool_alloc (attrs_pool);
00699 n->loc = src->loc;
00700 n->decl = src->decl;
00701 n->offset = src->offset;
00702 n->next = *dstp;
00703 *dstp = n;
00704 }
00705 }
00706
00707
00708
00709 static void
00710 attrs_list_union (attrs *dstp, attrs src)
00711 {
00712 for (; src; src = src->next)
00713 {
00714 if (!attrs_list_member (*dstp, src->decl, src->offset))
00715 attrs_list_insert (dstp, src->decl, src->offset, src->loc);
00716 }
00717 }
00718
00719
00720
00721 static void
00722 vars_clear (htab_t vars)
00723 {
00724 htab_empty (vars);
00725 }
00726
00727
00728
00729 static variable
00730 unshare_variable (dataflow_set *set, variable var)
00731 {
00732 void **slot;
00733 variable new_var;
00734 int i;
00735
00736 new_var = pool_alloc (var_pool);
00737 new_var->decl = var->decl;
00738 new_var->refcount = 1;
00739 var->refcount--;
00740 new_var->n_var_parts = var->n_var_parts;
00741
00742 for (i = 0; i < var->n_var_parts; i++)
00743 {
00744 location_chain node;
00745 location_chain *nextp;
00746
00747 new_var->var_part[i].offset = var->var_part[i].offset;
00748 nextp = &new_var->var_part[i].loc_chain;
00749 for (node = var->var_part[i].loc_chain; node; node = node->next)
00750 {
00751 location_chain new_lc;
00752
00753 new_lc = pool_alloc (loc_chain_pool);
00754 new_lc->next = NULL;
00755 new_lc->loc = node->loc;
00756
00757 *nextp = new_lc;
00758 nextp = &new_lc->next;
00759 }
00760
00761
00762
00763 if (new_var->var_part[i].loc_chain)
00764 new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
00765 else
00766 new_var->var_part[i].cur_loc = NULL;
00767 }
00768
00769 slot = htab_find_slot_with_hash (set->vars, new_var->decl,
00770 VARIABLE_HASH_VAL (new_var->decl),
00771 INSERT);
00772 *slot = new_var;
00773 return new_var;
00774 }
00775
00776
00777
00778
00779 static int
00780 vars_copy_1 (void **slot, void *data)
00781 {
00782 htab_t dst = (htab_t) data;
00783 variable src, *dstp;
00784
00785 src = *(variable *) slot;
00786 src->refcount++;
00787
00788 dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
00789 VARIABLE_HASH_VAL (src->decl),
00790 INSERT);
00791 *dstp = src;
00792
00793
00794 return 1;
00795 }
00796
00797
00798
00799 static void
00800 vars_copy (htab_t dst, htab_t src)
00801 {
00802 vars_clear (dst);
00803 htab_traverse (src, vars_copy_1, dst);
00804 }
00805
00806
00807
00808 static inline tree
00809 var_debug_decl (tree decl)
00810 {
00811 if (decl && DECL_P (decl)
00812 && DECL_DEBUG_EXPR_IS_FROM (decl) && DECL_DEBUG_EXPR (decl)
00813 && DECL_P (DECL_DEBUG_EXPR (decl)))
00814 decl = DECL_DEBUG_EXPR (decl);
00815
00816 return decl;
00817 }
00818
00819
00820
00821 static void
00822 var_reg_set (dataflow_set *set, rtx loc)
00823 {
00824 tree decl = REG_EXPR (loc);
00825 HOST_WIDE_INT offset = REG_OFFSET (loc);
00826 attrs node;
00827
00828 decl = var_debug_decl (decl);
00829
00830 for (node = set->regs[REGNO (loc)]; node; node = node->next)
00831 if (node->decl == decl && node->offset == offset)
00832 break;
00833 if (!node)
00834 attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc);
00835 set_variable_part (set, loc, decl, offset);
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 static void
00846 var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify)
00847 {
00848 tree decl = REG_EXPR (loc);
00849 HOST_WIDE_INT offset = REG_OFFSET (loc);
00850 attrs node, next;
00851 attrs *nextp;
00852
00853 decl = var_debug_decl (decl);
00854
00855 nextp = &set->regs[REGNO (loc)];
00856 for (node = *nextp; node; node = next)
00857 {
00858 next = node->next;
00859 if (node->decl != decl || node->offset != offset)
00860 {
00861 delete_variable_part (set, node->loc, node->decl, node->offset);
00862 pool_free (attrs_pool, node);
00863 *nextp = next;
00864 }
00865 else
00866 {
00867 node->loc = loc;
00868 nextp = &node->next;
00869 }
00870 }
00871 if (modify)
00872 clobber_variable_part (set, loc, decl, offset);
00873 var_reg_set (set, loc);
00874 }
00875
00876
00877
00878
00879
00880 static void
00881 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
00882 {
00883 attrs *reg = &set->regs[REGNO (loc)];
00884 attrs node, next;
00885
00886 if (clobber)
00887 {
00888 tree decl = REG_EXPR (loc);
00889 HOST_WIDE_INT offset = REG_OFFSET (loc);
00890
00891 decl = var_debug_decl (decl);
00892
00893 clobber_variable_part (set, NULL, decl, offset);
00894 }
00895
00896 for (node = *reg; node; node = next)
00897 {
00898 next = node->next;
00899 delete_variable_part (set, node->loc, node->decl, node->offset);
00900 pool_free (attrs_pool, node);
00901 }
00902 *reg = NULL;
00903 }
00904
00905
00906
00907 static void
00908 var_regno_delete (dataflow_set *set, int regno)
00909 {
00910 attrs *reg = &set->regs[regno];
00911 attrs node, next;
00912
00913 for (node = *reg; node; node = next)
00914 {
00915 next = node->next;
00916 delete_variable_part (set, node->loc, node->decl, node->offset);
00917 pool_free (attrs_pool, node);
00918 }
00919 *reg = NULL;
00920 }
00921
00922
00923
00924
00925
00926 static void
00927 var_mem_set (dataflow_set *set, rtx loc)
00928 {
00929 tree decl = MEM_EXPR (loc);
00930 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
00931
00932 decl = var_debug_decl (decl);
00933
00934 set_variable_part (set, loc, decl, offset);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944 static void
00945 var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify)
00946 {
00947 tree decl = MEM_EXPR (loc);
00948 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
00949
00950 decl = var_debug_decl (decl);
00951
00952 if (modify)
00953 clobber_variable_part (set, NULL, decl, offset);
00954 var_mem_set (set, loc);
00955 }
00956
00957
00958
00959
00960
00961 static void
00962 var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
00963 {
00964 tree decl = MEM_EXPR (loc);
00965 HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
00966
00967 decl = var_debug_decl (decl);
00968 if (clobber)
00969 clobber_variable_part (set, NULL, decl, offset);
00970 delete_variable_part (set, loc, decl, offset);
00971 }
00972
00973
00974
00975
00976 static void
00977 dataflow_set_init (dataflow_set *set, int vars_size)
00978 {
00979 init_attrs_list_set (set->regs);
00980 set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq,
00981 variable_htab_free);
00982 set->stack_adjust = 0;
00983 }
00984
00985
00986
00987 static void
00988 dataflow_set_clear (dataflow_set *set)
00989 {
00990 int i;
00991
00992 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00993 attrs_list_clear (&set->regs[i]);
00994
00995 vars_clear (set->vars);
00996 }
00997
00998
00999
01000 static void
01001 dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
01002 {
01003 int i;
01004
01005 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01006 attrs_list_copy (&dst->regs[i], src->regs[i]);
01007
01008 vars_copy (dst->vars, src->vars);
01009 dst->stack_adjust = src->stack_adjust;
01010 }
01011
01012
01013
01014 struct variable_union_info
01015 {
01016
01017 location_chain lc;
01018
01019
01020 int pos;
01021
01022
01023 int pos_src;
01024 int pos_dst;
01025 };
01026
01027
01028
01029 static int
01030 variable_union_info_cmp_pos (const void *n1, const void *n2)
01031 {
01032 const struct variable_union_info *i1 = n1;
01033 const struct variable_union_info *i2 = n2;
01034
01035 if (i1->pos != i2->pos)
01036 return i1->pos - i2->pos;
01037
01038 return (i1->pos_dst - i2->pos_dst);
01039 }
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 static int
01052 variable_union (void **slot, void *data)
01053 {
01054 variable src, dst, *dstp;
01055 dataflow_set *set = (dataflow_set *) data;
01056 int i, j, k;
01057
01058 src = *(variable *) slot;
01059 dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl,
01060 VARIABLE_HASH_VAL (src->decl),
01061 INSERT);
01062 if (!*dstp)
01063 {
01064 src->refcount++;
01065
01066
01067
01068
01069 for (k = 0; k < src->n_var_parts; k++)
01070 {
01071 gcc_assert (!src->var_part[k].loc_chain
01072 == !src->var_part[k].cur_loc);
01073 if (src->var_part[k].loc_chain)
01074 {
01075 gcc_assert (src->var_part[k].cur_loc);
01076 if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
01077 break;
01078 }
01079 }
01080 if (k < src->n_var_parts)
01081 unshare_variable (set, src);
01082 else
01083 *dstp = src;
01084
01085
01086 return 1;
01087 }
01088 else
01089 dst = *dstp;
01090
01091 gcc_assert (src->n_var_parts);
01092
01093
01094 for (i = 0, j = 0, k = 0;
01095 i < src->n_var_parts && j < dst->n_var_parts; k++)
01096 {
01097 if (src->var_part[i].offset == dst->var_part[j].offset)
01098 {
01099 i++;
01100 j++;
01101 }
01102 else if (src->var_part[i].offset < dst->var_part[j].offset)
01103 i++;
01104 else
01105 j++;
01106 }
01107 k += src->n_var_parts - i;
01108 k += dst->n_var_parts - j;
01109
01110
01111
01112 gcc_assert (k <= MAX_VAR_PARTS);
01113
01114 if (dst->refcount > 1 && dst->n_var_parts != k)
01115 dst = unshare_variable (set, dst);
01116
01117 i = src->n_var_parts - 1;
01118 j = dst->n_var_parts - 1;
01119 dst->n_var_parts = k;
01120
01121 for (k--; k >= 0; k--)
01122 {
01123 location_chain node, node2;
01124
01125 if (i >= 0 && j >= 0
01126 && src->var_part[i].offset == dst->var_part[j].offset)
01127 {
01128
01129
01130
01131 int dst_l, src_l;
01132 int ii, jj, n;
01133 struct variable_union_info *vui;
01134
01135
01136
01137
01138 if (dst->refcount > 1)
01139 {
01140 for (node = src->var_part[i].loc_chain,
01141 node2 = dst->var_part[j].loc_chain; node && node2;
01142 node = node->next, node2 = node2->next)
01143 {
01144 if (!((REG_P (node2->loc)
01145 && REG_P (node->loc)
01146 && REGNO (node2->loc) == REGNO (node->loc))
01147 || rtx_equal_p (node2->loc, node->loc)))
01148 break;
01149 }
01150 if (node || node2)
01151 dst = unshare_variable (set, dst);
01152 }
01153
01154 src_l = 0;
01155 for (node = src->var_part[i].loc_chain; node; node = node->next)
01156 src_l++;
01157 dst_l = 0;
01158 for (node = dst->var_part[j].loc_chain; node; node = node->next)
01159 dst_l++;
01160 vui = XCNEWVEC (struct variable_union_info, src_l + dst_l);
01161
01162
01163 for (node = dst->var_part[j].loc_chain, jj = 0; node;
01164 node = node->next, jj++)
01165 {
01166 vui[jj].lc = node;
01167 vui[jj].pos_dst = jj;
01168
01169
01170 vui[jj].pos_src = src_l + dst_l;
01171 }
01172
01173
01174 n = dst_l;
01175 for (node = src->var_part[i].loc_chain, ii = 0; node;
01176 node = node->next, ii++)
01177 {
01178
01179 for (jj = 0; jj < dst_l; jj++)
01180 {
01181 if ((REG_P (vui[jj].lc->loc)
01182 && REG_P (node->loc)
01183 && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
01184 || rtx_equal_p (vui[jj].lc->loc, node->loc))
01185 {
01186 vui[jj].pos_src = ii;
01187 break;
01188 }
01189 }
01190 if (jj >= dst_l)
01191 {
01192 location_chain new_node;
01193
01194
01195 new_node = pool_alloc (loc_chain_pool);
01196 new_node->loc = node->loc;
01197 vui[n].lc = new_node;
01198 vui[n].pos_src = ii;
01199 vui[n].pos_dst = src_l + dst_l;
01200 n++;
01201 }
01202 }
01203
01204 for (ii = 0; ii < src_l + dst_l; ii++)
01205 vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst;
01206
01207 qsort (vui, n, sizeof (struct variable_union_info),
01208 variable_union_info_cmp_pos);
01209
01210
01211 for (ii = 1; ii < n; ii++)
01212 vui[ii - 1].lc->next = vui[ii].lc;
01213 vui[n - 1].lc->next = NULL;
01214
01215 dst->var_part[k].loc_chain = vui[0].lc;
01216 dst->var_part[k].offset = dst->var_part[j].offset;
01217
01218 free (vui);
01219 i--;
01220 j--;
01221 }
01222 else if ((i >= 0 && j >= 0
01223 && src->var_part[i].offset < dst->var_part[j].offset)
01224 || i < 0)
01225 {
01226 dst->var_part[k] = dst->var_part[j];
01227 j--;
01228 }
01229 else if ((i >= 0 && j >= 0
01230 && src->var_part[i].offset > dst->var_part[j].offset)
01231 || j < 0)
01232 {
01233 location_chain *nextp;
01234
01235
01236 nextp = &dst->var_part[k].loc_chain;
01237 for (node = src->var_part[i].loc_chain; node; node = node->next)
01238 {
01239 location_chain new_lc;
01240
01241 new_lc = pool_alloc (loc_chain_pool);
01242 new_lc->next = NULL;
01243 new_lc->loc = node->loc;
01244
01245 *nextp = new_lc;
01246 nextp = &new_lc->next;
01247 }
01248
01249 dst->var_part[k].offset = src->var_part[i].offset;
01250 i--;
01251 }
01252
01253
01254
01255 if (dst->var_part[k].loc_chain)
01256 dst->var_part[k].cur_loc = dst->var_part[k].loc_chain->loc;
01257 else
01258 dst->var_part[k].cur_loc = NULL;
01259 }
01260
01261
01262 return 1;
01263 }
01264
01265
01266
01267 static void
01268 dataflow_set_union (dataflow_set *dst, dataflow_set *src)
01269 {
01270 int i;
01271
01272 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01273 attrs_list_union (&dst->regs[i], src->regs[i]);
01274
01275 htab_traverse (src->vars, variable_union, dst);
01276 }
01277
01278
01279 static bool
01280 dataflow_set_different_value;
01281
01282 static bool
01283 variable_part_different_p (variable_part *vp1, variable_part *vp2)
01284 {
01285 location_chain lc1, lc2;
01286
01287 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
01288 {
01289 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
01290 {
01291 if (REG_P (lc1->loc) && REG_P (lc2->loc))
01292 {
01293 if (REGNO (lc1->loc) == REGNO (lc2->loc))
01294 break;
01295 }
01296 if (rtx_equal_p (lc1->loc, lc2->loc))
01297 break;
01298 }
01299 if (!lc2)
01300 return true;
01301 }
01302 return false;
01303 }
01304
01305
01306
01307
01308
01309 static bool
01310 variable_different_p (variable var1, variable var2,
01311 bool compare_current_location)
01312 {
01313 int i;
01314
01315 if (var1 == var2)
01316 return false;
01317
01318 if (var1->n_var_parts != var2->n_var_parts)
01319 return true;
01320
01321 for (i = 0; i < var1->n_var_parts; i++)
01322 {
01323 if (var1->var_part[i].offset != var2->var_part[i].offset)
01324 return true;
01325 if (compare_current_location)
01326 {
01327 if (!((REG_P (var1->var_part[i].cur_loc)
01328 && REG_P (var2->var_part[i].cur_loc)
01329 && (REGNO (var1->var_part[i].cur_loc)
01330 == REGNO (var2->var_part[i].cur_loc)))
01331 || rtx_equal_p (var1->var_part[i].cur_loc,
01332 var2->var_part[i].cur_loc)))
01333 return true;
01334 }
01335 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
01336 return true;
01337 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
01338 return true;
01339 }
01340 return false;
01341 }
01342
01343
01344
01345
01346 static int
01347 dataflow_set_different_1 (void **slot, void *data)
01348 {
01349 htab_t htab = (htab_t) data;
01350 variable var1, var2;
01351
01352 var1 = *(variable *) slot;
01353 var2 = htab_find_with_hash (htab, var1->decl,
01354 VARIABLE_HASH_VAL (var1->decl));
01355 if (!var2)
01356 {
01357 dataflow_set_different_value = true;
01358
01359
01360 return 0;
01361 }
01362
01363 if (variable_different_p (var1, var2, false))
01364 {
01365 dataflow_set_different_value = true;
01366
01367
01368 return 0;
01369 }
01370
01371
01372 return 1;
01373 }
01374
01375
01376
01377
01378 static int
01379 dataflow_set_different_2 (void **slot, void *data)
01380 {
01381 htab_t htab = (htab_t) data;
01382 variable var1, var2;
01383
01384 var1 = *(variable *) slot;
01385 var2 = htab_find_with_hash (htab, var1->decl,
01386 VARIABLE_HASH_VAL (var1->decl));
01387 if (!var2)
01388 {
01389 dataflow_set_different_value = true;
01390
01391
01392 return 0;
01393 }
01394
01395
01396
01397 gcc_assert (!variable_different_p (var1, var2, false));
01398
01399
01400 return 1;
01401 }
01402
01403
01404
01405 static bool
01406 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
01407 {
01408 dataflow_set_different_value = false;
01409
01410 htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars);
01411 if (!dataflow_set_different_value)
01412 {
01413
01414
01415
01416 htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars);
01417 }
01418 return dataflow_set_different_value;
01419 }
01420
01421
01422
01423 static void
01424 dataflow_set_destroy (dataflow_set *set)
01425 {
01426 int i;
01427
01428 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01429 attrs_list_clear (&set->regs[i]);
01430
01431 htab_delete (set->vars);
01432 set->vars = NULL;
01433 }
01434
01435
01436
01437 static bool
01438 contains_symbol_ref (rtx x)
01439 {
01440 const char *fmt;
01441 RTX_CODE code;
01442 int i;
01443
01444 if (!x)
01445 return false;
01446
01447 code = GET_CODE (x);
01448 if (code == SYMBOL_REF)
01449 return true;
01450
01451 fmt = GET_RTX_FORMAT (code);
01452 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
01453 {
01454 if (fmt[i] == 'e')
01455 {
01456 if (contains_symbol_ref (XEXP (x, i)))
01457 return true;
01458 }
01459 else if (fmt[i] == 'E')
01460 {
01461 int j;
01462 for (j = 0; j < XVECLEN (x, i); j++)
01463 if (contains_symbol_ref (XVECEXP (x, i, j)))
01464 return true;
01465 }
01466 }
01467
01468 return false;
01469 }
01470
01471
01472
01473 static bool
01474 track_expr_p (tree expr)
01475 {
01476 rtx decl_rtl;
01477 tree realdecl;
01478
01479
01480 if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
01481 return 0;
01482
01483
01484 if (!DECL_NAME (expr))
01485 return 0;
01486
01487
01488 decl_rtl = DECL_RTL_IF_SET (expr);
01489 if (!decl_rtl)
01490 return 0;
01491
01492
01493
01494
01495 realdecl = expr;
01496 if (DECL_DEBUG_EXPR_IS_FROM (realdecl) && DECL_DEBUG_EXPR (realdecl))
01497 {
01498 realdecl = DECL_DEBUG_EXPR (realdecl);
01499
01500
01501 if (!DECL_P (realdecl))
01502 return 0;
01503 }
01504
01505
01506
01507 if (DECL_IGNORED_P (realdecl))
01508 return 0;
01509
01510
01511
01512 if (TREE_STATIC (realdecl))
01513 return 0;
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523 if (MEM_P (decl_rtl)
01524 && contains_symbol_ref (XEXP (decl_rtl, 0)))
01525 return 0;
01526
01527
01528
01529 if (MEM_P (decl_rtl))
01530 {
01531
01532 if (GET_MODE (decl_rtl) == BLKmode
01533 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
01534 return 0;
01535 if (MEM_SIZE (decl_rtl)
01536 && INTVAL (MEM_SIZE (decl_rtl)) > MAX_VAR_PARTS)
01537 return 0;
01538 }
01539
01540 return 1;
01541 }
01542
01543
01544
01545
01546 static bool
01547 same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
01548 {
01549 tree expr2;
01550 HOST_WIDE_INT offset2;
01551
01552 if (! DECL_P (expr))
01553 return false;
01554
01555 if (REG_P (loc))
01556 {
01557 expr2 = REG_EXPR (loc);
01558 offset2 = REG_OFFSET (loc);
01559 }
01560 else if (MEM_P (loc))
01561 {
01562 expr2 = MEM_EXPR (loc);
01563 offset2 = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
01564 }
01565 else
01566 return false;
01567
01568 if (! expr2 || ! DECL_P (expr2))
01569 return false;
01570
01571 expr = var_debug_decl (expr);
01572 expr2 = var_debug_decl (expr2);
01573
01574 return (expr == expr2 && offset == offset2);
01575 }
01576
01577
01578
01579
01580
01581 static int
01582 count_uses (rtx *loc, void *insn)
01583 {
01584 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
01585
01586 if (REG_P (*loc))
01587 {
01588 gcc_assert (REGNO (*loc) < FIRST_PSEUDO_REGISTER);
01589 VTI (bb)->n_mos++;
01590 }
01591 else if (MEM_P (*loc)
01592 && MEM_EXPR (*loc)
01593 && track_expr_p (MEM_EXPR (*loc)))
01594 {
01595 VTI (bb)->n_mos++;
01596 }
01597
01598 return 0;
01599 }
01600
01601
01602
01603 static void
01604 count_uses_1 (rtx *x, void *insn)
01605 {
01606 for_each_rtx (x, count_uses, insn);
01607 }
01608
01609
01610
01611
01612 static void
01613 count_stores (rtx loc, rtx expr ATTRIBUTE_UNUSED, void *insn)
01614 {
01615 count_uses (&loc, insn);
01616 }
01617
01618
01619
01620
01621 static int
01622 add_uses (rtx *loc, void *insn)
01623 {
01624 if (REG_P (*loc))
01625 {
01626 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
01627 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
01628
01629 mo->type = ((REG_EXPR (*loc) && track_expr_p (REG_EXPR (*loc)))
01630 ? MO_USE : MO_USE_NO_VAR);
01631 mo->u.loc = *loc;
01632 mo->insn = (rtx) insn;
01633 }
01634 else if (MEM_P (*loc)
01635 && MEM_EXPR (*loc)
01636 && track_expr_p (MEM_EXPR (*loc)))
01637 {
01638 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
01639 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
01640
01641 mo->type = MO_USE;
01642 mo->u.loc = *loc;
01643 mo->insn = (rtx) insn;
01644 }
01645
01646 return 0;
01647 }
01648
01649
01650
01651 static void
01652 add_uses_1 (rtx *x, void *insn)
01653 {
01654 for_each_rtx (x, add_uses, insn);
01655 }
01656
01657
01658
01659
01660
01661 static void
01662 add_stores (rtx loc, rtx expr, void *insn)
01663 {
01664 if (REG_P (loc))
01665 {
01666 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
01667 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
01668
01669 if (GET_CODE (expr) == CLOBBER
01670 || ! REG_EXPR (loc)
01671 || ! track_expr_p (REG_EXPR (loc)))
01672 mo->type = MO_CLOBBER;
01673 else if (GET_CODE (expr) == SET
01674 && SET_DEST (expr) == loc
01675 && same_variable_part_p (SET_SRC (expr),
01676 REG_EXPR (loc),
01677 REG_OFFSET (loc)))
01678 mo->type = MO_COPY;
01679 else
01680 mo->type = MO_SET;
01681 mo->u.loc = loc;
01682 mo->insn = NEXT_INSN ((rtx) insn);
01683 }
01684 else if (MEM_P (loc)
01685 && MEM_EXPR (loc)
01686 && track_expr_p (MEM_EXPR (loc)))
01687 {
01688 basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
01689 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
01690
01691 if (GET_CODE (expr) == CLOBBER)
01692 mo->type = MO_CLOBBER;
01693 else if (GET_CODE (expr) == SET
01694 && SET_DEST (expr) == loc
01695 && same_variable_part_p (SET_SRC (expr),
01696 MEM_EXPR (loc),
01697 MEM_OFFSET (loc)
01698 ? INTVAL (MEM_OFFSET (loc)) : 0))
01699 mo->type = MO_COPY;
01700 else
01701 mo->type = MO_SET;
01702 mo->u.loc = loc;
01703 mo->insn = NEXT_INSN ((rtx) insn);
01704 }
01705 }
01706
01707
01708
01709 static bool
01710 compute_bb_dataflow (basic_block bb)
01711 {
01712 int i, n, r;
01713 bool changed;
01714 dataflow_set old_out;
01715 dataflow_set *in = &VTI (bb)->in;
01716 dataflow_set *out = &VTI (bb)->out;
01717
01718 dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3);
01719 dataflow_set_copy (&old_out, out);
01720 dataflow_set_copy (out, in);
01721
01722 n = VTI (bb)->n_mos;
01723 for (i = 0; i < n; i++)
01724 {
01725 switch (VTI (bb)->mos[i].type)
01726 {
01727 case MO_CALL:
01728 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
01729 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
01730 var_regno_delete (out, r);
01731 break;
01732
01733 case MO_USE:
01734 {
01735 rtx loc = VTI (bb)->mos[i].u.loc;
01736
01737 if (GET_CODE (loc) == REG)
01738 var_reg_set (out, loc);
01739 else if (GET_CODE (loc) == MEM)
01740 var_mem_set (out, loc);
01741 }
01742 break;
01743
01744 case MO_SET:
01745 {
01746 rtx loc = VTI (bb)->mos[i].u.loc;
01747
01748 if (REG_P (loc))
01749 var_reg_delete_and_set (out, loc, true);
01750 else if (MEM_P (loc))
01751 var_mem_delete_and_set (out, loc, true);
01752 }
01753 break;
01754
01755 case MO_COPY:
01756 {
01757 rtx loc = VTI (bb)->mos[i].u.loc;
01758
01759 if (REG_P (loc))
01760 var_reg_delete_and_set (out, loc, false);
01761 else if (MEM_P (loc))
01762 var_mem_delete_and_set (out, loc, false);
01763 }
01764 break;
01765
01766 case MO_USE_NO_VAR:
01767 {
01768 rtx loc = VTI (bb)->mos[i].u.loc;
01769
01770 if (REG_P (loc))
01771 var_reg_delete (out, loc, false);
01772 else if (MEM_P (loc))
01773 var_mem_delete (out, loc, false);
01774 }
01775 break;
01776
01777 case MO_CLOBBER:
01778 {
01779 rtx loc = VTI (bb)->mos[i].u.loc;
01780
01781 if (REG_P (loc))
01782 var_reg_delete (out, loc, true);
01783 else if (MEM_P (loc))
01784 var_mem_delete (out, loc, true);
01785 }
01786 break;
01787
01788 case MO_ADJUST:
01789 out->stack_adjust += VTI (bb)->mos[i].u.adjust;
01790 break;
01791 }
01792 }
01793
01794 changed = dataflow_set_different (&old_out, out);
01795 dataflow_set_destroy (&old_out);
01796 return changed;
01797 }
01798
01799
01800
01801 static void
01802 vt_find_locations (void)
01803 {
01804 fibheap_t worklist, pending, fibheap_swap;
01805 sbitmap visited, in_worklist, in_pending, sbitmap_swap;
01806 basic_block bb;
01807 edge e;
01808 int *bb_order;
01809 int *rc_order;
01810 int i;
01811
01812
01813
01814 rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
01815 bb_order = XNEWVEC (int, last_basic_block);
01816 pre_and_rev_post_order_compute (NULL, rc_order, false);
01817 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
01818 bb_order[rc_order[i]] = i;
01819 free (rc_order);
01820
01821 worklist = fibheap_new ();
01822 pending = fibheap_new ();
01823 visited = sbitmap_alloc (last_basic_block);
01824 in_worklist = sbitmap_alloc (last_basic_block);
01825 in_pending = sbitmap_alloc (last_basic_block);
01826 sbitmap_zero (in_worklist);
01827
01828 FOR_EACH_BB (bb)
01829 fibheap_insert (pending, bb_order[bb->index], bb);
01830 sbitmap_ones (in_pending);
01831
01832 while (!fibheap_empty (pending))
01833 {
01834 fibheap_swap = pending;
01835 pending = worklist;
01836 worklist = fibheap_swap;
01837 sbitmap_swap = in_pending;
01838 in_pending = in_worklist;
01839 in_worklist = sbitmap_swap;
01840
01841 sbitmap_zero (visited);
01842
01843 while (!fibheap_empty (worklist))
01844 {
01845 bb = fibheap_extract_min (worklist);
01846 RESET_BIT (in_worklist, bb->index);
01847 if (!TEST_BIT (visited, bb->index))
01848 {
01849 bool changed;
01850 edge_iterator ei;
01851
01852 SET_BIT (visited, bb->index);
01853
01854
01855 dataflow_set_clear (&VTI (bb)->in);
01856 FOR_EACH_EDGE (e, ei, bb->preds)
01857 {
01858 dataflow_set_union (&VTI (bb)->in, &VTI (e->src)->out);
01859 }
01860
01861 changed = compute_bb_dataflow (bb);
01862 if (changed)
01863 {
01864 FOR_EACH_EDGE (e, ei, bb->succs)
01865 {
01866 if (e->dest == EXIT_BLOCK_PTR)
01867 continue;
01868
01869 if (e->dest == bb)
01870 continue;
01871
01872 if (TEST_BIT (visited, e->dest->index))
01873 {
01874 if (!TEST_BIT (in_pending, e->dest->index))
01875 {
01876
01877 SET_BIT (in_pending, e->dest->index);
01878 fibheap_insert (pending,
01879 bb_order[e->dest->index],
01880 e->dest);
01881 }
01882 }
01883 else if (!TEST_BIT (in_worklist, e->dest->index))
01884 {
01885
01886 SET_BIT (in_worklist, e->dest->index);
01887 fibheap_insert (worklist, bb_order[e->dest->index],
01888 e->dest);
01889 }
01890 }
01891 }
01892 }
01893 }
01894 }
01895
01896 free (bb_order);
01897 fibheap_delete (worklist);
01898 fibheap_delete (pending);
01899 sbitmap_free (visited);
01900 sbitmap_free (in_worklist);
01901 sbitmap_free (in_pending);
01902 }
01903
01904
01905
01906 static void
01907 dump_attrs_list (attrs list)
01908 {
01909 for (; list; list = list->next)
01910 {
01911 print_mem_expr (dump_file, list->decl);
01912 fprintf (dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset);
01913 }
01914 fprintf (dump_file, "\n");
01915 }
01916
01917
01918
01919 static int
01920 dump_variable (void **slot, void *data ATTRIBUTE_UNUSED)
01921 {
01922 variable var = *(variable *) slot;
01923 int i;
01924 location_chain node;
01925
01926 fprintf (dump_file, " name: %s\n",
01927 IDENTIFIER_POINTER (DECL_NAME (var->decl)));
01928 for (i = 0; i < var->n_var_parts; i++)
01929 {
01930 fprintf (dump_file, " offset %ld\n",
01931 (long) var->var_part[i].offset);
01932 for (node = var->var_part[i].loc_chain; node; node = node->next)
01933 {
01934 fprintf (dump_file, " ");
01935 print_rtl_single (dump_file, node->loc);
01936 }
01937 }
01938
01939
01940 return 1;
01941 }
01942
01943
01944
01945 static void
01946 dump_vars (htab_t vars)
01947 {
01948 if (htab_elements (vars) > 0)
01949 {
01950 fprintf (dump_file, "Variables:\n");
01951 htab_traverse (vars, dump_variable, NULL);
01952 }
01953 }
01954
01955
01956
01957 static void
01958 dump_dataflow_set (dataflow_set *set)
01959 {
01960 int i;
01961
01962 fprintf (dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n",
01963 set->stack_adjust);
01964 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
01965 {
01966 if (set->regs[i])
01967 {
01968 fprintf (dump_file, "Reg %d:", i);
01969 dump_attrs_list (set->regs[i]);
01970 }
01971 }
01972 dump_vars (set->vars);
01973 fprintf (dump_file, "\n");
01974 }
01975
01976
01977
01978 static void
01979 dump_dataflow_sets (void)
01980 {
01981 basic_block bb;
01982
01983 FOR_EACH_BB (bb)
01984 {
01985 fprintf (dump_file, "\nBasic block %d:\n", bb->index);
01986 fprintf (dump_file, "IN:\n");
01987 dump_dataflow_set (&VTI (bb)->in);
01988 fprintf (dump_file, "OUT:\n");
01989 dump_dataflow_set (&VTI (bb)->out);
01990 }
01991 }
01992
01993
01994
01995
01996 static void
01997 variable_was_changed (variable var, htab_t htab)
01998 {
01999 hashval_t hash = VARIABLE_HASH_VAL (var->decl);
02000
02001 if (emit_notes)
02002 {
02003 variable *slot;
02004
02005 slot = (variable *) htab_find_slot_with_hash (changed_variables,
02006 var->decl, hash, INSERT);
02007
02008 if (htab && var->n_var_parts == 0)
02009 {
02010 variable empty_var;
02011 void **old;
02012
02013 empty_var = pool_alloc (var_pool);
02014 empty_var->decl = var->decl;
02015 empty_var->refcount = 1;
02016 empty_var->n_var_parts = 0;
02017 *slot = empty_var;
02018
02019 old = htab_find_slot_with_hash (htab, var->decl, hash,
02020 NO_INSERT);
02021 if (old)
02022 htab_clear_slot (htab, old);
02023 }
02024 else
02025 {
02026 *slot = var;
02027 }
02028 }
02029 else
02030 {
02031 gcc_assert (htab);
02032 if (var->n_var_parts == 0)
02033 {
02034 void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
02035 NO_INSERT);
02036 if (slot)
02037 htab_clear_slot (htab, slot);
02038 }
02039 }
02040 }
02041
02042
02043
02044
02045
02046
02047 static inline int
02048 find_variable_location_part (variable var, HOST_WIDE_INT offset,
02049 int *insertion_point)
02050 {
02051 int pos, low, high;
02052
02053
02054 low = 0;
02055 high = var->n_var_parts;
02056 while (low != high)
02057 {
02058 pos = (low + high) / 2;
02059 if (var->var_part[pos].offset < offset)
02060 low = pos + 1;
02061 else
02062 high = pos;
02063 }
02064 pos = low;
02065
02066 if (insertion_point)
02067 *insertion_point = pos;
02068
02069 if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
02070 return pos;
02071
02072 return -1;
02073 }
02074
02075
02076
02077
02078
02079 static void
02080 set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
02081 {
02082 int pos;
02083 location_chain node, next;
02084 location_chain *nextp;
02085 variable var;
02086 void **slot;
02087
02088 slot = htab_find_slot_with_hash (set->vars, decl,
02089 VARIABLE_HASH_VAL (decl), INSERT);
02090 if (!*slot)
02091 {
02092
02093 var = pool_alloc (var_pool);
02094 var->decl = decl;
02095 var->refcount = 1;
02096 var->n_var_parts = 1;
02097 var->var_part[0].offset = offset;
02098 var->var_part[0].loc_chain = NULL;
02099 var->var_part[0].cur_loc = NULL;
02100 *slot = var;
02101 pos = 0;
02102 }
02103 else
02104 {
02105 int inspos = 0;
02106
02107 var = (variable) *slot;
02108
02109 pos = find_variable_location_part (var, offset, &inspos);
02110
02111 if (pos >= 0)
02112 {
02113 node = var->var_part[pos].loc_chain;
02114
02115 if (node
02116 && ((REG_P (node->loc) && REG_P (loc)
02117 && REGNO (node->loc) == REGNO (loc))
02118 || rtx_equal_p (node->loc, loc)))
02119 {
02120
02121
02122 return;
02123 }
02124 else
02125 {
02126
02127 if (var->refcount > 1)
02128 var = unshare_variable (set, var);
02129 }
02130 }
02131 else
02132 {
02133
02134
02135
02136 if (var->refcount > 1)
02137 var = unshare_variable (set, var);
02138
02139
02140
02141 gcc_assert (var->n_var_parts < MAX_VAR_PARTS);
02142
02143
02144
02145 for (pos = var->n_var_parts; pos > inspos; pos--)
02146 var->var_part[pos] = var->var_part[pos - 1];
02147
02148 var->n_var_parts++;
02149 var->var_part[pos].offset = offset;
02150 var->var_part[pos].loc_chain = NULL;
02151 var->var_part[pos].cur_loc = NULL;
02152 }
02153 }
02154
02155
02156 nextp = &var->var_part[pos].loc_chain;
02157 for (node = var->var_part[pos].loc_chain; node; node = next)
02158 {
02159 next = node->next;
02160 if ((REG_P (node->loc) && REG_P (loc)
02161 && REGNO (node->loc) == REGNO (loc))
02162 || rtx_equal_p (node->loc, loc))
02163 {
02164 pool_free (loc_chain_pool, node);
02165 *nextp = next;
02166 break;
02167 }
02168 else
02169 nextp = &node->next;
02170 }
02171
02172
02173 node = pool_alloc (loc_chain_pool);
02174 node->loc = loc;
02175 node->next = var->var_part[pos].loc_chain;
02176 var->var_part[pos].loc_chain = node;
02177
02178
02179 if (var->var_part[pos].cur_loc == NULL)
02180 {
02181 var->var_part[pos].cur_loc = loc;
02182 variable_was_changed (var, set->vars);
02183 }
02184 }
02185
02186
02187
02188
02189
02190
02191 static void
02192 clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
02193 HOST_WIDE_INT offset)
02194 {
02195 void **slot;
02196
02197 if (! decl || ! DECL_P (decl))
02198 return;
02199
02200 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
02201 NO_INSERT);
02202 if (slot)
02203 {
02204 variable var = (variable) *slot;
02205 int pos = find_variable_location_part (var, offset, NULL);
02206
02207 if (pos >= 0)
02208 {
02209 location_chain node, next;
02210
02211
02212 next = var->var_part[pos].loc_chain;
02213 for (node = next; node; node = next)
02214 {
02215 next = node->next;
02216 if (node->loc != loc)
02217 {
02218 if (REG_P (node->loc))
02219 {
02220 attrs anode, anext;
02221 attrs *anextp;
02222
02223
02224
02225
02226
02227 anextp = &set->regs[REGNO (node->loc)];
02228 for (anode = *anextp; anode; anode = anext)
02229 {
02230 anext = anode->next;
02231 if (anode->decl == decl
02232 && anode->offset == offset)
02233 {
02234 pool_free (attrs_pool, anode);
02235 *anextp = anext;
02236 }
02237 }
02238 }
02239
02240 delete_variable_part (set, node->loc, decl, offset);
02241 }
02242 }
02243 }
02244 }
02245 }
02246
02247
02248
02249
02250
02251 static void
02252 delete_variable_part (dataflow_set *set, rtx loc, tree decl,
02253 HOST_WIDE_INT offset)
02254 {
02255 void **slot;
02256
02257 slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
02258 NO_INSERT);
02259 if (slot)
02260 {
02261 variable var = (variable) *slot;
02262 int pos = find_variable_location_part (var, offset, NULL);
02263
02264 if (pos >= 0)
02265 {
02266 location_chain node, next;
02267 location_chain *nextp;
02268 bool changed;
02269
02270 if (var->refcount > 1)
02271 {
02272
02273
02274 for (node = var->var_part[pos].loc_chain; node;
02275 node = node->next)
02276 {
02277 if ((REG_P (node->loc) && REG_P (loc)
02278 && REGNO (node->loc) == REGNO (loc))
02279 || rtx_equal_p (node->loc, loc))
02280 {
02281 var = unshare_variable (set, var);
02282 break;
02283 }
02284 }
02285 }
02286
02287
02288 nextp = &var->var_part[pos].loc_chain;
02289 for (node = *nextp; node; node = next)
02290 {
02291 next = node->next;
02292 if ((REG_P (node->loc) && REG_P (loc)
02293 && REGNO (node->loc) == REGNO (loc))
02294 || rtx_equal_p (node->loc, loc))
02295 {
02296 pool_free (loc_chain_pool, node);
02297 *nextp = next;
02298 break;
02299 }
02300 else
02301 nextp = &node->next;
02302 }
02303
02304
02305
02306
02307 if (var->var_part[pos].cur_loc
02308 && ((REG_P (loc)
02309 && REG_P (var->var_part[pos].cur_loc)
02310 && REGNO (loc) == REGNO (var->var_part[pos].cur_loc))
02311 || rtx_equal_p (loc, var->var_part[pos].cur_loc)))
02312 {
02313 changed = true;
02314 if (var->var_part[pos].loc_chain)
02315 var->var_part[pos].cur_loc = var->var_part[pos].loc_chain->loc;
02316 }
02317 else
02318 changed = false;
02319
02320 if (var->var_part[pos].loc_chain == NULL)
02321 {
02322 var->n_var_parts--;
02323 while (pos < var->n_var_parts)
02324 {
02325 var->var_part[pos] = var->var_part[pos + 1];
02326 pos++;
02327 }
02328 }
02329 if (changed)
02330 variable_was_changed (var, set->vars);
02331 }
02332 }
02333 }
02334
02335
02336
02337
02338
02339 static int
02340 emit_note_insn_var_location (void **varp, void *data)
02341 {
02342 variable var = *(variable *) varp;
02343 rtx insn = ((emit_note_data *)data)->insn;
02344 enum emit_note_where where = ((emit_note_data *)data)->where;
02345 rtx note;
02346 int i, j, n_var_parts;
02347 bool complete;
02348 HOST_WIDE_INT last_limit;
02349 tree type_size_unit;
02350 HOST_WIDE_INT offsets[MAX_VAR_PARTS];
02351 rtx loc[MAX_VAR_PARTS];
02352
02353 gcc_assert (var->decl);
02354
02355 complete = true;
02356 last_limit = 0;
02357 n_var_parts = 0;
02358 for (i = 0; i < var->n_var_parts; i++)
02359 {
02360 enum machine_mode mode, wider_mode;
02361
02362 if (last_limit < var->var_part[i].offset)
02363 {
02364 complete = false;
02365 break;
02366 }
02367 else if (last_limit > var->var_part[i].offset)
02368 continue;
02369 offsets[n_var_parts] = var->var_part[i].offset;
02370 loc[n_var_parts] = var->var_part[i].loc_chain->loc;
02371 mode = GET_MODE (loc[n_var_parts]);
02372 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
02373
02374
02375 wider_mode = GET_MODE_WIDER_MODE (mode);
02376 for (j = i + 1; j < var->n_var_parts; j++)
02377 if (last_limit <= var->var_part[j].offset)
02378 break;
02379 if (j < var->n_var_parts
02380 && wider_mode != VOIDmode
02381 && GET_CODE (loc[n_var_parts])
02382 == GET_CODE (var->var_part[j].loc_chain->loc)
02383 && mode == GET_MODE (var->var_part[j].loc_chain->loc)
02384 && last_limit == var->var_part[j].offset)
02385 {
02386 rtx new_loc = NULL;
02387 rtx loc2 = var->var_part[j].loc_chain->loc;
02388
02389 if (REG_P (loc[n_var_parts])
02390 && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
02391 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
02392 && REGNO (loc[n_var_parts])
02393 + hard_regno_nregs[REGNO (loc[n_var_parts])][mode]
02394 == REGNO (loc2))
02395 {
02396 if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
02397 new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
02398 mode, 0);
02399 else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
02400 new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
02401 if (new_loc)
02402 {
02403 if (!REG_P (new_loc)
02404 || REGNO (new_loc) != REGNO (loc[n_var_parts]))
02405 new_loc = NULL;
02406 else
02407 REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
02408 }
02409 }
02410 else if (MEM_P (loc[n_var_parts])
02411 && GET_CODE (XEXP (loc2, 0)) == PLUS
02412 && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG
02413 && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT)
02414 {
02415 if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG
02416 && rtx_equal_p (XEXP (loc[n_var_parts], 0),
02417 XEXP (XEXP (loc2, 0), 0))
02418 && INTVAL (XEXP (XEXP (loc2, 0), 1))
02419 == GET_MODE_SIZE (mode))
02420 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
02421 && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1))
02422 == CONST_INT
02423 && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
02424 XEXP (XEXP (loc2, 0), 0))
02425 && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
02426 + GET_MODE_SIZE (mode)
02427 == INTVAL (XEXP (XEXP (loc2, 0), 1))))
02428 new_loc = adjust_address_nv (loc[n_var_parts],
02429 wider_mode, 0);
02430 }
02431
02432 if (new_loc)
02433 {
02434 loc[n_var_parts] = new_loc;
02435 mode = wider_mode;
02436 last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
02437 i = j;
02438 }
02439 }
02440 ++n_var_parts;
02441 }
02442 type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
02443 if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
02444 complete = false;
02445
02446 if (where == EMIT_NOTE_AFTER_INSN)
02447 note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
02448 else
02449 note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
02450
02451 if (!complete)
02452 {
02453 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
02454 NULL_RTX);
02455 }
02456 else if (n_var_parts == 1)
02457 {
02458 rtx expr_list
02459 = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
02460
02461 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
02462 expr_list);
02463 }
02464 else if (n_var_parts)
02465 {
02466 rtx parallel;
02467
02468 for (i = 0; i < n_var_parts; i++)
02469 loc[i]
02470 = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
02471
02472 parallel = gen_rtx_PARALLEL (VOIDmode,
02473 gen_rtvec_v (n_var_parts, loc));
02474 NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
02475 parallel);
02476 }
02477
02478 htab_clear_slot (changed_variables, varp);
02479
02480
02481
02482
02483 if (var->n_var_parts == 0)
02484 {
02485 pool_free (var_pool, var);
02486 }
02487
02488
02489 return 1;
02490 }
02491
02492
02493
02494
02495
02496 static void
02497 emit_notes_for_changes (rtx insn, enum emit_note_where where)
02498 {
02499 emit_note_data data;
02500
02501 data.insn = insn;
02502 data.where = where;
02503 htab_traverse (changed_variables, emit_note_insn_var_location, &data);
02504 }
02505
02506
02507
02508
02509 static int
02510 emit_notes_for_differences_1 (void **slot, void *data)
02511 {
02512 htab_t new_vars = (htab_t) data;
02513 variable old_var, new_var;
02514
02515 old_var = *(variable *) slot;
02516 new_var = htab_find_with_hash (new_vars, old_var->decl,
02517 VARIABLE_HASH_VAL (old_var->decl));
02518
02519 if (!new_var)
02520 {
02521
02522 variable empty_var;
02523
02524 empty_var = pool_alloc (var_pool);
02525 empty_var->decl = old_var->decl;
02526 empty_var->refcount = 1;
02527 empty_var->n_var_parts = 0;
02528 variable_was_changed (empty_var, NULL);
02529 }
02530 else if (variable_different_p (old_var, new_var, true))
02531 {
02532 variable_was_changed (new_var, NULL);
02533 }
02534
02535
02536 return 1;
02537 }
02538
02539
02540
02541
02542 static int
02543 emit_notes_for_differences_2 (void **slot, void *data)
02544 {
02545 htab_t old_vars = (htab_t) data;
02546 variable old_var, new_var;
02547
02548 new_var = *(variable *) slot;
02549 old_var = htab_find_with_hash (old_vars, new_var->decl,
02550 VARIABLE_HASH_VAL (new_var->decl));
02551 if (!old_var)
02552 {
02553
02554 variable_was_changed (new_var, NULL);
02555 }
02556
02557
02558 return 1;
02559 }
02560
02561
02562
02563
02564 static void
02565 emit_notes_for_differences (rtx insn, dataflow_set *old_set,
02566 dataflow_set *new_set)
02567 {
02568 htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars);
02569 htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars);
02570 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
02571 }
02572
02573
02574
02575 static void
02576 emit_notes_in_bb (basic_block bb)
02577 {
02578 int i;
02579 dataflow_set set;
02580
02581 dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3);
02582 dataflow_set_copy (&set, &VTI (bb)->in);
02583
02584 for (i = 0; i < VTI (bb)->n_mos; i++)
02585 {
02586 rtx insn = VTI (bb)->mos[i].insn;
02587
02588 switch (VTI (bb)->mos[i].type)
02589 {
02590 case MO_CALL:
02591 {
02592 int r;
02593
02594 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
02595 if (TEST_HARD_REG_BIT (call_used_reg_set, r))
02596 {
02597 var_regno_delete (&set, r);
02598 }
02599 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
02600 }
02601 break;
02602
02603 case MO_USE:
02604 {
02605 rtx loc = VTI (bb)->mos[i].u.loc;
02606
02607 if (GET_CODE (loc) == REG)
02608 var_reg_set (&set, loc);
02609 else
02610 var_mem_set (&set, loc);
02611
02612 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
02613 }
02614 break;
02615
02616 case MO_SET:
02617 {
02618 rtx loc = VTI (bb)->mos[i].u.loc;
02619
02620 if (REG_P (loc))
02621 var_reg_delete_and_set (&set, loc, true);
02622 else
02623 var_mem_delete_and_set (&set, loc, true);
02624
02625 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
02626 }
02627 break;
02628
02629 case MO_COPY:
02630 {
02631 rtx loc = VTI (bb)->mos[i].u.loc;
02632
02633 if (REG_P (loc))
02634 var_reg_delete_and_set (&set, loc, false);
02635 else
02636 var_mem_delete_and_set (&set, loc, false);
02637
02638 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
02639 }
02640 break;
02641
02642 case MO_USE_NO_VAR:
02643 {
02644 rtx loc = VTI (bb)->mos[i].u.loc;
02645
02646 if (REG_P (loc))
02647 var_reg_delete (&set, loc, false);
02648 else
02649 var_mem_delete (&set, loc, false);
02650
02651 emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
02652 }
02653 break;
02654
02655 case MO_CLOBBER:
02656 {
02657 rtx loc = VTI (bb)->mos[i].u.loc;
02658
02659 if (REG_P (loc))
02660 var_reg_delete (&set, loc, true);
02661 else
02662 var_mem_delete (&set, loc, true);
02663
02664 emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
02665 }
02666 break;
02667
02668 case MO_ADJUST:
02669 set.stack_adjust += VTI (bb)->mos[i].u.adjust;
02670 break;
02671 }
02672 }
02673 dataflow_set_destroy (&set);
02674 }
02675
02676
02677
02678 static void
02679 vt_emit_notes (void)
02680 {
02681 basic_block bb;
02682 dataflow_set *last_out;
02683 dataflow_set empty;
02684
02685 gcc_assert (!htab_elements (changed_variables));
02686
02687
02688
02689 emit_notes = true;
02690
02691 dataflow_set_init (&empty, 7);
02692 last_out = ∅
02693
02694 FOR_EACH_BB (bb)
02695 {
02696
02697
02698 emit_notes_for_differences (BB_HEAD (bb), last_out, &VTI (bb)->in);
02699
02700
02701 emit_notes_in_bb (bb);
02702
02703 last_out = &VTI (bb)->out;
02704 }
02705 dataflow_set_destroy (&empty);
02706 emit_notes = false;
02707 }
02708
02709
02710
02711
02712 static bool
02713 vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
02714 {
02715 if (REG_P (rtl))
02716 {
02717 if (REG_ATTRS (rtl))
02718 {
02719 *declp = REG_EXPR (rtl);
02720 *offsetp = REG_OFFSET (rtl);
02721 return true;
02722 }
02723 }
02724 else if (MEM_P (rtl))
02725 {
02726 if (MEM_ATTRS (rtl))
02727 {
02728 *declp = MEM_EXPR (rtl);
02729 *offsetp = MEM_OFFSET (rtl) ? INTVAL (MEM_OFFSET (rtl)) : 0;
02730 return true;
02731 }
02732 }
02733 return false;
02734 }
02735
02736
02737
02738 static void
02739 vt_add_function_parameters (void)
02740 {
02741 tree parm;
02742
02743 for (parm = DECL_ARGUMENTS (current_function_decl);
02744 parm; parm = TREE_CHAIN (parm))
02745 {
02746 rtx decl_rtl = DECL_RTL_IF_SET (parm);
02747 rtx incoming = DECL_INCOMING_RTL (parm);
02748 tree decl;
02749 HOST_WIDE_INT offset;
02750 dataflow_set *out;
02751
02752 if (TREE_CODE (parm) != PARM_DECL)
02753 continue;
02754
02755 if (!DECL_NAME (parm))
02756 continue;
02757
02758 if (!decl_rtl || !incoming)
02759 continue;
02760
02761 if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode)
02762 continue;
02763
02764 if (!vt_get_decl_and_offset (incoming, &decl, &offset))
02765 if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
02766 continue;
02767
02768 if (!decl)
02769 continue;
02770
02771 gcc_assert (parm == decl);
02772
02773 out = &VTI (ENTRY_BLOCK_PTR)->out;
02774
02775 if (REG_P (incoming))
02776 {
02777 gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
02778 attrs_list_insert (&out->regs[REGNO (incoming)],
02779 parm, offset, incoming);
02780 set_variable_part (out, incoming, parm, offset);
02781 }
02782 else if (MEM_P (incoming))
02783 set_variable_part (out, incoming, parm, offset);
02784 }
02785 }
02786
02787
02788
02789
02790 static void
02791 vt_initialize (void)
02792 {
02793 basic_block bb;
02794
02795 alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
02796
02797 FOR_EACH_BB (bb)
02798 {
02799 rtx insn;
02800 HOST_WIDE_INT pre, post = 0;
02801
02802
02803 VTI (bb)->n_mos = 0;
02804 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
02805 insn = NEXT_INSN (insn))
02806 {
02807 if (INSN_P (insn))
02808 {
02809 if (!frame_pointer_needed)
02810 {
02811 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
02812 if (pre)
02813 VTI (bb)->n_mos++;
02814 if (post)
02815 VTI (bb)->n_mos++;
02816 }
02817 note_uses (&PATTERN (insn), count_uses_1, insn);
02818 note_stores (PATTERN (insn), count_stores, insn);
02819 if (CALL_P (insn))
02820 VTI (bb)->n_mos++;
02821 }
02822 }
02823
02824
02825 VTI (bb)->mos = XNEWVEC (micro_operation, VTI (bb)->n_mos);
02826 VTI (bb)->n_mos = 0;
02827 for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
02828 insn = NEXT_INSN (insn))
02829 {
02830 if (INSN_P (insn))
02831 {
02832 int n1, n2;
02833
02834 if (!frame_pointer_needed)
02835 {
02836 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
02837 if (pre)
02838 {
02839 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
02840
02841 mo->type = MO_ADJUST;
02842 mo->u.adjust = pre;
02843 mo->insn = insn;
02844 }
02845 }
02846
02847 n1 = VTI (bb)->n_mos;
02848 note_uses (&PATTERN (insn), add_uses_1, insn);
02849 n2 = VTI (bb)->n_mos - 1;
02850
02851
02852 while (n1 < n2)
02853 {
02854 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
02855 n1++;
02856 while (n1 < n2 && VTI (bb)->mos[n2].type == MO_USE_NO_VAR)
02857 n2--;
02858 if (n1 < n2)
02859 {
02860 micro_operation sw;
02861
02862 sw = VTI (bb)->mos[n1];
02863 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
02864 VTI (bb)->mos[n2] = sw;
02865 }
02866 }
02867
02868 if (CALL_P (insn))
02869 {
02870 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
02871
02872 mo->type = MO_CALL;
02873 mo->insn = insn;
02874 }
02875
02876 n1 = VTI (bb)->n_mos;
02877
02878
02879
02880 note_stores (PATTERN (insn), add_stores, insn);
02881 n2 = VTI (bb)->n_mos - 1;
02882
02883
02884 while (n1 < n2)
02885 {
02886 while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER)
02887 n1++;
02888 while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET
02889 || VTI (bb)->mos[n2].type == MO_COPY))
02890 n2--;
02891 if (n1 < n2)
02892 {
02893 micro_operation sw;
02894
02895 sw = VTI (bb)->mos[n1];
02896 VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
02897 VTI (bb)->mos[n2] = sw;
02898 }
02899 }
02900
02901 if (!frame_pointer_needed && post)
02902 {
02903 micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
02904
02905 mo->type = MO_ADJUST;
02906 mo->u.adjust = post;
02907 mo->insn = insn;
02908 }
02909 }
02910 }
02911 }
02912
02913
02914 FOR_ALL_BB (bb)
02915 {
02916 VTI (bb)->visited = false;
02917 dataflow_set_init (&VTI (bb)->in, 7);
02918 dataflow_set_init (&VTI (bb)->out, 7);
02919 }
02920
02921 attrs_pool = create_alloc_pool ("attrs_def pool",
02922 sizeof (struct attrs_def), 1024);
02923 var_pool = create_alloc_pool ("variable_def pool",
02924 sizeof (struct variable_def), 64);
02925 loc_chain_pool = create_alloc_pool ("location_chain_def pool",
02926 sizeof (struct location_chain_def),
02927 1024);
02928 changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
02929 NULL);
02930 vt_add_function_parameters ();
02931 }
02932
02933
02934
02935 static void
02936 vt_finalize (void)
02937 {
02938 basic_block bb;
02939
02940 FOR_EACH_BB (bb)
02941 {
02942 free (VTI (bb)->mos);
02943 }
02944
02945 FOR_ALL_BB (bb)
02946 {
02947 dataflow_set_destroy (&VTI (bb)->in);
02948 dataflow_set_destroy (&VTI (bb)->out);
02949 }
02950 free_aux_for_blocks ();
02951 free_alloc_pool (attrs_pool);
02952 free_alloc_pool (var_pool);
02953 free_alloc_pool (loc_chain_pool);
02954 htab_delete (changed_variables);
02955 }
02956
02957
02958
02959 unsigned int
02960 variable_tracking_main (void)
02961 {
02962 if (n_basic_blocks > 500 && n_edges / n_basic_blocks >= 20)
02963 return 0;
02964
02965 mark_dfs_back_edges ();
02966 vt_initialize ();
02967 if (!frame_pointer_needed)
02968 {
02969 if (!vt_stack_adjustments ())
02970 {
02971 vt_finalize ();
02972 return 0;
02973 }
02974 }
02975
02976 vt_find_locations ();
02977 vt_emit_notes ();
02978
02979 if (dump_file && (dump_flags & TDF_DETAILS))
02980 {
02981 dump_dataflow_sets ();
02982 dump_flow_info (dump_file, dump_flags);
02983 }
02984
02985 vt_finalize ();
02986 return 0;
02987 }
02988
02989 static bool
02990 gate_handle_var_tracking (void)
02991 {
02992 return (flag_var_tracking);
02993 }
02994
02995
02996
02997 struct tree_opt_pass pass_variable_tracking =
02998 {
02999 "vartrack",
03000 gate_handle_var_tracking,
03001 variable_tracking_main,
03002 NULL,
03003 NULL,
03004 0,
03005 TV_VAR_TRACKING,
03006 0,
03007 0,
03008 0,
03009 0,
03010 TODO_dump_func,
03011 'V'
03012 };
03013