* Removed all Id tags.
[cacao.git] / src / vm / jit / optimizing / lsra.c
1 /* src/vm/jit/optimizing/lsra.inc - linear scan register allocator
2
3    Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Ullrich
28
29
30 */
31 #include "config.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "arch.h"
37 #include "md-abi.h"
38
39 #include "mm/memory.h"
40
41 #include "toolbox/bitvector.h"
42
43 #include "vmcore/statistics.h"
44 #include "vmcore/options.h"
45 #include "vmcore/method.h"
46
47 #include "vm/jit/abi.h"
48 #include "vm/jit/reg.h"
49 #include "vm/jit/jit.h"
50
51
52 #include "vm/jit/optimizing/graph.h"
53 #include "vm/jit/optimizing/lifetimes.h"
54 #include "vm/jit/optimizing/ssa.h"
55
56 #include "vm/jit/optimizing/lsra.h"
57
58 #ifdef LSRA_TESTLT
59 # include "vm/resolve.h"
60 #include "vm/builtin.h"
61 #endif
62
63
64 #include "toolbox/logging.h"
65
66 extern const char *string_java_lang_InternalError;
67 /* function prototypes */
68 void lsra_init(jitdata *);
69 graphdata *lsra_setup(jitdata *);
70 void lsra_main(jitdata *);
71 #ifdef LSRA_DEBUG_VERBOSE
72 void lsra_dump_stack(stackptr );
73 void print_lifetimes(jitdata *, int *, int);
74 void print_all_lifetimes(jitdata *);
75 #endif
76 void lsra_reg_setup(jitdata *,struct lsra_register *,
77                                         struct lsra_register *);
78
79 void lsra_calc_lifetime_length(jitdata *);
80
81 void _lsra_main( jitdata *, int *, int, struct lsra_register *,
82                                  int *);
83 void lsra_expire_old_intervalls(jitdata *, struct lifetime *,
84                                                                 struct lsra_register *);
85 void spill_at_intervall(jitdata *, struct lifetime *);
86 void lsra_add_active(struct lifetime *, struct lifetime **, int *);
87 void _lsra_expire_old_intervalls(jitdata *, struct lifetime *,
88                                                                  struct lsra_register *,
89                                                                  struct lifetime **, int *);
90 void _spill_at_intervall(struct lifetime *, struct lifetime **, int *);
91 void lsra_alloc(jitdata *, int *, int,
92                                 int *);
93 int lsra_getmem(struct lifetime *, struct freemem *, int *);
94 struct freemem *lsra_getnewmem(int *);
95
96 void lsra(jitdata *jd) {
97         methodinfo *m;
98         codegendata *cd;
99         registerdata *rd;
100         lsradata *ls;
101         graphdata *gd;
102 #if defined(ENABLE_STATISTICS)
103         int locals_start;
104         int i,j;
105 #endif  
106 #if defined(LSRA_DEBUG_CHECK)
107 #if 0
108         int b_index;
109         stackptr in,out;
110         int      ind, outd;
111 #endif
112 #endif
113
114         m = jd->m;
115         cd = jd->cd;
116         rd = jd->rd;
117         ls = jd->ls;
118
119 #if defined(LSRA_DEBUG_CHECK)
120 #if 0
121         b_index = 0;
122         while (b_index < jd->basicblockcount ) {
123
124                 if (jd->basicblocks[b_index].flags >= BBREACHED) {
125
126                         in=m->basicblocks[b_index].instack;
127                         ind=m->basicblocks[b_index].indepth;
128                         for (;ind != 0;in=in->prev, ind--) {
129                                 /* ARGVAR or LOCALVAR in instack is ok*/
130 #if defined(LSRA_DEBUG_VERBOSE)
131                                 if (compileverbose) {
132                                         if (in->varkind == ARGVAR) printf("ARGVAR in instack: \n");
133                                         if (in->varkind == LOCALVAR) 
134                                                 printf("LOCALVAR in instack\n");
135                                 }
136 #endif
137                         }
138                         out=m->basicblocks[b_index].outstack;
139                         outd=m->basicblocks[b_index].outdepth;
140                         for (;outd != 0;out=out->prev, outd--) {
141                                 if (out->varkind == ARGVAR)
142                                         { log_text("ARGVAR in outstack\n"); assert(0); }
143                                 if (out->varkind == LOCALVAR)
144                                         { log_text("LOCALVAR in outstack\n"); assert(0); }
145                         }
146                 }
147                         b_index++;
148         }
149 #endif
150 #endif
151
152 #if defined(LSRA_DEBUG_CHECK) || defined(LSRA_DEBUG_VERBOSE)
153 #if defined(LSRA_DEBUG_VERBOSE)
154         if (compileverbose) {
155                 printf("%s %s ",m->class->name->text, m->name->text);
156                 if (jd->isleafmethod)
157                         printf("**Leafmethod**");
158                 printf("\n");
159         }
160 #endif
161         if (strcmp(m->class->name->text,"java/lang/String")==0)
162                 if (strcmp(m->name->text,"toLowerCase")==0)
163 #if defined(LSRA_DEBUG_VERBOSE)
164                         if (compileverbose)
165                                 printf("12-------------------12\n");
166 #else
167                 { int dummy=1; dummy++; }
168 #endif
169 #endif
170
171     lsra_init(jd);
172         gd = lsra_setup(jd);
173
174 #if defined(ENABLE_STATISTICS)
175         /* find conflicts between locals for statistics */
176         if (opt_stat) {
177                 /* local Variable Lifetimes are at the end of the lifetime array and */
178                 /* have v_index >= 0 */
179                 for (locals_start = ls->lifetimecount-1; (locals_start >=0) && 
180                         (ls->lifetime[ls->lt_used[locals_start]].v_index >= 0);
181                          locals_start--);
182                 for (i=locals_start + 1; i < ls->lifetimecount; i++)
183                         for (j=i+1; j < ls->lifetimecount; j++)
184                                 if ( !((ls->lifetime[ls->lt_used[i]].i_end 
185                                            < ls->lifetime[ls->lt_used[j]].i_start) 
186                                         || (ls->lifetime[ls->lt_used[j]].i_end < 
187                                            ls->lifetime[ls->lt_used[i]].i_start)) )
188                                         count_locals_conflicts += 2;
189          }
190 #endif
191         /* Run LSRA */
192         lsra_main(jd);
193 #ifdef LSRA_TESTLT
194         test_lifetimes( jd, gd );
195 #endif
196         fflush(stdout);
197 }
198
199
200 void lsra_init(jitdata *jd) 
201 {
202         lsradata *ls = jd->ls;
203
204         /* Init LSRA Data Structures */
205         /* allocate lifetimes for all Basicblocks */
206
207         ls->v_index = -1;
208 }
209
210 graphdata *lsra_setup(jitdata *jd)
211 {
212         methodinfo *m;
213         codegendata *cd;
214         registerdata *rd;
215         lsradata *ls;
216         graphdata *gd;
217
218 #if defined(ENABLE_LOOPS)
219         /* Loop optimization "destroys" the basicblock array */
220         /* TODO: work with the basicblock list               */
221         if (opt_loops) {
222                 log_text("lsra not possible with loop optimization\n");
223                 exit(1);
224         }
225 #endif
226
227         m = jd->m;
228         cd = jd->cd;
229         rd = jd->rd;
230         ls = jd->ls;
231
232         ssa_init(jd);
233
234         /* Setup LSRA Data structures */
235
236         /* Generate the Control Flow Graph */
237         /* Add one for a Basic Block 0 to be inserted, so lateron */
238         /* with SSA Parameter initialization is handled right */
239         gd = graph_init(jd->basicblockcount + 1);
240         graph_make_cfg(jd, gd);
241         ssa(jd, gd);
242         lt_lifeness_analysis(jd, gd);
243
244 #ifdef LSRA_DEBUG_VERBOSE
245         if (compileverbose) {
246                 printf("Lifetimes after LifenessAnalyse: \n");
247                 print_all_lifetimes(jd);
248         }
249 #endif
250
251         lsra_calc_lifetime_length(jd);
252
253 #ifdef LSRA_DEBUG_VERBOSE
254         if (compileverbose) {
255                 printf("Basicblockcount: %4i\n",ls->basicblockcount);
256         }
257 #endif
258         return gd;
259 }
260
261 void lsra_reg_setup(jitdata *jd,
262                                         struct lsra_register *int_reg,
263                                         struct lsra_register *flt_reg ) {
264         int i, j, iarg, farg;
265         int int_sav_top;
266         int flt_sav_top;
267         bool *fltarg_used, *intarg_used;
268         methoddesc *md;
269         methodinfo *m;
270         registerdata *rd;
271
272         m = jd->m;
273         rd = jd->rd;
274         md = m->parseddesc;
275
276         int_reg->nregdesc = nregdescint;
277         flt_reg->nregdesc = nregdescfloat;
278         if (jd->isleafmethod) { 
279                 /* Temp and Argumentregister can be used as saved registers */
280
281                 int_reg->sav_top = INT_ARG_CNT + INT_TMP_CNT + INT_SAV_CNT;
282                 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
283                 int_reg->tmp_reg = NULL;
284                 int_reg->tmp_top = -1;
285                 flt_reg->sav_top = FLT_ARG_CNT + FLT_TMP_CNT + FLT_SAV_CNT;
286                 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
287                 flt_reg->tmp_reg = NULL;
288                 flt_reg->tmp_top = -1;
289
290                 /* additionaly precolour registers for Local Variables acting as */
291                 /* Parameters */
292
293                 farg = FLT_ARG_CNT;
294                 iarg = INT_ARG_CNT;
295
296                 intarg_used = DMNEW(bool, INT_ARG_CNT);
297                 for (i=0; i < INT_ARG_CNT; i++)
298                         intarg_used[i]=false;
299
300                 fltarg_used = DMNEW(bool, FLT_ARG_CNT);
301                 for (i=0; i < FLT_ARG_CNT; i++)
302                         fltarg_used[i]=false;
303
304                 int_sav_top=int_reg->sav_top;
305                 flt_sav_top=flt_reg->sav_top;
306
307                 for (i=0; (i < md->paramcount); i++) {
308                         if (!md->params[i].inmemory) {
309                                 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
310 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
311                                         if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {
312                                                 int_reg->sav_reg[--int_sav_top] = 
313                                                         GET_HIGH_REG(md->params[i].regoff);
314                                                 intarg_used[GET_HIGH_REG(md->params[i].regoff)]=true;
315                                                 /*used -> don't copy later on */
316                                                 int_reg->sav_reg[--int_sav_top] = 
317                                                         GET_LOW_REG(md->params[i].regoff);
318                                                 intarg_used[GET_LOW_REG(md->params[i].regoff)]=true;
319                                                 /*used -> don't copy later on */
320                                         } else
321 #endif
322                                         { /* !IS_2_WORD_TYPE(md->paramtypes[i].type */
323                                                 int_reg->sav_reg[--int_sav_top] = 
324                                                         md->params[i].regoff;
325                                                 intarg_used[md->params[i].regoff]=true;
326                                                 /*used -> don't copy later on */
327                                         }
328                                 }
329 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
330                                 /* do not precolour float arguments if they are passed in     */
331                                 /* integer registers. But these integer argument registers    */
332                                 /* still be used in the method! */
333                                 else { /* IS_FLT_DBL_TYPE(md->paramtypes[i].type */
334                                                 flt_reg->sav_reg[--flt_sav_top] = 
335                                                         md->params[i].regoff;
336                                                 fltarg_used[md->params[i].regoff]=true;
337                                 }
338 #endif
339                                         
340                         }
341                 }
342
343                 /* copy rest of argument registers to flt_reg->sav_reg and */
344                 /* int_reg->sav_reg; */
345                 for (i=0; i < INT_ARG_CNT; i++)
346                         if (!intarg_used[i])
347                                 int_reg->sav_reg[--int_sav_top]=i;
348                 for (i=0; i < FLT_ARG_CNT; i++)
349                         if (!fltarg_used[i])
350                                 flt_reg->sav_reg[--flt_sav_top]=i;
351
352                 /* copy temp registers to flt_reg->sav_reg and int_reg->sav_reg */
353                 for (i=0; i < INT_TMP_CNT; i++)
354                         int_reg->sav_reg[--int_sav_top]=rd->tmpintregs[i];
355                 for (i=0; i < FLT_TMP_CNT; i++)
356                         flt_reg->sav_reg[--flt_sav_top]=rd->tmpfltregs[i];
357
358         } else {
359                 /* non leaf method -> use Argument Registers [arg[int|flt]reguse */
360                 /* ... [INT|FLT]_ARG_CNT[ as temp reg */
361                 /* divide temp and saved registers */
362
363                 int argintreguse, argfltreguse;
364
365                 /* with Locals as non SAVEDVAR, the used arg[int|flt] as in params */
366                 /* of the method itself have to be regarded, or mismatch before    */
367                 /* block 0 with parameter copy could happen! */
368
369                 argintreguse = max(rd->argintreguse, md->argintreguse);
370                 argfltreguse = max(rd->argfltreguse, md->argfltreguse);
371
372                 int_sav_top = int_reg->sav_top = INT_SAV_CNT;
373                 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
374                 int_reg->tmp_top = INT_TMP_CNT +
375                         max(0, (INT_ARG_CNT - argintreguse));
376                 int_reg->tmp_reg = DMNEW(int, int_reg->tmp_top);
377
378                 flt_sav_top =flt_reg->sav_top = FLT_SAV_CNT;
379                 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
380                 flt_reg->tmp_top = FLT_TMP_CNT +
381                         max(0 , (FLT_ARG_CNT - argfltreguse));
382                 flt_reg->tmp_reg = DMNEW(int, flt_reg->tmp_top);
383
384                 /* copy temp and unused argument registers to flt_reg->tmp_reg and */
385                 /* int_reg->tmp_reg */
386
387                 for (i=0; i < INT_TMP_CNT; i++)
388                         int_reg->tmp_reg[i]=rd->tmpintregs[i];
389
390                 /* quick and dirty patch for the drop of rd->argxxxreg[] - but will */
391                 /* work anyhow on i386, !! has to be made "real" for other archs    */
392
393                 for (j = argintreguse; j < INT_ARG_CNT; j++, i++)
394                         int_reg->tmp_reg[i]=j;
395                 for (i=0; i < FLT_TMP_CNT; i++)
396                         flt_reg->tmp_reg[i]=rd->tmpfltregs[i];
397
398                 /* quick and dirty patch for the drop of rd->argxxxreg[] - but will */
399                 /* work anyhow on i386, !! has to be made "real" for other archs    */
400
401                 for (j = argfltreguse; j < FLT_ARG_CNT; j++, i++)
402                         flt_reg->tmp_reg[i]=j;
403         }
404
405         /* now copy saved registers to flt_reg->sav_reg and int_reg->sav_reg */
406         for (i = INT_SAV_CNT-1; i >= 0; i--)
407                 int_reg->sav_reg[--int_sav_top]=rd->savintregs[i];
408         for (i = FLT_SAV_CNT-1; i >= 0; i--)
409                 flt_reg->sav_reg[--flt_sav_top]=rd->savfltregs[i];
410         /* done */
411 }
412
413 void lsra_insertion( struct lsradata *ls, int *a, int lo, int hi) {
414         int i,j,t,tmp;
415
416         for (i=lo+1; i<=hi; i++) {
417                 j=i;
418                 t=ls->lifetime[a[j]].i_start;
419                 tmp = a[j];
420                 while ((j>lo) && (ls->lifetime[a[j-1]].i_start > t)) {
421                         a[j]=a[j-1];
422                         j--;
423                 }
424                 a[j]=tmp;
425         }
426 }
427
428 void lsra_qsort( struct lsradata *ls, int *a, int lo, int hi) {
429         int i,j,x,tmp;
430         if (lo < hi) {
431                 if ( (lo+5)<hi) {
432                         i = lo;
433                         j = hi;
434                         x = ls->lifetime[a[(lo+hi)/2]].i_start;
435
436                         while (i <= j) {
437                                 while (ls->lifetime[a[i]].i_start < x) i++;
438                                 while (ls->lifetime[a[j]].i_start > x) j--;
439                                 if (i <= j) {
440                                         /* exchange a[i], a[j] */
441                                         tmp = a[i];
442                                         a[i] = a[j];
443                                         a[j] = tmp;
444                         
445                                         i++;
446                                         j--;
447                                 }
448                         }
449
450                         if (lo < j) lsra_qsort( ls, a, lo, j);
451                         if (i < hi) lsra_qsort( ls, a, i, hi);
452                 } else
453                         lsra_insertion(ls, a, lo, hi);
454         }
455 }
456
457 void lsra_param_sort(struct lsradata *ls, int *lifetime, int lifetime_count) {
458
459         int param_count;
460         int i,j,tmp;
461
462         /* count number of parameters ( .i_start == -1) */
463         for (param_count=0; (param_count < lifetime_count) &&
464 /*               (ls->lifetime[lifetime[param_count]].i_start == -1); param_count++); */
465                  (ls->lifetime[lifetime[param_count]].i_start == 0); param_count++);
466
467         if (param_count > 0) {
468                 /* now sort the parameters by v_index */
469                 for (i=0; i < param_count -1; i++)
470                         for (j=i+1; j < param_count; j++)
471                                 if ( ls->lifetime[lifetime[i]].v_index >
472                                          ls->lifetime[lifetime[j]].v_index) {
473                                         /* swap */
474                                         tmp = lifetime[i];
475                                         lifetime[i]=lifetime[j];
476                                         lifetime[j]=tmp;
477                                 }
478         }                       
479 }
480
481 void lsra_main(jitdata *jd)
482 {
483 #ifdef LSRA_DEBUG_VERBOSE
484         int i;
485 #endif
486         int lsra_mem_use;
487         int lsra_reg_use;
488         struct lsra_register flt_reg, int_reg;
489         methodinfo *m;
490         registerdata *rd;
491         lsradata *ls;
492
493         ls = jd->ls;
494         m = jd->m;
495         rd = jd->rd;
496
497 /* sort lifetimes by increasing start */
498         lsra_qsort( ls, ls->lt_mem, 0, ls->lt_mem_count - 1);
499         lsra_qsort( ls, ls->lt_int, 0, ls->lt_int_count - 1);
500         lsra_qsort( ls, ls->lt_flt, 0, ls->lt_flt_count - 1);
501 /* sort local vars used as parameter */
502         lsra_param_sort( ls, ls->lt_int, ls->lt_int_count);
503         lsra_param_sort( ls, ls->lt_flt, ls->lt_flt_count);
504         lsra_reg_setup(jd, &int_reg, &flt_reg);
505
506 #ifdef LSRA_DEBUG_VERBOSE
507         if (compileverbose) {
508                 printf("INTSAV REG: ");
509                 for (i=0; i<int_reg.sav_top; i++)
510                         printf("%2i ",int_reg.sav_reg[i]);
511                 printf("\nINTTMP REG: ");
512                 for (i=0; i<int_reg.tmp_top; i++)
513                         printf("%2i ",int_reg.tmp_reg[i]);
514                 printf("\nFLTSAV REG: ");
515                 for (i=0; i<flt_reg.sav_top; i++)
516                         printf("%2i ",flt_reg.sav_reg[i]);
517                 printf("\nFLTTMP REG: ");
518                 for (i=0; i<flt_reg.tmp_top; i++)
519                         printf("%2i ",flt_reg.tmp_reg[i]);
520                 printf("\n");
521         }
522 #endif
523
524         ls->active_tmp = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
525         ls->active_sav = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
526
527         lsra_reg_use=INT_SAV_CNT; /* init to no saved reg used... */
528         _lsra_main(jd, ls->lt_int, ls->lt_int_count, &int_reg,
529                                    &lsra_reg_use);
530         if (lsra_reg_use > INT_SAV_CNT) lsra_reg_use=INT_SAV_CNT;
531         rd->savintreguse = lsra_reg_use;
532
533         lsra_reg_use = FLT_SAV_CNT; /* no saved reg used... */
534
535         _lsra_main(jd, ls->lt_flt, ls->lt_flt_count, &flt_reg, &lsra_reg_use);
536         if (lsra_reg_use > FLT_SAV_CNT) lsra_reg_use=FLT_SAV_CNT;
537
538         rd->savfltreguse=lsra_reg_use;
539
540         /* rd->memuse was already set in stack.c to allocate stack space for */
541         /* passing arguments to called methods */
542 #if defined(__I386__)
543         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
544                 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
545                 if (rd->memuse < 1)
546                         rd->memuse = 1;
547         }
548 #endif
549
550         lsra_mem_use = rd->memuse; /* Init with memuse from stack.c */
551
552         lsra_alloc(jd, ls->lt_mem, ls->lt_mem_count, &lsra_mem_use);
553         lsra_alloc(jd, ls->lt_int, ls->lt_int_count, &lsra_mem_use);
554         lsra_alloc(jd, ls->lt_flt, ls->lt_flt_count, &lsra_mem_use);
555
556         rd->memuse=lsra_mem_use;
557
558 #ifdef LSRA_DEBUG_VERBOSE
559         if (compileverbose) {
560                 printf("Int RA complete \n");
561                 printf("Lifetimes after splitting int: \n");
562                 print_lifetimes(jd, ls->lt_int, ls->lt_int_count);
563                 
564                 printf("Flt RA complete \n");
565                 printf("Lifetimes after splitting flt:\n");
566                 print_lifetimes(jd, ls->lt_flt, ls->lt_flt_count);
567
568                 printf("Rest RA complete \n");
569                 printf("Lifetimes after leftt:\n");
570                 print_lifetimes(jd, ls->lt_mem, ls->lt_mem_count);
571
572                 printf("jd->varcount: %i jd->vartop %i\n", jd->varcount, jd->vartop);
573         }
574 #endif
575 }
576
577 void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
578 {
579         int flags,regoff;
580         struct lifetime *lt;
581         struct freemem *fmem;
582         int lt_index;
583 #ifdef HAS_4BYTE_STACKSLOT
584         struct freemem *fmem_2;
585 #endif
586         methodinfo *m;
587         registerdata *rd;
588         lsradata *ls;
589
590         m = jd->m;
591         rd = jd->rd;
592         ls = jd->ls;
593
594         fmem=DNEW(struct freemem);
595         fmem->off=-1;
596         fmem->next=NULL;
597 #ifdef HAS_4BYTE_STACKSLOT
598         fmem_2=DNEW(struct freemem);
599         fmem_2->off=-1;
600         fmem_2->next=NULL;
601 #endif
602
603         for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
604                 lt = ls->lifetime + lifet[lt_index];
605 #ifdef LSRA_MEMORY
606                 lt->reg=-1;
607 #endif
608                 if (lt->regoff == -1) {
609                         flags = INMEMORY;
610 #ifdef HAS_4BYTE_STACKSLOT
611                         if (IS_2_WORD_TYPE(lt->type))
612                                 regoff = lsra_getmem(lt, fmem_2, mem_use);
613                         else
614 #endif
615                         regoff = lsra_getmem(lt, fmem, mem_use);
616                 } else {
617                         flags = lt->savedvar;
618                         regoff = lt->regoff;
619                 }
620
621                 lt->regoff = regoff;
622                 VAR(lt->v_index)->vv.regoff = regoff;
623                 VAR(lt->v_index)->flags  = flags;
624         }
625 }
626
627 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
628 {
629         struct freemem *fm, *p;
630
631         /* no memmory allocated till now, or all other are still live */
632         if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
633 /*      if (1) { */
634 #ifdef HAS_4BYTE_STACKSLOT
635                 if (IS_2_WORD_TYPE(lt->type))
636                         if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
637                                 (*mem_use)++;
638                 fm=lsra_getnewmem(mem_use);
639                 if (IS_2_WORD_TYPE(lt->type))
640                         /* allocate a second following Slot for 2 Word Types */
641                         (*mem_use)++;
642 #else
643                 fm=lsra_getnewmem(mem_use);
644 #endif
645         } else {
646                 /* Speicherstelle frei */
647                 fm=fmem->next;
648                 fmem->next=fm->next;
649                 fm->next=NULL;
650         }
651         fm->end=lt->i_end;
652         for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
653         fm->next=p->next;
654         p->next=fm;
655         return fm->off;
656 }
657
658 struct freemem *lsra_getnewmem(int *mem_use)
659 {
660         struct freemem *fm;
661
662         fm=DNEW(struct freemem);
663         fm->next=NULL;
664         fm->off=*mem_use;
665         (*mem_use)++;
666         return fm;
667 }
668
669 void _lsra_main( jitdata *jd, int *lifet, int lifetimecount,
670                                  struct lsra_register *reg, int *reg_use)
671 {
672         struct lifetime *lt;
673         int lt_index;
674         int reg_index;
675         int regsneeded;
676         bool temp; /* reg from temp registers (true) or saved registers (false) */
677         methodinfo *m;
678         lsradata *ls;
679
680         m = jd->m;
681         ls = jd->ls;
682         
683 #if !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
684         regsneeded = 0;
685 #endif
686         if ((reg->tmp_top+reg->sav_top) == 0) {
687
688                 /* no registers available */
689                 for (lt_index = 0; lt_index < lifetimecount; lt_index++)
690                         ls->lifetime[lifet[lt_index]].regoff = -1;
691                 return;
692         }
693
694         ls->active_tmp_top = 0;
695         ls->active_sav_top = 0;
696
697         for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
698                 lt = &(ls->lifetime[lifet[lt_index]]);
699
700 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
701         regsneeded = (lt->type == TYPE_LNG)?1:0;
702 #endif
703
704                 lsra_expire_old_intervalls(jd, lt, reg);
705                 reg_index = -1;
706                 temp = false;
707 #ifdef LSRA_SAVEDVAR
708                 lt->savedvar = SAVEDVAR;
709 #endif
710                 if (lt->savedvar || jd->isleafmethod) {
711                         /* use Saved Reg (in case of leafmethod all regs are saved regs) */
712                         if (reg->sav_top > regsneeded) {
713 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
714                                 if (regsneeded)
715                                         reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
716                                                                                   reg->sav_reg[--reg->sav_top]);
717                                 else
718 #endif
719
720                                         reg_index = reg->sav_reg[--reg->sav_top];
721                         }
722                 } else { /* use Temp Reg or if none is free a Saved Reg */
723                         if (reg->tmp_top > regsneeded) {
724                                 temp = true;
725 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
726                         if (regsneeded)
727                                 reg_index = PACK_REGS(reg->tmp_reg[--reg->tmp_top],
728                                                                           reg->tmp_reg[--reg->tmp_top]);
729                         else
730 #endif
731                                 reg_index = reg->tmp_reg[--reg->tmp_top];
732                         }
733                         else
734                                 if (reg->sav_top > regsneeded) {
735
736 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
737                                 if (regsneeded)
738                                         reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
739                                                                                   reg->sav_reg[--reg->sav_top]);
740                                 else
741 #endif
742                                         reg_index = reg->sav_reg[--reg->sav_top];
743                                 }
744                 }
745                 if (reg_index == -1) /* no reg is available anymore... -> spill */
746                         spill_at_intervall(jd, lt);
747                 else {
748                         lt->regoff = reg_index;
749                         if (temp)
750                                 lsra_add_active(lt, ls->active_tmp, &(ls->active_tmp_top));
751                         else {
752                                 if (reg->sav_top<*reg_use) *reg_use=reg->sav_top;
753                                 lsra_add_active(lt, ls->active_sav, &(ls->active_sav_top));
754                         }
755                 }
756         }
757 }
758
759 void lsra_add_active(struct lifetime *lt, struct lifetime **active,
760                                          int *active_top)
761 {
762         int i, j;
763
764         for(i = 0; (i < *active_top) && (active[i]->i_end < lt->i_end); i++);
765
766         for(j = *active_top; j > i; j--) active[j] = active[j-1];
767
768         (*active_top)++;
769
770         active[i] = lt;
771
772 }
773
774 void lsra_expire_old_intervalls(jitdata *jd,
775                                                                 struct lifetime *lt, struct lsra_register *reg)
776 {
777         _lsra_expire_old_intervalls(jd, lt, reg, jd->ls->active_tmp,
778                                                                 &(jd->ls->active_tmp_top));
779         _lsra_expire_old_intervalls(jd, lt, reg, jd->ls->active_sav,
780                                                                 &(jd->ls->active_sav_top));
781 }
782
783 void _lsra_expire_old_intervalls(jitdata *jd, struct lifetime *lt,
784                                                                  struct lsra_register *reg,
785                                                                  struct lifetime **active, int *active_top)
786 {
787         int i, j, k;
788
789         for(i = 0; i < *active_top; i++) {
790                 if (active[i]->i_end > lt->i_start) break;
791
792                 /* make active[i]->reg available again */
793                 if (jd->isleafmethod) { 
794                         /* leafmethod -> don't care about type -> put all again into */
795                         /* reg->sav_reg */
796 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
797                         if (active[i]->type == TYPE_LNG) {
798                                 reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
799                                 reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
800                         } else
801 #endif
802                                 reg->sav_reg[reg->sav_top++] = active[i]->regoff;
803                 } else { 
804                         /* no leafmethod -> distinguish between temp and saved register */
805 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
806                         if (active[i]->type == TYPE_LNG) {
807                                 /* no temp and saved regs are packed together, so looking at */
808                                 /* LOW_REG is sufficient */
809                                 if ( reg->nregdesc[ GET_LOW_REG(active[i]->reg)] == REG_SAV) {
810                                         reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
811                                         reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
812                                 } else {
813                                         reg->tmp_reg[reg->tmp_top++] = GET_LOW_REG(active[i]->reg);
814                                         reg->tmp_reg[reg->tmp_top++] = GET_HIGH_REG(active[i]->reg);
815                                 }
816                         } else
817 #endif
818                         if ( reg->nregdesc[active[i]->regoff] == REG_SAV) {
819                                         reg->sav_reg[reg->sav_top++] = active[i]->regoff;
820                         } else {
821                                         reg->tmp_reg[reg->tmp_top++] = active[i]->regoff;
822                         }
823                 }
824         }
825         
826         /* active[0..i[ is to be removed */
827         /* -> move [i..*active_top[ to [0..*active_top-i[ */
828         for(k = 0, j = i; (j < *active_top); k++,j++)
829                 active[k] = active[j];
830
831         (*active_top) -= i;
832
833 }
834
835 void spill_at_intervall(jitdata *jd, struct lifetime *lt )
836 {
837         lsradata *ls;
838
839         ls = jd->ls;
840
841         if (lt->savedvar || jd->isleafmethod) {
842                 _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
843         } else {
844                 _spill_at_intervall(lt, ls->active_tmp, &(ls->active_tmp_top));
845                 if (lt->regoff == -1) { /* kein tmp mehr frei gewesen */
846                         _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
847                 }
848         }
849 }
850
851 void _spill_at_intervall(struct lifetime *lt, struct lifetime **active,
852                                                  int *active_top)
853 {
854         int i, j;
855 #if 0
856 #ifdef USAGE_COUNT
857         int u_min, i_min;
858 #endif /* USAGE_COUNT */
859 #endif /* 0 */
860
861         if (*active_top == 0) {
862                 lt->regoff = -1;
863                 return;
864         }
865         
866         i = *active_top - 1;
867 #ifdef USAGE_COUNT
868 #if 0
869     /* find intervall which ends later or equal than than lt and has the */
870         /* lowest usagecount lower than lt */
871         i_min = -1;
872         u_min = lt->usagecount;
873         for (; (i >= 0) && (active[i]->i_end >= lt->i_end); i--) {
874                 if (active[i]->usagecount < u_min) {
875                         u_min = active[i]->usagecount;
876                         i_min = i;
877                 }
878         }
879
880         if (i_min != -1) {
881                 i = i_min;
882 #endif /* 0 */
883         if ((active[i]->i_end >= lt->i_end) &&
884                 (active[i]->usagecount < lt->usagecount)) {
885 #else /* USAGE_COUNT */
886         /* get last intervall from active */
887         if (active[i]->i_end > lt->i_end) {
888 #endif /* USAGE_COUNT */
889
890 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
891                 /* Don't spill between one and two word int types */
892                 if ((active[i]->type == TYPE_LNG) != (lt->type == TYPE_LNG))
893                         return;
894 #endif
895                 
896                 lt->regoff = active[i]->regoff;
897                 active[i]->regoff = -1;
898
899                 (*active_top)--;
900                 for (j = i; j < *active_top; j++)
901                         active[j] = active[j + 1];
902                 
903                 lsra_add_active(lt, active, active_top);
904         } else {
905                 lt->regoff = -1;
906         }
907 }
908
909 void lsra_calc_lifetime_length(jitdata *jd)
910 {
911         struct lifetime *lt;
912         int i, lt_index;
913         int lifetimecount;
914
915         int *icount_block, icount;
916         int flags; /* 0 INMEMORY -> ls->lt_mem */
917                    /* 1 INTREG   -> ls->lt_int  */
918                    /* 2 FLTREG   -> ls->lt_flt  */
919
920         lsradata *ls;
921
922         ls = jd->ls;
923
924         icount_block = DMNEW(int, ls->basicblockcount);
925         icount_block[0] = icount = 0 /* + ls->max_vars_with_indices + 1 */;
926         for (i=1; i < ls->basicblockcount; i++) {
927                 if (ls->sorted[i-1] != -1)
928                         icount += ls->basicblocks[ls->sorted[i-1]]->icount + 1 + 
929                                 ls->varcount_with_indices;
930                 if (ls->sorted[i] != -1)
931                         icount_block[i] = icount;
932         }
933
934 #ifdef LSRA_DEBUG_VERBOSE
935         if (compileverbose) {
936                 printf("icount_block: ");
937                 for (i=0; i < ls->basicblockcount; i++)
938                         printf("(%3i-%3i) ",i, icount_block[i]);
939                 printf("\n");
940         }
941 #endif
942
943         lifetimecount = 0;
944         for(lt_index = 0 ;lt_index < ls->lifetimecount; lt_index++) {
945                 if ( ls->lifetime[lt_index].type != -1) { /* used lifetime */
946                         /* remember lt_index in lt_sorted */
947                         ls->lt_used[lifetimecount ++] = lt_index; 
948                         lt = &(ls->lifetime[lt_index]);
949
950                         /* compute lt->bb_first_def, i_first_def, bb_last_use and */
951                         /* i_last_use */
952
953                         _LSRA_ASSERT(lt->def != NULL);
954                         /*                      _LSRA_ASSERT(lt->use != NULL);*/
955                         if (lt->use == NULL)
956                                 lt->use = lt->def;
957
958 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
959                         /* prevent conflicts between lifetimes of type long by increasing */
960                         /* the lifetime by one instruction */
961                         /* i.e.(ri/rj)  ...       */
962                         /*     (rk/rl)  ICMD_LNEG */
963                         /* with i==l and/or j==k  */
964                         /* to resolve this during codegeneration a temporary register     */
965                         /* would be needed */
966                         if (lt->type == TYPE_LNG) 
967                                 lt->i_last_use++;
968 #endif
969
970 /* distribute lifetimes to lt_int, lt_flt and lt_mem */
971
972                         lt->regoff = -1;
973
974                         switch (lt->type) {
975                         case TYPE_LNG:
976 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
977                                 flags = 0;
978 #else
979                                 flags = 1;
980 #endif
981                                 break;
982
983                         case TYPE_INT:
984                         case TYPE_ADR:
985                                 flags=1;
986                                 break;
987                         case TYPE_DBL:
988                         case TYPE_FLT:
989 #if defined(__I386__)
990                                 /*
991                                  * for i386 put all floats in memory
992                                  */
993                                 flags=0;
994                                 break;
995 #endif
996                                 flags=2;
997                                 break;
998                         default:
999                                 { log_text("Unknown Type\n"); exit(1); }
1000                         }
1001
1002                         switch (flags) {
1003                         case 0: /* lt_used[lt_used_index] -> lt_rest */
1004                                 ls->lt_mem[ ls->lt_mem_count++ ] = lt_index;
1005                                 break;
1006                         case 1: /* l->lifetimes -> lt_int */
1007                                 ls->lt_int[ ls->lt_int_count++ ] = lt_index;
1008                                 break;
1009                         case 2: /* l->lifetimes -> lt_flt */
1010                                 ls->lt_flt[ ls->lt_flt_count++ ] = lt_index;
1011                                 break;
1012                         }
1013
1014
1015                         if (lt->bb_first_def < -1) {
1016                                 printf("--------- Warning: variable not defined!------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1017                                 lt->bb_first_def = 0;
1018                                 lt->i_first_def = 0;
1019                         }
1020
1021                         lt->i_start = icount_block[lt->bb_first_def] + lt->i_first_def;
1022
1023                         if (lt->bb_last_use == -1) {
1024                                 /* unused Vars are not regarded by lifeness_analysis! */
1025                                 _LSRA_ASSERT(lt->def != NULL)
1026                                 _LSRA_ASSERT(lt->def->next == NULL)
1027                                 
1028                                 if (compileverbose) {
1029                                         printf("--------- Warning: variable not used! ---------");
1030                                         printf("vi: %i start: %i end: %i\n", lt->v_index, 
1031                                                    lt->i_start, lt->i_end);
1032                                 }
1033                                 lt->bb_last_use = lt->bb_first_def;
1034                                 lt->i_last_use = lt->i_first_def;
1035                         }
1036
1037                         lt->i_end = icount_block[lt->bb_last_use] + lt->i_last_use;
1038
1039                         if (lt->i_start < 0)
1040                                 printf("------- Error: Lt %3i Vi %4i invalid!\n",lt_index, lt->v_index);
1041
1042                         if (lt->i_start > lt->i_end) 
1043                                 printf("--------- Warning: last use before first def! vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1044
1045 #ifdef USAGE_PER_INSTR
1046                         lt->usagecount = lt->usagecount / ( lt->i_end - lt->i_start + 1);
1047 #endif
1048                 }
1049         }
1050         ls->lifetimecount = lifetimecount;
1051 }
1052
1053 #ifdef LSRA_DEBUG_VERBOSE
1054 void print_lifetimes(jitdata *jd, int *lt, int lifetimecount)
1055 {
1056         struct lifetime *n;
1057         int lt_index;
1058         lsradata *ls;
1059         registerdata *rd;
1060
1061         rd = jd->rd;
1062         ls = jd->ls;
1063
1064         for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1065                 n = ls->lifetime + lt[lt_index];
1066                 printf("i_Start: %3i(%3i,%3i) i_stop: %3i(%3i,%3i) reg: %3i VI: %3i type: %3i flags: %3i usage: %3li ltflags: %xi \n",n->i_start, ls->sorted[n->bb_first_def], n->i_first_def,n->i_end, ls->sorted[n->bb_last_use], n->i_last_use,n->regoff,n->v_index,n->type,n->flags, n->usagecount, n->flags);
1067         }
1068         printf( "%3i Lifetimes printed \n",lt_index);
1069 }
1070
1071 void print_all_lifetimes(jitdata *jd)
1072 {
1073         struct lifetime *n;
1074         int lt_index;
1075         lsradata *ls;
1076         registerdata *rd;
1077
1078         rd = jd->rd;
1079         ls = jd->ls;
1080
1081         for (lt_index = 0; lt_index < ls->lifetimecount; lt_index++) {
1082                 n = &(ls->lifetime[lt_index]);
1083                 if (n->type != -1) {
1084                         printf("i_Start: %3i(%3i,%3i) i_stop: %3i(%3i,%3i) VI: %3i type: %3i flags: %3i usage: %3li ltflags: %xi \n",n->i_start, ls->sorted[n->bb_first_def], n->i_first_def,n->i_end, ls->sorted[n->bb_last_use], n->i_last_use,n->v_index,n->type,n->flags, n->usagecount, n->flags);
1085                 }
1086         }
1087         printf( "%3i Lifetimes printed \n",lt_index);
1088 }
1089 #endif
1090
1091 /*
1092  * These are local overrides for various environment variables in Emacs.
1093  * Please do not remove this and leave it at the end of the file, where
1094  * Emacs will automagically detect them.
1095  * ---------------------------------------------------------------------
1096  * Local variables:
1097  * mode: c
1098  * indent-tabs-mode: t
1099  * c-basic-offset: 4
1100  * tab-width: 4
1101  * End:
1102  */