aboutsummaryrefslogtreecommitdiff
path: root/gcc-1.40/local-alloc.c
blob: beb3799e7945d93929a6f4eea07b2912281605ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
/* Allocate registers within a basic block, for GNU compiler.
   Copyright (C) 1987, 1988 Free Software Foundation, Inc.

This file is part of GNU CC.

GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.

GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */


/* Allocation of hard register numbers to pseudo registers is done in
   two passes.  In this pass we consider only regs that are born and
   die once within one basic block.  We do this one basic block at a
   time.  Then the next pass allocates the registers that remain.
   Two passes are used because this pass uses methods that work only
   on linear code, but that do a better job than the general methods
   used in global_alloc, and more quickly too.

   The assignments made are recorded in the vector reg_renumber
   whose space is allocated here.  The rtl code itself is not altered.

   We assign each instruction in the basic block a number
   which is its order from the beginning of the block.
   Then we can represent the lifetime of a pseudo register with
   a pair of numbers, and check for conflicts easily.
   We can record the availability of hard registers with a
   HARD_REG_SET for each instruction.  The HARD_REG_SET
   contains 0 or 1 for each hard reg.

   To avoid register shuffling, we tie registers together when one
   dies by being copied into another, or dies in an instruction that
   does arithmetic to produce another.  The tied registers are
   allocated as one.  Registers with different reg class preferences
   can never be tied unless the class preferred by one is a subclass
   of the one preferred by the other.

   Tying is represented with "quantity numbers".
   A non-tied register is given a new quantity number.
   Tied registers have the same quantity number.
   
   We have provision to exempt registers, even when they are contained
   within the block, that can be tied to others that are not contained in it.
   This is so that global_alloc could process them both and tie them then.
   But this is currently disabled since tying in global_alloc is not
   yet implemented.  */

#include <stdio.h>
#include "config.h"
#include "rtl.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "recog.h"

/* What about hardware registers used and set within same insn?
   Will that ever happen for a non-fixed register?
   Our lifetime-tracking for hardware registers would lose.
   [This caution is an old comment that may be obsolete;
    I think there is no longer a problem, but I'm not sure.]  */

/* Next quantity number available for allocation.  */

static int next_qty;

/* In all the following vectors indexed by quantity number,
   only elements at indices >= FIRST_PSEUDO_REGISTER are actually used.  */

/* Element Q is the hard reg number chosen for quantity Q,
   or -1 if none was found.  */

static short *qty_phys_reg;

/* Element Q is the hard reg number suggested for quantity Q,
   or -1 if no specific suggestion.  */

static short *qty_phys_sugg;

/* Element Q is the number of refs to quantity Q.  */

static short *qty_n_refs;

/* Element Q is a reg class contained in (smaller than) the
   preferred classes of all the pseudo regs that are tied in quantity Q.
   This is the preferred class for allocating that quantity.  */

static enum reg_class *qty_min_class;

/* Insn number (counting from head of basic block)
   where quantity Q was born.  -1 if birth has not been recorded.  */

static int *qty_birth;

/* Insn number (counting from head of basic block)
   where quantity Q died.  Due to the way tying is done,
   and the fact that we consider in this pass only regs that die but once,
   a quantity can die only once.  Each quantity's life span
   is a set of consecutive insns.  -1 if death has not been recorded.  */

static int *qty_death;

/* Number of words needed to hold the data in quantity Q.
   This depends on its machine mode.  It is used for these purposes:
   1. If it is 0, the qty is not really in use and is not allocated.
   2. It is used in computing the relative importances of qtys,
      which determines the order in which we look for regs for them.
   3. It is used in rules that prevent tying several registers of
      different sizes in a way that is geometrically impossible
      (see combine_regs).  */

static int *qty_size;

/* This holds the mode of the registers that are tied to qty Q,
   or VOIDmode if registers with differing modes are tied together.  */

static enum machine_mode *qty_mode;

/* Number of times a reg tied to qty Q lives across a CALL_INSN.  */

static int *qty_n_calls_crossed;

/* Nonzero means don't allocate qty Q if we can't get its preferred class.  */

static char *qty_preferred_or_nothing;

/* reg_qty[N] (where N is a pseudo reg number)
   is the qty number of that reg (which is >= FIRST_PSEUDO_REGISTER),
   or -1 if (REG N) is not local to the current basic block,
   or -2 if not known yet.

   If N is < FIRST_PSEUDO_REGISTER, reg_qty[N] is -1.  */

static int *reg_qty;

/* The offset (in words) of register N within its quantity.
   This can be nonzero if register N is SImode, and has been tied
   to a subreg of a DImode register.  */

static int *reg_offset;

/* Vector of substitutions of register numbers,
   used to map pseudo regs into hardware regs.
   This is set up as a result of register allocation.
   Element N is the hard reg assigned to pseudo reg N,
   or is -1 if no hard reg was assigned.
   If N is a hard reg number, element N is N.  */

short *reg_renumber;

/* Set of hard registers live at the current point in the scan
   of the instructions in a basic block.  */

static HARD_REG_SET regs_live;

/* Indexed by insn-number-within-basic-block,
   a set or hard registers live *after* that insn.  */

static HARD_REG_SET *regs_live_at;

/* Nonzero if a CALL_INSN has been scanned
   but we have not yet seen a reference to the value returned.  */

static int call_seen;

/* Communicate local vars `insn_number' and `insn'
   from `block_alloc' to `reg_is_set' and `wipe_dead_reg'.  */
static int this_insn_number;
static rtx this_insn;

static void block_alloc ();
static int combine_regs ();
static void wipe_dead_reg ();
static int find_free_reg ();
static void reg_is_born ();
static void reg_is_set ();
static void mark_life ();
static void post_mark_life ();
static int qty_compare ();
static int qty_compare_1 ();
static int reg_meets_class_p ();
static int reg_class_subset_p ();
static int reg_classes_overlap_p ();
static void update_qty_class ();

/* Allocate a new quantity (new within current basic block)
   for register number REGNO which is born in insn number INSN_NUMBER
   within the block.  MODE and SIZE are info on reg REGNO.  */

static void
alloc_qty (regno, mode, size, insn_number)
     int regno;
     enum machine_mode mode;
     int size, insn_number;
{
  register int qty = next_qty++;
  reg_qty[regno] = qty;
  reg_offset[regno] = 0;
  qty_size[qty] = size;
  qty_mode[qty] = mode;
  qty_birth[qty] = insn_number;
  qty_n_calls_crossed[qty] = reg_n_calls_crossed[regno];
  qty_min_class[qty] = reg_preferred_class (regno);
  qty_preferred_or_nothing[qty] = reg_preferred_or_nothing (regno);
  qty_n_refs[qty] = reg_n_refs[regno];
}

/* Main entry point of this file.  */

void
local_alloc ()
{
  register int b, i;

  /* Allocate vectors of temporary data.
     See the declarations of these variables, above,
     for what they mean.  */

  qty_phys_reg = (short *) alloca (max_regno * sizeof (short));
  qty_phys_sugg = (short *) alloca (max_regno * sizeof (short));
  qty_birth = (int *) alloca (max_regno * sizeof (int));
  qty_death = (int *) alloca (max_regno * sizeof (int));
  qty_size = (int *) alloca (max_regno * sizeof (int));
  qty_mode = (enum machine_mode *) alloca (max_regno * sizeof (enum machine_mode));
  qty_n_calls_crossed = (int *) alloca (max_regno * sizeof (int));
  qty_min_class = (enum reg_class *) alloca (max_regno * sizeof (enum reg_class));
  qty_preferred_or_nothing = (char *) alloca (max_regno);
  qty_n_refs = (short *) alloca (max_regno * sizeof (short));

  reg_qty = (int *) alloca (max_regno * sizeof (int));
  reg_offset = (int *) alloca (max_regno * sizeof (int));

  reg_renumber = (short *) oballoc (max_regno * sizeof (short));
  for (i = 0; i < max_regno; i++)
    reg_renumber[i] = -1;

  /* This controls only how many elts of the `qty_...' vectors
     need to be zero for the first basic block.  */
  next_qty = max_regno;

  /* Allocate each block's local registers, block by block.  */

  for (b = 0; b < n_basic_blocks; b++)
    {
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
	{
	  reg_qty[i] = -1;
	}
      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
	{
	  qty_phys_sugg[i] = -1;
	  qty_birth[i] = -1;
	  qty_death[i] = -1;
	  /* Set reg_qty to -2 for pseudos in this block, -1 for others.  */
	  if (reg_basic_block[i] == b && reg_n_deaths[i] == 1)
	    reg_qty[i] = -2;
	  else
	    reg_qty[i] = -1;
	}

      bzero (reg_offset, max_regno * sizeof (int));

      /* NEXT_QTY indicates which elements of the `qty_...'
	 vectors might need to be initialized.  Initialize those,
	 with explicit loop if there are few, else with bzero.  */

      if (next_qty < FIRST_PSEUDO_REGISTER + 6)
	{
	  for (i = FIRST_PSEUDO_REGISTER; i < next_qty; i++)
	    {
	      qty_size[i] = 0;
	      qty_mode[i] = VOIDmode;
	      qty_min_class[i] = NO_REGS;
	      qty_preferred_or_nothing[i] = 0;
	      qty_n_calls_crossed[i] = 0;
	      qty_n_refs[i] = 0;
	    }
	}
      else
	{
	  int clear_length = next_qty - FIRST_PSEUDO_REGISTER;

#define CLEAR(vector)  \
   bzero ((vector) + FIRST_PSEUDO_REGISTER,    \
	  (sizeof (*(vector))) * clear_length)

	  CLEAR (qty_size);
	  CLEAR (qty_mode);
	  CLEAR (qty_min_class);
	  CLEAR (qty_preferred_or_nothing);
	  CLEAR (qty_n_calls_crossed);
	  CLEAR (qty_n_refs);
	}

      next_qty = FIRST_PSEUDO_REGISTER;

      block_alloc (b);
#ifdef USE_C_ALLOCA
      alloca (0);
#endif
    }
}

/* Allocate hard regs to the pseudo regs used only within block number B.
   Only the pseudos that die but once can be handled.  */

static void
block_alloc (b)
     int b;
{
  register int i, q;
  register rtx insn;
  int insn_number = 0;
  int insn_count = 0;
  short *qty_order;
  int *insn_map;

  call_seen = 0;

  /* Count the instructions in the basic block.  */

  insn = basic_block_end[b];
  while (1)
    {
      if (GET_CODE (insn) != NOTE)
	insn_count++;
      if (insn == basic_block_head[b])
	break;
      insn = PREV_INSN (insn);
    }

  /* +1 to leave room for a post_mark_life at the last insn.  */
  regs_live_at = (HARD_REG_SET *) alloca ((insn_count + 1)
					  * sizeof (HARD_REG_SET));
  bzero (regs_live_at, (insn_count + 1) * sizeof (HARD_REG_SET));

  /* This will be a map from uids to insn-numbers within the block.  */

  insn_map = (int *) alloca (get_max_uid () * sizeof (int));

  /* Initialize table of hardware registers currently live.  */

#ifdef HARD_REG_SET
  regs_live = *basic_block_live_at_start[b];
#else
  COPY_HARD_REG_SET (regs_live, basic_block_live_at_start[b]);
#endif

  /* This loop scans the instructions of the basic block
     and assigns quantities to registers.
     It computes which registers to tie.  */

  insn = basic_block_head[b];
  insn_number = 0;
  while (1)
    {
      register rtx body = PATTERN (insn);

      if (GET_CODE (insn) != NOTE)
	insn_number++;
      insn_map[INSN_UID (insn)] = insn_number;

      if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
	  || GET_CODE (insn) == CALL_INSN)
	{
	  register rtx link;
	  register int win = 0;
	  register rtx r0, r1;
	  int combined_regno = -1;
	  int insn_code_number = recog_memoized (insn);
	  int commutative = 0;

	  this_insn_number = insn_number;
	  this_insn = insn;

	  /* Set COMMUTATIVE if operands 1 and 2 are commutative.  */
	  if (insn_code_number >= 0
	      && insn_n_operands[insn_code_number] > 2
	      && insn_operand_constraint[insn_code_number][1][0] == '%')
	    commutative = 1;

	  /* Is this insn suitable for tying two registers?
	     If so, try doing that.
	     Suitable insns are (set reg0 reg1) and
	     (set reg0 (arithop reg1 ...)).
	     For a commutative operation, try (set reg0 (arithop ... reg1)).
	     Subregs in place of regs are also ok.
	     An insn with parallel sets is ok if the first set is suitable.

	     If tying is done, WIN is set nonzero.  */

	  if (GET_CODE (body) == SET
	      && (r0 = SET_DEST (body),
		  GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
	      && (r1 = SET_SRC (body),
		  GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
	    win = combine_regs (r1, r0, b, insn_number, insn);
	  else if (GET_CODE (body) == SET)
	    {
	      r0 = SET_DEST (body);
	      if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
		{
		  if (GET_RTX_FORMAT (GET_CODE (SET_SRC (body)))[0] == 'e'
		      && (r1 = XEXP (SET_SRC (body), 0),
			  GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
		    win = combine_regs (r1, r0, b, insn_number, insn);
		  if (win == 0 && commutative
		      && GET_RTX_FORMAT (GET_CODE (SET_SRC (body)))[1] == 'e'
		      && (r1 = XEXP (SET_SRC (body), 1),
			  GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
		    win = combine_regs (r1, r0, b, insn_number, insn);
		}
	    }
	  else if (GET_CODE (body) == PARALLEL)
	    {
	      rtx set1 = XVECEXP (body, 0, 0);
	      if (GET_CODE (set1) == SET 
		  && (r0 = SET_DEST (set1),
		      GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
		  && GET_RTX_FORMAT (GET_CODE (SET_SRC (set1)))[0] == 'e'
		  && (r1 = XEXP (SET_SRC (set1), 0),
		      GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
		win = combine_regs (r1, r0, b, insn_number, insn);
	      if (win == 0 && commutative && GET_CODE (set1) == SET 
		  && (r0 = SET_DEST (set1),
		      GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
		  && GET_RTX_FORMAT (GET_CODE (SET_SRC (set1)))[1] == 'e'
		  && (r1 = XEXP (SET_SRC (set1), 1),
		      GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
		win = combine_regs (r1, r0, b, insn_number, insn);
	    }

	  /* If registers were just tied, set COMBINED_REGNO
	     to the number of the register used in this insn
	     that was tied to the register set in this insn.
	     This register's qty should not be "killed".  */

	  if (win)
	    {
	      while (GET_CODE (r1) == SUBREG)
		r1 = SUBREG_REG (r1);
	      combined_regno = REGNO (r1);
	    }

	  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
	    {
	      /* Mark the death of everything that dies in this instruction,
		 except for anything that was just combined.  */
	      if (XEXP (link, 0)
		  && REG_NOTE_KIND (link) == REG_DEAD
		  && combined_regno != REGNO (XEXP (link, 0)))
		{
#if 0  /* The mechanism in reg_is_set that checks whether the qty dies here
	  ought to handle this case properly.  */
		  if (combined_regno >= 0 &&
		      reg_qty[combined_regno] == reg_qty[REGNO (XEXP (link, 0))])
		    /* Here for the death of the quotient in a divmod insn:
		       something that was born and dead in this insn
		       but combined with something else that also dies here.
		       Mark the qty as dying one instruction later.  */
		    wipe_dead_reg (XEXP (link, 0), insn_number,
				   insn_number + 1);
		  else
#endif
		    wipe_dead_reg (XEXP (link, 0), insn_number, insn_number);
		}
	      /* Also, if this insn introduces a "constant" register,
		 that could just be replaced by the value it is given here
		 (which can legitimately be an immediate operand),
		 tell global-alloc not to allocate it
		 unless it is used at least twice more.  */

	      else if (REG_NOTE_KIND (link) == REG_EQUIV
		       && GET_CODE (SET_DEST (body)) == REG
		       && general_operand (XEXP (link, 0), VOIDmode)
		       /* Don't inhibit allocation of a "constant" register
			  that we have already tied to something else!  */
		       && combined_regno < 0
		       /* Don't mess with things live during setjmp.  */
		       && reg_live_length[REGNO (SET_DEST (body))] >= 0)
		{
		  i = REGNO (SET_DEST (body));
		  if (reg_n_sets[i] > 1)
		    {
		      /* Register is set in another place => not really constant.
			 cse or flow can cause this to happen.
			 Ok, forget we ever thought it was constant.  */
		      GET_MODE (link) = VOIDmode;
		    }
		  else if (reg_n_refs[i] <= 2)
		    {
		      /* For a parameter copy, do let global-alloc
			 allocate it; otherwise we would be forced to
			 have a frame pointer.  */
		      if (! frame_pointer_needed
			  && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
			reg_live_length[i] = -2;
		      else
			reg_live_length[i] = -1;

		      /* If value is not constant, we have a parameter
			 or a static chain pointer.  Tell local-alloc
			 as well not to allocate it.  */
		      if (! CONSTANT_P (SET_SRC (PATTERN (insn))))
			{
			  reg_basic_block[i] = REG_BLOCK_GLOBAL;
			  reg_qty[i] = -1;
			}
		    }
		  else
		    /* In any case, lower its priority for global-alloc.  */
		    reg_live_length[i] *= 2;
		}
	    }

	  /* Allocate qty numbers for all registers local to this block
	     that are born (set) in this instruction.
	     A pseudo that already has a qty is not changed.  */

	  note_stores (PATTERN (insn), reg_is_set);
	}
      if (GET_CODE (insn) == CALL_INSN)
	call_seen = 1;
      if (insn == basic_block_end[b])
	break;
      /* We don't need this for the block's first instruction
	 since no regs we care about are live before that instruction.
	 Also we do not allocate space in regs_live_at for that instruction. */
      IOR_HARD_REG_SET (regs_live_at[insn_number], regs_live);
      insn = NEXT_INSN (insn);
    }

  /* Now every register that is local to this basic block
     should have been given a quantity, or else -1 meaning ignore it.
     Every quantity should have a known birth (verify this now).

     If a qty's death has not been established, it indicates a dead store.
     That is ok if the insn is not entirely dead.
     So set the qty'd death to just after its birth.  */

  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
    if (reg_basic_block[i] == b && reg_qty[i] >= 0)
      {
	/* In the case of a register that is used uninitialized,
	   the code above will miss the actual first use.
	   So count that first use as the birth.  */  
	if (qty_birth[reg_qty[i]] > insn_map[INSN_UID (reg_first_use[i])])
	  qty_birth[reg_qty[i]] = insn_map[INSN_UID (reg_first_use[i])];
      }

  for (i = FIRST_PSEUDO_REGISTER; i < next_qty; i++)
    {
      if (qty_birth[i] == -1)
	abort ();
      if (qty_death[i] == -1)
	qty_death[i] = qty_birth[i] + 1;
    }

  /* Now order the qtys so we assign them registers
     in order of decreasing length of life.  */
  qty_order = (short *) alloca (next_qty * sizeof (short));
  for (i = FIRST_PSEUDO_REGISTER; i < next_qty; i++)
    qty_order[i] = i;

#define EXCHANGE(I1, I2)  \
  { i = qty_order[I1]; qty_order[I1] = qty_order[I2]; qty_order[I2] = i; }

  if (next_qty == 2 + FIRST_PSEUDO_REGISTER)
    {
      if (qty_compare (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1) > 0)
	EXCHANGE (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1);
    }
  else if (next_qty == 3 + FIRST_PSEUDO_REGISTER)
    {
      if (qty_compare (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1) > 0)
	EXCHANGE (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1);
      if (qty_compare (FIRST_PSEUDO_REGISTER + 1, FIRST_PSEUDO_REGISTER + 2) > 0)
	EXCHANGE (FIRST_PSEUDO_REGISTER + 2, FIRST_PSEUDO_REGISTER + 1);
      if (qty_compare (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1) > 0)
	EXCHANGE (FIRST_PSEUDO_REGISTER, FIRST_PSEUDO_REGISTER + 1);
    }
  else if (next_qty > 3 + FIRST_PSEUDO_REGISTER)
    qsort (qty_order + FIRST_PSEUDO_REGISTER,
	   next_qty - FIRST_PSEUDO_REGISTER, sizeof (short), qty_compare_1);

  /* Now for each qty that is not a hardware register,
     look for a hardware register to put it in.
     First try the register class that is cheapest for this qty,
     if there is more than one class.  */

  for (i = FIRST_PSEUDO_REGISTER; i < next_qty; i++)
    {
      q = qty_order[i];
      if (qty_size[q] >= 0)
	{
	  if (N_REG_CLASSES > 1)
	    {
	      qty_phys_reg[q] = find_free_reg (qty_min_class[q], 
					       qty_mode[q], q, 0,
					       qty_birth[q], qty_death[q]);
	      if (qty_phys_reg[q] >= 0)
		continue;
	    }

	  if (!qty_preferred_or_nothing[q])
	    qty_phys_reg[q] = find_free_reg (GENERAL_REGS, 
					     qty_mode[q], q, 0,
					     qty_birth[q], qty_death[q]);
	}
    }

  /* Now propagate the register assignments
     to the pseudo regs belonging to the qtys.  */

  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
    if (reg_qty[i] >= 0 && qty_phys_reg[reg_qty[i]] >= 0)
      {
	reg_renumber[i] = qty_phys_reg[reg_qty[i]] + reg_offset[i];
      }
}

/* Compare two quantities' priority for getting real registers.
   We give quantities with hard-reg suggestions priority over all others.
   We give longer-lived quantities higher priority
   so that the shorter-lived ones will tend to be in the same places
   which gives in general the maximum room for the regs to
   be allocated by global-alloc.
   Regs with more references are also preferred.  */

static int
qty_compare (q1, q2)
     int q1, q2;
{
  register int tem = (qty_phys_sugg[q2] >= 0) - (qty_phys_sugg[q1] >= 0);
  if (tem != 0) return tem;
  return -((qty_n_refs[q1] + qty_death[q1] - qty_birth[q1]) * qty_size[q2]
	   - (qty_n_refs[q2] + qty_death[q2] - qty_birth[q2]) * qty_size[q1]);
}

static int
qty_compare_1 (q1, q2)
     short *q1, *q2;
{
  register int tem = (qty_phys_sugg[*q2] >= 0) - (qty_phys_sugg[*q1] >= 0);
  if (tem != 0) return tem;
  tem = -((qty_n_refs[*q1] + qty_death[*q1] - qty_birth[*q1]) * qty_size[*q2]
	  - (qty_n_refs[*q2] + qty_death[*q2] - qty_birth[*q2]) * qty_size[*q1]);
  if (tem != 0) return tem;
  /* If qtys are equally good, sort by qty number,
     so that the results of qsort leave nothing to chance.  */
  return *q1 - *q2;
}

/* Attempt to combine the two registers (rtx's) USEDREG and SETREG.
   Returns 1 if have done so, or 0 if cannot.

   Combining registers means marking them as having the same quantity
   and adjusting the offsets within the quantity if either of
   them is a SUBREG).

   We don't actually combine a hard reg with a pseudo; instead
   we just record the hard reg as the suggestion for the pseudo's quantity.
   If we really combined them, we could lose if the pseudo lives
   across an insn that clobbers the hard reg (eg, movstr).

   There are elaborate checks for the validity of combining.  */

   
static int
combine_regs (usedreg, setreg, b, insn_number, insn)
     rtx usedreg, setreg;
     int b;
     int insn_number;
     rtx insn;
{
  register int ureg, sreg;
  register int offset = 0;
  int usize, ssize;
  register int sqty;

  /* Determine the numbers and sizes of registers being used.  */

  while (GET_CODE (usedreg) == SUBREG)
    {
      offset += SUBREG_WORD (usedreg);
      usedreg = SUBREG_REG (usedreg);
    }
  if (GET_CODE (usedreg) != REG)
    return 0;
  ureg = REGNO (usedreg);
  usize = REG_SIZE (usedreg);

  while (GET_CODE (setreg) == SUBREG)
    {
      offset -= SUBREG_WORD (setreg);
      setreg = SUBREG_REG (setreg);
    }
  if (GET_CODE (setreg) != REG)
    return 0;
  sreg = REGNO (setreg);
  ssize = REG_SIZE (setreg);

  /* Do not combine registers unless one fits within the other.  */
  if (offset > 0 && usize + offset > ssize)
    return 0;
  if (offset < 0 && usize + offset < ssize)
    return 0;
  /* Do not combine with a smaller already-assigned object
     if that smaller object is already combined with something bigger
     or if that smaller object is a hard reg.
     In the latter case, we would implicitly be using consecutive
     hard regs, and there is no code to keep track of that.
     (This is overcautious; we could check that ssize actually
     requires more hard regs at this spot.)  */
  if (ssize > usize && reg_qty[ureg] >= FIRST_PSEUDO_REGISTER
      && usize < qty_size[reg_qty[ureg]])
    return 0;

  /* Don't do anything with the non-allocatable registers.
     Also, don't suggest a call-clobberable register
     for something that must live across calls.
     Also, don't suggest a hardware register for anything larger than it.  */
  if (ureg < FIRST_PSEUDO_REGISTER)
    {
      if (fixed_regs[ureg])
	return 0;
      if (reg_n_calls_crossed[sreg] != 0 && call_used_regs[ureg])
	return 0;
      if (usize < ssize)
	return 0;
    }

  if (sreg < FIRST_PSEUDO_REGISTER)
    {
      if (fixed_regs[sreg])
	return 0;
      if (reg_n_calls_crossed[ureg] != 0 && call_used_regs[sreg])
	return 0;
      if (ssize < usize)
	return 0;
    }

  /* Don't tie something to itself.  In most cases it would make no
     difference, but it would screw up if the reg being tied to itself
     also dies in this insn.  */

  if (ureg == sreg)
    return 0; 

  /* Don't try to connect two different hardware registers.  */

  if (ureg < FIRST_PSEUDO_REGISTER && sreg < FIRST_PSEUDO_REGISTER)
    return 0;

  /* Don't connect two different machine modes if they have different
     implications as to which registers may be used.  */

  if (!MODES_TIEABLE_P (GET_MODE (usedreg), GET_MODE (setreg)))
    return 0;

  /* Now, if one of UREG and SREG is a hard reg and the other is
     a pseudo, record the hard reg as the qty_phys_sugg for the pseudo
     instead of tying them.  */
  /* Return "failure" so that the lifespan of UREG is terminated here;
     that way the two lifespans will be disjoint and nothing will prevent
     the pseudo reg from being given this hard reg.  */

  if (ureg < FIRST_PSEUDO_REGISTER)
    {
      if (reg_qty[sreg] == -2)
	reg_is_born (setreg, insn_number);
      if (reg_qty[ureg] == -2)
	reg_is_born (usedreg, insn_number);
      if (reg_qty[sreg] >= 0)
	qty_phys_sugg[reg_qty[sreg]] = ureg;
      return 0;
    }
  if (sreg < FIRST_PSEUDO_REGISTER)
    {
      if (reg_qty[sreg] == -2)
	reg_is_born (setreg, insn_number);
      if (reg_qty[ureg] == -2)
	reg_is_born (usedreg, insn_number);
      /* If UREG already has a suggested hard reg, don't override it,
	 since the most likely case is on a risc machine
	 when a pseudo gets a subroutine result and is then returned by
	 this function.  In this case, the outgoing register window
	 is probably a better place to use.  */
      if (reg_qty[ureg] >= 0
	  && (qty_phys_sugg[reg_qty[ureg]] < 0
	      /* If the old suggestion is no good, override it.  */
	      || (qty_n_calls_crossed[reg_qty[ureg]] != 0
		  && call_used_regs[qty_phys_sugg[reg_qty[ureg]]])))
	qty_phys_sugg[reg_qty[ureg]] = sreg;
      return 0;
    }

  /* Do nothing if SREG is a pseudo that already has a quantity
     or if it isn't local to this basic block or dies more than once.  */

  if (reg_qty[sreg] != -2)
    return 0;

  /* Do nothing if UREG isn't local to this block or dies more than once.
     We do this because global_alloc has no idea of tying,
     so there is no use noting those local pseudos that could
     profitably be delayed till global_alloc and get tied to global ones.  */

  if (reg_qty[ureg] == -1)
    return 0;

  /* We don't already know about SREG, so tie it to UREG
     if this is the last use of UREG, provided the classes they want
     are compatible.  */

  if (find_regno_note (insn, REG_DEAD, ureg)
      && (reg_qty[ureg] >= FIRST_PSEUDO_REGISTER
	  ? reg_meets_class_p (sreg, qty_min_class[reg_qty[ureg]])
	  : reg_meets_class_p (sreg, reg_preferred_class (ureg))))
    {
      /* If combining these two registers would leave no satisfactory
	 register available, don't do it.  */
      if (ureg >= FIRST_PSEUDO_REGISTER && sreg >= FIRST_PSEUDO_REGISTER
	  && (qty_preferred_or_nothing[reg_qty[ureg]]
	      || reg_preferred_or_nothing (sreg))
	  && ! (reg_classes_overlap_p
		(reg_preferred_class (ureg), reg_preferred_class (sreg),
		 reg_n_calls_crossed[ureg] || reg_n_calls_crossed[sreg])))
	return 0;
      if (reg_qty[ureg] == -2)
	reg_is_born (usedreg, insn_number);
      sqty = reg_qty[sreg] = reg_qty[ureg];
      if (sqty < FIRST_PSEUDO_REGISTER) abort ();
      /* If SREG's reg class is smaller, set qty_min_class[SQTY].  */
      update_qty_class (sqty, sreg);
      reg_offset[sreg] = reg_offset[ureg] + offset;
      if (sqty >= 0)
	{
	  qty_n_calls_crossed[sqty] += reg_n_calls_crossed[sreg];
	  qty_n_refs[sqty] += reg_n_refs[sreg];
	  if (! reg_preferred_or_nothing (sreg))
	    qty_preferred_or_nothing[sqty] = 0;
	  if (usize < ssize)
	    {
	      register int i;
	      for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
		if (reg_qty[i] == sqty)
		  reg_offset[i] -= offset;
	      qty_size[sqty] = ssize;
	      qty_mode[sqty] = GET_MODE (setreg);
	    }
	}
    }
  else
    return 0;

  return 1;
}

/* Return 1 if the preferred class of REG allows it to be tied
   to a quantity or register whose class is CLASS.
   True if REG's reg class either contains or is contained in CLASS.  */

static int
reg_meets_class_p (reg, class)
     int reg;
     enum reg_class class;
{
  register enum reg_class rclass = reg_preferred_class (reg);
  return (reg_class_subset_p (rclass, class)
	  || reg_class_subset_p (class, rclass));
}

/* Return nonzero if R2's preferred class is the same as or contains
   R1's preferred class.  R1 and R2 are pseudo-register numbers.  */

static int
reg_class_subset_p (c1, c2)
     register enum reg_class c1;
     register enum reg_class c2;
{
  if (c1 == c2) return 1;

  if (c2 == ALL_REGS)
  win:
    return 1;
  GO_IF_HARD_REG_SUBSET (reg_class_contents[(int)c1],
			 reg_class_contents[(int)c2],
			 win);
  return 0;
}

/* Return 1 if the two specified classes have registers in common.
   If CALL_SAVED, then consider only call-saved registers.  */

static int
reg_classes_overlap_p (c1, c2, call_saved)
     register enum reg_class c1;
     register enum reg_class c2;
     int call_saved;
{
  HARD_REG_SET c;
  int i;

  COPY_HARD_REG_SET (c, reg_class_contents[(int) c1]);
  AND_HARD_REG_SET (c, reg_class_contents[(int) c2]);

  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (TEST_HARD_REG_BIT (c, i)
	&& (! call_saved || ! call_used_regs[i]))
      return 1;

  return 0;
}

/* Update the class of QTY assuming that REG is being tied to it.  */

static void
update_qty_class (qty, reg)
     int qty;
     int reg;
{
  enum reg_class rclass = reg_preferred_class (reg);
  if (reg_class_subset_p (rclass, qty_min_class[qty]))
    qty_min_class[qty] = rclass;
}

/* Handle something which alters the value of an rtx REG.
   REG is whatever is set or clobbered.  (CLOBBER_FLAG says which.)
   If it is not really a register, we do nothing.
   The file-global variables `this_insn' and `this_insn_number'
   carry info from `block_alloc'.  */

static void
reg_is_set (reg, setter)
     rtx reg;
     rtx setter;
{
  register int regno;
  int clobber_flag = GET_CODE (setter) == CLOBBER;

  if (reg == 0 || GET_CODE (reg) != REG)
    return;

  regno = REGNO (reg);

  if (regno < FIRST_PSEUDO_REGISTER)
    {
      /* A hard reg is set or clobbered.
	 Mark it as live at the moment immediately following this insn
	 so that no pseudo can live here at that time.
	 For a CLOBBER, mark it as live before this insn,
	 to make sure it is free during the entire insn.  */

      register int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
      register int i;
      for (i = regno; i < lim; i++)
	{
	  SET_HARD_REG_BIT (regs_live_at[this_insn_number], i);
	  if (clobber_flag)
	    SET_HARD_REG_BIT (regs_live_at[this_insn_number - 1], i);
	}

      /* If the hard reg is given a useful value
	 and it does not die in this insn,
	 mark it as live indefinitely afterward.  */
      if (! clobber_flag
	  && ! find_regno_note (this_insn, REG_DEAD, regno))
	reg_is_born (reg, this_insn_number);
    }
  else if (! clobber_flag)
    {
      /* A pseudo-reg is set (not just clobbered).  */

      reg_is_born (reg, this_insn_number);

      /* If a pseudo register dies in the same insn that sets it,
	 say it dies in the following insn instead,
	 because it will have to be live right after this insn.  */
      if (qty_death[reg_qty[regno]] == this_insn_number)
	{
	  /* Calls to post_mark_life and mark_life deleted here.
	     They only know how to handle hard regs.  */
	  qty_death[reg_qty[regno]]++;
	}
    }
  else if (reg_qty[regno] >= 0 && qty_death[reg_qty[regno]] == this_insn_number
	   && qty_birth[reg_qty[regno]] == this_insn_number)
    {
      /* A psuedo-reg is clobbered by this insn and was born and dies here.
	 This is a temporary required for this insn and so will
	 conflict with any other live registers at this point.  We must
	 assume that this register is used before all the inputs of the
	 insn are dead.  So this register must not conflict with any of them.
	 Mark it as born at the previous insn.  */
      qty_birth[reg_qty[regno]]--;
      /* It should also conflict with this insn's outputs.  */
      qty_death[reg_qty[regno]]++;
    }
}

/* Handle beginning of the life of register REG.
   INSN_NUMBER is the insn at which this is happening.  */

static void
reg_is_born (reg, insn_number)
     rtx reg;
     int insn_number;
{
  register int regno = REGNO (reg);
     
  if (regno < FIRST_PSEUDO_REGISTER)
    mark_life (regno, GET_MODE (reg), 1);
  else if (reg_qty[regno] == -2)
    alloc_qty (regno, GET_MODE (reg), PSEUDO_REGNO_SIZE (regno), insn_number);
}

/* Record the death in insn DEATH_INSN_NUMBER for the register REG.  */

static void
wipe_dead_reg (reg, this_insn_number, death_insn_number)
     register rtx reg;
     int this_insn_number;
     int death_insn_number;
{
  register int regno = REGNO (reg);

  if (regno < FIRST_PSEUDO_REGISTER)
    {
      mark_life (regno, GET_MODE (reg), 0);
      if (this_insn_number != death_insn_number)
	abort ();
#if 0				/* Should never get here */
	post_mark_life (regno, GET_MODE (reg), 1,
			this_insn_number, death_insn_number);
#endif
    }
  else
    {
      /* If a pseudo reg is referred to but was never set,
	 we will find here that its qty is -2.
	 Since these regs do not conflict with anything,
	 mark them as born and dead in the same place.  */
      if (reg_qty[regno] == -2)
	{
	  alloc_qty (regno, GET_MODE (reg), REG_SIZE (reg), this_insn_number);
	  REG_NOTES (this_insn) = gen_rtx (EXPR_LIST, REG_UNSET, reg,
					   REG_NOTES (this_insn));
	}

      if (reg_qty[regno] >= 0)
	qty_death[reg_qty[regno]] = death_insn_number;
    }
}

/* Find a block of SIZE words of hard regs in reg_class CLASS
   that can hold something of machine-mode MODE
     (but actually we test only the first of the block for holding MODE)
   and still free between insn BORN_INSN and insn DEAD_INSN,
   and return the number of the first of them.
   Return -1 if such a block cannot be found. 
   If QTY crosses calls, insist on a register preserved by calls,
   unless ACCEPT_CALL_CLOBBERED is nonzero.  */

static int
find_free_reg (class, mode, qty, accept_call_clobbered, born_insn, dead_insn)
     enum reg_class class;
     enum machine_mode mode;
     int accept_call_clobbered;
     int qty;
     int born_insn, dead_insn;
{
  register int i, ins;
#ifdef HARD_REG_SET
  register		/* Declare it register if it's a scalar.  */
#endif
    HARD_REG_SET used;

  if (accept_call_clobbered)
    COPY_HARD_REG_SET (used, call_fixed_reg_set);
  else if (qty_n_calls_crossed[qty] == 0)
    COPY_HARD_REG_SET (used, fixed_reg_set);
  else
    COPY_HARD_REG_SET (used, call_used_reg_set);

  for (ins = born_insn; ins < dead_insn; ins++)
    IOR_HARD_REG_SET (used, regs_live_at[ins]);

  IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
  /* Don't use the frame pointer reg in local-alloc even if
     we may omit the frame pointer, because if we do that and then we
     need a frame pointer, reload won't know how to move the pseudo
     to another hard reg.  It can move only regs made by global-alloc.  */
  SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);

  /* If quantity QTY has a suggested physical register,
     try that one first.  */

  if (qty_phys_sugg[qty] >= 0)
    {
      i = qty_phys_sugg[qty];
      if (! TEST_HARD_REG_BIT (used, i)
	  && HARD_REGNO_MODE_OK (i, mode))
	{
	  register int j;
	  register int size1 = HARD_REGNO_NREGS (i, mode);
	  for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, i + j); j++);
	  if (j == size1)
	    {
	      post_mark_life (i, mode, 1, born_insn, dead_insn);
	      return i;
	    }
	}
    }

  /* If that doesn't find one, test each hard reg.  */

  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    {
#ifdef REG_ALLOC_ORDER
      int regno = reg_alloc_order[i];
#else
      int regno = i;
#endif
      if (! TEST_HARD_REG_BIT (used, regno)
	  && HARD_REGNO_MODE_OK (regno, mode))
	{
	  register int j;
	  register int size1 = HARD_REGNO_NREGS (regno, mode);
	  for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
	  if (j == size1)
	    {
	      post_mark_life (regno, mode, 1, born_insn, dead_insn);
	      return regno;
	    }
#ifndef REG_ALLOC_ORDER
	  i += j;		/* Skip starting points we know will lose */
#endif
	}
    }

  /* If it would be profitable to allocate a call-clobbered register
     and save and restore it around calls, do that.  */

  if (! accept_call_clobbered
      && flag_caller_saves
      && qty_n_calls_crossed[qty] != 0
      && CALLER_SAVE_PROFITABLE (qty_n_refs[qty], qty_n_calls_crossed[qty]))
    {
      i = find_free_reg (class, mode, qty, 1, born_insn, dead_insn);
      if (i >= 0)
	caller_save_needed = 1;
      return i;
    }
  return -1;
}

static void
mark_life (regno, mode, life)
     register int regno;
     enum machine_mode mode;
     int life;
{
  register int j = HARD_REGNO_NREGS (regno, mode);
  if (life)
    while (--j >= 0)
      SET_HARD_REG_BIT (regs_live, regno + j);
  else
    while (--j >= 0)
      CLEAR_HARD_REG_BIT (regs_live, regno + j);
}

static void
post_mark_life (regno, mode, life, birth, death)
     register int regno, life, birth;
     enum machine_mode mode;
     int death;
{
  register int j = HARD_REGNO_NREGS (regno, mode);
#ifdef HARD_REG_SET
  register		/* Declare it register if it's a scalar.  */
#endif
    HARD_REG_SET this_reg;

  CLEAR_HARD_REG_SET (this_reg);
  while (--j >= 0)
    SET_HARD_REG_BIT (this_reg, regno + j);

  /* If a reg is born and dies in one insn,
     consider it live after that insn.  */

  if (birth == death)
    death++;

  if (life)
    while (birth < death)
      {
	IOR_HARD_REG_SET (regs_live_at[birth], this_reg);
	birth++;
      }
  else
    while (birth < death)
      {
	AND_COMPL_HARD_REG_SET (regs_live_at[birth], this_reg);
	birth++;
      }
}

void
dump_local_alloc (file)
     FILE *file;
{
  register int i;
  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
    if (reg_renumber[i] != -1)
      fprintf (file, ";; Register %d in %d.\n", i, reg_renumber[i]);
}