source: trunk/third/gcc/stupid.c @ 11288

Revision 11288, 18.4 KB checked in by ghudson, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11287, which included commits to RCS files with non-trunk default branches.
Line 
1/* Dummy data flow analysis for GNU compiler in nonoptimizing mode.
2   Copyright (C) 1987, 91, 94, 95, 96, 1997 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21
22/* This file performs stupid register allocation, which is used
23   when cc1 gets the -noreg switch (which is when cc does not get -O).
24
25   Stupid register allocation goes in place of the the flow_analysis,
26   local_alloc and global_alloc passes.  combine_instructions cannot
27   be done with stupid allocation because the data flow info that it needs
28   is not computed here.
29
30   In stupid allocation, the only user-defined variables that can
31   go in registers are those declared "register".  They are assumed
32   to have a life span equal to their scope.  Other user variables
33   are given stack slots in the rtl-generation pass and are not
34   represented as pseudo regs.  A compiler-generated temporary
35   is assumed to live from its first mention to its last mention.
36
37   Since each pseudo-reg's life span is just an interval, it can be
38   represented as a pair of numbers, each of which identifies an insn by
39   its position in the function (number of insns before it).  The first
40   thing done for stupid allocation is to compute such a number for each
41   insn.  It is called the suid.  Then the life-interval of each
42   pseudo reg is computed.  Then the pseudo regs are ordered by priority
43   and assigned hard regs in priority order.  */
44
45#include "config.h"
46#include <stdio.h>
47#include "rtl.h"
48#include "hard-reg-set.h"
49#include "regs.h"
50#include "flags.h"
51
52/* Vector mapping INSN_UIDs to suids.
53   The suids are like uids but increase monotonically always.
54   We use them to see whether a subroutine call came
55   between a variable's birth and its death.  */
56
57static int *uid_suid;
58
59/* Get the suid of an insn.  */
60
61#define INSN_SUID(INSN) (uid_suid[INSN_UID (INSN)])
62
63/* Record the suid of the last CALL_INSN
64   so we can tell whether a pseudo reg crosses any calls.  */
65
66static int last_call_suid;
67
68/* Record the suid of the last NOTE_INSN_SETJMP
69   so we can tell whether a pseudo reg crosses any setjmp.  */
70
71static int last_setjmp_suid;
72
73/* Element N is suid of insn where life span of pseudo reg N ends.
74   Element is  0 if register N has not been seen yet on backward scan.  */
75
76static int *reg_where_dead;
77
78/* Element N is suid of insn where life span of pseudo reg N begins.  */
79
80static int *reg_where_born;
81
82/* Numbers of pseudo-regs to be allocated, highest priority first.  */
83
84static int *reg_order;
85
86/* Indexed by reg number (hard or pseudo), nonzero if register is live
87   at the current point in the instruction stream.  */
88
89static char *regs_live;
90
91/* Indexed by reg number, nonzero if reg was used in a SUBREG that changes
92   its size.  */
93
94static char *regs_change_size;
95
96/* Indexed by reg number, nonzero if reg crosses a setjmp.  */
97
98static char *regs_crosses_setjmp;
99
100/* Indexed by insn's suid, the set of hard regs live after that insn.  */
101
102static HARD_REG_SET *after_insn_hard_regs;
103
104/* Record that hard reg REGNO is live after insn INSN.  */
105
106#define MARK_LIVE_AFTER(INSN,REGNO)  \
107  SET_HARD_REG_BIT (after_insn_hard_regs[INSN_SUID (INSN)], (REGNO))
108
109static int stupid_reg_compare   PROTO((const GENERIC_PTR,const GENERIC_PTR));
110static int stupid_find_reg      PROTO((int, enum reg_class, enum machine_mode,
111                                       int, int, int));
112static void stupid_mark_refs    PROTO((rtx, rtx));
113
114/* Stupid life analysis is for the case where only variables declared
115   `register' go in registers.  For this case, we mark all
116   pseudo-registers that belong to register variables as
117   dying in the last instruction of the function, and all other
118   pseudo registers as dying in the last place they are referenced.
119   Hard registers are marked as dying in the last reference before
120   the end or before each store into them.  */
121
122void
123stupid_life_analysis (f, nregs, file)
124     rtx f;
125     int nregs;
126     FILE *file;
127{
128  register int i;
129  register rtx last, insn;
130  int max_uid, max_suid;
131
132  bzero (regs_ever_live, sizeof regs_ever_live);
133
134  regs_live = (char *) alloca (nregs);
135
136  /* First find the last real insn, and count the number of insns,
137     and assign insns their suids.  */
138
139  for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
140    if (INSN_UID (insn) > i)
141      i = INSN_UID (insn);
142
143  max_uid = i + 1;
144  uid_suid = (int *) alloca ((i + 1) * sizeof (int));
145
146  /* Compute the mapping from uids to suids.
147     Suids are numbers assigned to insns, like uids,
148     except that suids increase monotonically through the code.  */
149
150  last = 0;                     /* In case of empty function body */
151  for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
152    {
153      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
154        last = insn;
155
156      INSN_SUID (insn) = ++i;
157    }
158
159  last_call_suid = i + 1;
160  last_setjmp_suid = i + 1;
161  max_suid = i + 1;
162
163  max_regno = nregs;
164
165  /* Allocate tables to record info about regs.  */
166
167  reg_where_dead = (int *) alloca (nregs * sizeof (int));
168  bzero ((char *) reg_where_dead, nregs * sizeof (int));
169
170  reg_where_born = (int *) alloca (nregs * sizeof (int));
171  bzero ((char *) reg_where_born, nregs * sizeof (int));
172
173  reg_order = (int *) alloca (nregs * sizeof (int));
174  bzero ((char *) reg_order, nregs * sizeof (int));
175
176  regs_change_size = (char *) alloca (nregs * sizeof (char));
177  bzero ((char *) regs_change_size, nregs * sizeof (char));
178
179  regs_crosses_setjmp = (char *) alloca (nregs * sizeof (char));
180  bzero ((char *) regs_crosses_setjmp, nregs * sizeof (char));
181
182  /* Allocate the reg_renumber array */
183  allocate_reg_info (max_regno, FALSE, TRUE);
184  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
185    reg_renumber[i] = i;
186
187  after_insn_hard_regs
188    = (HARD_REG_SET *) alloca (max_suid * sizeof (HARD_REG_SET));
189
190  bzero ((char *) after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
191
192  /* Allocate and zero out many data structures
193     that will record the data from lifetime analysis.  */
194
195  allocate_for_life_analysis ();
196
197  for (i = 0; i < max_regno; i++)
198    REG_N_DEATHS (i) = 1;
199
200  bzero (regs_live, nregs);
201
202  /* Find where each pseudo register is born and dies,
203     by scanning all insns from the end to the start
204     and noting all mentions of the registers.
205
206     Also find where each hard register is live
207     and record that info in after_insn_hard_regs.
208     regs_live[I] is 1 if hard reg I is live
209     at the current point in the scan.  */
210
211  for (insn = last; insn; insn = PREV_INSN (insn))
212    {
213      register HARD_REG_SET *p = after_insn_hard_regs + INSN_SUID (insn);
214
215      /* Copy the info in regs_live into the element of after_insn_hard_regs
216         for the current position in the rtl code.  */
217
218      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
219        if (regs_live[i])
220          SET_HARD_REG_BIT (*p, i);
221
222      /* Update which hard regs are currently live
223         and also the birth and death suids of pseudo regs
224         based on the pattern of this insn.  */
225
226      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
227        stupid_mark_refs (PATTERN (insn), insn);
228
229      if (GET_CODE (insn) == NOTE
230          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
231        last_setjmp_suid = INSN_SUID (insn);
232
233      /* Mark all call-clobbered regs as live after each call insn
234         so that a pseudo whose life span includes this insn
235         will not go in one of them.
236         Then mark those regs as all dead for the continuing scan
237         of the insns before the call.  */
238
239      if (GET_CODE (insn) == CALL_INSN)
240        {
241          last_call_suid = INSN_SUID (insn);
242          IOR_HARD_REG_SET (after_insn_hard_regs[last_call_suid],
243                            call_used_reg_set);
244
245          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
246            if (call_used_regs[i])
247              regs_live[i] = 0;
248
249          /* It is important that this be done after processing the insn's
250             pattern because we want the function result register to still
251             be live if it's also used to pass arguments.  */
252          stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
253        }
254    }
255
256  /* Now decide the order in which to allocate the pseudo registers.  */
257
258  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
259    reg_order[i] = i;
260
261  qsort (&reg_order[LAST_VIRTUAL_REGISTER + 1],
262         max_regno - LAST_VIRTUAL_REGISTER - 1, sizeof (int),
263         stupid_reg_compare);
264
265  /* Now, in that order, try to find hard registers for those pseudo regs.  */
266
267  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
268    {
269      register int r = reg_order[i];
270
271      /* Some regnos disappear from the rtl.  Ignore them to avoid crash.
272         Also don't allocate registers that cross a setjmp, or live across
273         a call if this function receives a nonlocal goto.  */
274      if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
275          || (REG_N_CALLS_CROSSED (r) > 0
276              && current_function_has_nonlocal_label))
277        continue;
278
279      /* Now find the best hard-register class for this pseudo register */
280      if (N_REG_CLASSES > 1)
281        reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
282                                           reg_preferred_class (r),
283                                           PSEUDO_REGNO_MODE (r),
284                                           reg_where_born[r],
285                                           reg_where_dead[r],
286                                           regs_change_size[r]);
287
288      /* If no reg available in that class, try alternate class.  */
289      if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS)
290        reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
291                                           reg_alternate_class (r),
292                                           PSEUDO_REGNO_MODE (r),
293                                           reg_where_born[r],
294                                           reg_where_dead[r],
295                                           regs_change_size[r]);
296    }
297
298  if (file)
299    dump_flow_info (file);
300}
301
302/* Comparison function for qsort.
303   Returns -1 (1) if register *R1P is higher priority than *R2P.  */
304
305static int
306stupid_reg_compare (r1p, r2p)
307     const GENERIC_PTR r1p;
308     const GENERIC_PTR r2p;
309{
310  register int r1 = *(int *)r1p, r2 = *(int *)r2p;
311  register int len1 = reg_where_dead[r1] - reg_where_born[r1];
312  register int len2 = reg_where_dead[r2] - reg_where_born[r2];
313  int tem;
314
315  tem = len2 - len1;
316  if (tem != 0)
317    return tem;
318
319  tem = REG_N_REFS (r1) - REG_N_REFS (r2);
320  if (tem != 0)
321    return tem;
322
323  /* If regs are equally good, sort by regno,
324     so that the results of qsort leave nothing to chance.  */
325  return r1 - r2;
326}
327
328/* Find a block of SIZE words of hard registers in reg_class CLASS
329   that can hold a value of machine-mode MODE
330     (but actually we test only the first of the block for holding MODE)
331   currently free from after insn whose suid is BORN_INSN
332   through the insn whose suid is DEAD_INSN,
333   and return the number of the first of them.
334   Return -1 if such a block cannot be found.
335
336   If CALL_PRESERVED is nonzero, insist on registers preserved
337   over subroutine calls, and return -1 if cannot find such.
338
339   If CHANGES_SIZE is nonzero, it means this register was used as the
340   operand of a SUBREG that changes its size.  */
341
342static int
343stupid_find_reg (call_preserved, class, mode,
344                 born_insn, dead_insn, changes_size)
345     int call_preserved;
346     enum reg_class class;
347     enum machine_mode mode;
348     int born_insn, dead_insn;
349     int changes_size;
350{
351  register int i, ins;
352#ifdef HARD_REG_SET
353  register              /* Declare them register if they are scalars.  */
354#endif
355    HARD_REG_SET used, this_reg;
356#ifdef ELIMINABLE_REGS
357  static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
358#endif
359
360  /* If this register's life is more than 5,000 insns, we probably
361     can't allocate it, so don't waste the time trying.  This avoids
362     quadratic behavior on programs that have regularly-occurring
363     SAVE_EXPRs.  */
364  if (dead_insn > born_insn + 5000)
365    return -1;
366
367  COPY_HARD_REG_SET (used,
368                     call_preserved ? call_used_reg_set : fixed_reg_set);
369
370#ifdef ELIMINABLE_REGS
371  for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++)
372    SET_HARD_REG_BIT (used, eliminables[i].from);
373#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
374  SET_HARD_REG_BIT (used, HARD_FRAME_POINTER_REGNUM);
375#endif
376#else
377  SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
378#endif
379
380  for (ins = born_insn; ins < dead_insn; ins++)
381    IOR_HARD_REG_SET (used, after_insn_hard_regs[ins]);
382
383  IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
384
385#ifdef CLASS_CANNOT_CHANGE_SIZE
386  if (changes_size)
387    IOR_HARD_REG_SET (used,
388                      reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
389#endif
390
391  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
392    {
393#ifdef REG_ALLOC_ORDER
394      int regno = reg_alloc_order[i];
395#else
396      int regno = i;
397#endif
398
399      /* If a register has screwy overlap problems,
400         don't use it at all if not optimizing.
401         Actually this is only for the 387 stack register,
402         and it's because subsequent code won't work.  */
403#ifdef OVERLAPPING_REGNO_P
404      if (OVERLAPPING_REGNO_P (regno))
405        continue;
406#endif
407
408      if (! TEST_HARD_REG_BIT (used, regno)
409          && HARD_REGNO_MODE_OK (regno, mode))
410        {
411          register int j;
412          register int size1 = HARD_REGNO_NREGS (regno, mode);
413          for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
414          if (j == size1)
415            {
416              CLEAR_HARD_REG_SET (this_reg);
417              while (--j >= 0)
418                SET_HARD_REG_BIT (this_reg, regno + j);
419              for (ins = born_insn; ins < dead_insn; ins++)
420                {
421                  IOR_HARD_REG_SET (after_insn_hard_regs[ins], this_reg);
422                }
423              return regno;
424            }
425#ifndef REG_ALLOC_ORDER
426          i += j;               /* Skip starting points we know will lose */
427#endif
428        }
429    }
430
431  return -1;
432}
433
434/* Walk X, noting all assignments and references to registers
435   and recording what they imply about life spans.
436   INSN is the current insn, supplied so we can find its suid.  */
437
438static void
439stupid_mark_refs (x, insn)
440     rtx x, insn;
441{
442  register RTX_CODE code;
443  register char *fmt;
444  register int regno, i;
445
446  if (x == 0)
447    return;
448
449  code = GET_CODE (x);
450
451  if (code == SET || code == CLOBBER)
452    {
453      if (SET_DEST (x) != 0
454          && (GET_CODE (SET_DEST (x)) == REG
455              || (GET_CODE (SET_DEST (x)) == SUBREG
456                  && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
457                  && (REGNO (SUBREG_REG (SET_DEST (x)))
458                      >= FIRST_PSEUDO_REGISTER))))
459        {
460          /* Register is being assigned.  */
461          /* If setting a SUBREG, we treat the entire reg as being set.  */
462          if (GET_CODE (SET_DEST (x)) == SUBREG)
463            regno = REGNO (SUBREG_REG (SET_DEST (x)));
464          else
465            regno = REGNO (SET_DEST (x));
466
467          /* For hard regs, update the where-live info.  */
468          if (regno < FIRST_PSEUDO_REGISTER)
469            {
470              register int j
471                = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (x)));
472
473              while (--j >= 0)
474                {
475                  regs_ever_live[regno+j] = 1;
476                  regs_live[regno+j] = 0;
477
478                  /* The following line is for unused outputs;
479                     they do get stored even though never used again.  */
480                  MARK_LIVE_AFTER (insn, regno+j);
481
482                  /* When a hard reg is clobbered, mark it in use
483                     just before this insn, so it is live all through.  */
484                  if (code == CLOBBER && INSN_SUID (insn) > 0)
485                    SET_HARD_REG_BIT (after_insn_hard_regs[INSN_SUID (insn) - 1],
486                                      regno+j);
487                }
488            }
489          /* For pseudo regs, record where born, where dead, number of
490             times used, and whether live across a call.  */
491          else
492            {
493              /* Update the life-interval bounds of this pseudo reg.  */
494
495              /* When a pseudo-reg is CLOBBERed, it is born just before
496                 the clobbering insn.  When setting, just after.  */
497              int where_born = INSN_SUID (insn) - (code == CLOBBER);
498
499              reg_where_born[regno] = where_born;
500
501              /* The reg must live at least one insn even
502                 in it is never again used--because it has to go
503                 in SOME hard reg.  Mark it as dying after the current
504                 insn so that it will conflict with any other outputs of
505                 this insn.  */
506              if (reg_where_dead[regno] < where_born + 2)
507                {
508                  reg_where_dead[regno] = where_born + 2;
509                  regs_live[regno] = 1;
510                }
511
512              /* Count the refs of this reg.  */
513              REG_N_REFS (regno)++;
514
515              if (last_call_suid < reg_where_dead[regno])
516                REG_N_CALLS_CROSSED (regno) += 1;
517
518              if (last_setjmp_suid < reg_where_dead[regno])
519                regs_crosses_setjmp[regno] = 1;
520
521              /* If this register is only used in this insn and is only
522                 set, mark it unused.  We have to do this even when not
523                 optimizing so that MD patterns which count on this
524                 behavior (e.g., it not causing an output reload on
525                 an insn setting CC) will operate correctly.  */
526              if (GET_CODE (SET_DEST (x)) == REG
527                  && REGNO_FIRST_UID (regno) == INSN_UID (insn)
528                  && REGNO_LAST_UID (regno) == INSN_UID (insn)
529                  && (code == CLOBBER || ! reg_mentioned_p (SET_DEST (x),
530                                                            SET_SRC (x))))
531                REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED,
532                                            SET_DEST (x), REG_NOTES (insn));
533            }
534        }
535
536      /* Record references from the value being set,
537         or from addresses in the place being set if that's not a reg.
538         If setting a SUBREG, we treat the entire reg as *used*.  */
539      if (code == SET)
540        {
541          stupid_mark_refs (SET_SRC (x), insn);
542          if (GET_CODE (SET_DEST (x)) != REG)
543            stupid_mark_refs (SET_DEST (x), insn);
544        }
545      return;
546    }
547
548  else if (code == SUBREG
549           && GET_CODE (SUBREG_REG (x)) == REG
550           && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
551           && (GET_MODE_SIZE (GET_MODE (x))
552               != GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
553           && (INTEGRAL_MODE_P (GET_MODE (x))
554               || INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (x)))))
555    regs_change_size[REGNO (SUBREG_REG (x))] = 1;
556
557  /* Register value being used, not set.  */
558
559  else if (code == REG)
560    {
561      regno = REGNO (x);
562      if (regno < FIRST_PSEUDO_REGISTER)
563        {
564          /* Hard reg: mark it live for continuing scan of previous insns.  */
565          register int j = HARD_REGNO_NREGS (regno, GET_MODE (x));
566          while (--j >= 0)
567            {
568              regs_ever_live[regno+j] = 1;
569              regs_live[regno+j] = 1;
570            }
571        }
572      else
573        {
574          /* Pseudo reg: record first use, last use and number of uses.  */
575
576          reg_where_born[regno] = INSN_SUID (insn);
577          REG_N_REFS (regno)++;
578          if (regs_live[regno] == 0)
579            {
580              regs_live[regno] = 1;
581              reg_where_dead[regno] = INSN_SUID (insn);
582            }
583        }
584      return;
585    }
586
587  /* Recursive scan of all other rtx's.  */
588
589  fmt = GET_RTX_FORMAT (code);
590  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
591    {
592      if (fmt[i] == 'e')
593        stupid_mark_refs (XEXP (x, i), insn);
594      if (fmt[i] == 'E')
595        {
596          register int j;
597          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
598            stupid_mark_refs (XVECEXP (x, i, j), insn);
599        }
600    }
601}
Note: See TracBrowser for help on using the repository browser.