OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [var-tracking.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.