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