Commit 641d5fbe6bef1cbc34732665efa8d5f0b71acbc4

Authored by bellard
1 parent 98fc5614

added local temporaries

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4576 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 103 additions and 45 deletions
tcg/tcg.c
... ... @@ -269,7 +269,7 @@ void tcg_func_start(TCGContext *s)
269 269 int i;
270 270 tcg_pool_reset(s);
271 271 s->nb_temps = s->nb_globals;
272   - for(i = 0; i < TCG_TYPE_COUNT; i++)
  272 + for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
273 273 s->first_free_temp[i] = -1;
274 274 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
275 275 s->nb_labels = 0;
... ... @@ -407,19 +407,23 @@ TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
407 407 return MAKE_TCGV(idx);
408 408 }
409 409  
410   -TCGv tcg_temp_new(TCGType type)
  410 +TCGv tcg_temp_new_internal(TCGType type, int temp_local)
411 411 {
412 412 TCGContext *s = &tcg_ctx;
413 413 TCGTemp *ts;
414   - int idx;
  414 + int idx, k;
415 415  
416   - idx = s->first_free_temp[type];
  416 + k = type;
  417 + if (temp_local)
  418 + k += TCG_TYPE_COUNT;
  419 + idx = s->first_free_temp[k];
417 420 if (idx != -1) {
418 421 /* There is already an available temp with the
419 422 right type */
420 423 ts = &s->temps[idx];
421   - s->first_free_temp[type] = ts->next_free_temp;
  424 + s->first_free_temp[k] = ts->next_free_temp;
422 425 ts->temp_allocated = 1;
  426 + assert(ts->temp_local == temp_local);
423 427 } else {
424 428 idx = s->nb_temps;
425 429 #if TCG_TARGET_REG_BITS == 32
... ... @@ -429,11 +433,13 @@ TCGv tcg_temp_new(TCGType type)
429 433 ts->base_type = type;
430 434 ts->type = TCG_TYPE_I32;
431 435 ts->temp_allocated = 1;
  436 + ts->temp_local = temp_local;
432 437 ts->name = NULL;
433 438 ts++;
434 439 ts->base_type = TCG_TYPE_I32;
435 440 ts->type = TCG_TYPE_I32;
436 441 ts->temp_allocated = 1;
  442 + ts->temp_local = temp_local;
437 443 ts->name = NULL;
438 444 s->nb_temps += 2;
439 445 } else
... ... @@ -444,6 +450,7 @@ TCGv tcg_temp_new(TCGType type)
444 450 ts->base_type = type;
445 451 ts->type = type;
446 452 ts->temp_allocated = 1;
  453 + ts->temp_local = temp_local;
447 454 ts->name = NULL;
448 455 s->nb_temps++;
449 456 }
... ... @@ -456,15 +463,17 @@ void tcg_temp_free(TCGv arg)
456 463 TCGContext *s = &tcg_ctx;
457 464 TCGTemp *ts;
458 465 int idx = GET_TCGV(arg);
459   - TCGType type;
  466 + int k;
460 467  
461 468 assert(idx >= s->nb_globals && idx < s->nb_temps);
462 469 ts = &s->temps[idx];
463 470 assert(ts->temp_allocated != 0);
464 471 ts->temp_allocated = 0;
465   - type = ts->base_type;
466   - ts->next_free_temp = s->first_free_temp[type];
467   - s->first_free_temp[type] = idx;
  472 + k = ts->base_type;
  473 + if (ts->temp_local)
  474 + k += TCG_TYPE_COUNT;
  475 + ts->next_free_temp = s->first_free_temp[k];
  476 + s->first_free_temp[k] = idx;
468 477 }
469 478  
470 479  
... ... @@ -683,7 +692,10 @@ static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
683 692 if (idx < s->nb_globals) {
684 693 pstrcpy(buf, buf_size, ts->name);
685 694 } else {
686   - snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
  695 + if (ts->temp_local)
  696 + snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
  697 + else
  698 + snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
687 699 }
688 700 return buf;
689 701 }
... ... @@ -987,13 +999,34 @@ static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
987 999 }
988 1000 }
989 1001  
990   -/* liveness analysis: end of basic block: globals are live, temps are dead */
991   -static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
  1002 +/* liveness analysis: end of function: globals are live, temps are
  1003 + dead. */
  1004 +/* XXX: at this stage, not used as there would be little gains because
  1005 + most TBs end with a conditional jump. */
  1006 +static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
992 1007 {
993 1008 memset(dead_temps, 0, s->nb_globals);
994 1009 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
995 1010 }
996 1011  
  1012 +/* liveness analysis: end of basic block: globals are live, temps are
  1013 + dead, local temps are live. */
  1014 +static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
  1015 +{
  1016 + int i;
  1017 + TCGTemp *ts;
  1018 +
  1019 + memset(dead_temps, 0, s->nb_globals);
  1020 + ts = &s->temps[s->nb_globals];
  1021 + for(i = s->nb_globals; i < s->nb_temps; i++) {
  1022 + if (ts->temp_local)
  1023 + dead_temps[i] = 0;
  1024 + else
  1025 + dead_temps[i] = 1;
  1026 + ts++;
  1027 + }
  1028 +}
  1029 +
997 1030 /* Liveness analysis : update the opc_dead_iargs array to tell if a
998 1031 given input arguments is dead. Instructions updating dead
999 1032 temporaries are removed. */
... ... @@ -1366,37 +1399,48 @@ static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1366 1399 tcg_abort();
1367 1400 }
1368 1401  
  1402 +/* save a temporary to memory. 'allocated_regs' is used in case a
  1403 + temporary registers needs to be allocated to store a constant. */
  1404 +static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
  1405 +{
  1406 + TCGTemp *ts;
  1407 + int reg;
  1408 +
  1409 + ts = &s->temps[temp];
  1410 + if (!ts->fixed_reg) {
  1411 + switch(ts->val_type) {
  1412 + case TEMP_VAL_REG:
  1413 + tcg_reg_free(s, ts->reg);
  1414 + break;
  1415 + case TEMP_VAL_DEAD:
  1416 + ts->val_type = TEMP_VAL_MEM;
  1417 + break;
  1418 + case TEMP_VAL_CONST:
  1419 + reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
  1420 + allocated_regs);
  1421 + if (!ts->mem_allocated)
  1422 + temp_allocate_frame(s, temp);
  1423 + tcg_out_movi(s, ts->type, reg, ts->val);
  1424 + tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
  1425 + ts->val_type = TEMP_VAL_MEM;
  1426 + break;
  1427 + case TEMP_VAL_MEM:
  1428 + break;
  1429 + default:
  1430 + tcg_abort();
  1431 + }
  1432 + }
  1433 +}
  1434 +
1369 1435 /* save globals to their cannonical location and assume they can be
1370 1436 modified be the following code. 'allocated_regs' is used in case a
1371 1437 temporary registers needs to be allocated to store a constant. */
1372 1438 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1373 1439 {
1374   - TCGTemp *ts;
1375   - int i, reg;
  1440 + int i;
1376 1441  
1377 1442 for(i = 0; i < s->nb_globals; i++) {
1378   - ts = &s->temps[i];
1379   - if (!ts->fixed_reg) {
1380   - switch(ts->val_type) {
1381   - case TEMP_VAL_REG:
1382   - tcg_reg_free(s, ts->reg);
1383   - break;
1384   - case TEMP_VAL_DEAD:
1385   - ts->val_type = TEMP_VAL_MEM;
1386   - break;
1387   - case TEMP_VAL_CONST:
1388   - reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1389   - allocated_regs);
1390   - tcg_out_movi(s, ts->type, reg, ts->val);
1391   - tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1392   - ts->val_type = TEMP_VAL_MEM;
1393   - break;
1394   - case TEMP_VAL_MEM:
1395   - break;
1396   - default:
1397   - tcg_abort();
1398   - }
1399   - }
  1443 + temp_save(s, i, allocated_regs);
1400 1444 }
1401 1445 }
1402 1446  
... ... @@ -1409,10 +1453,14 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1409 1453  
1410 1454 for(i = s->nb_globals; i < s->nb_temps; i++) {
1411 1455 ts = &s->temps[i];
1412   - if (ts->val_type == TEMP_VAL_REG) {
1413   - s->reg_to_temp[ts->reg] = -1;
  1456 + if (ts->temp_local) {
  1457 + temp_save(s, i, allocated_regs);
  1458 + } else {
  1459 + if (ts->val_type == TEMP_VAL_REG) {
  1460 + s->reg_to_temp[ts->reg] = -1;
  1461 + }
  1462 + ts->val_type = TEMP_VAL_DEAD;
1414 1463 }
1415   - ts->val_type = TEMP_VAL_DEAD;
1416 1464 }
1417 1465  
1418 1466 save_globals(s, allocated_regs);
... ...
tcg/tcg.h
... ... @@ -189,6 +189,9 @@ typedef struct TCGTemp {
189 189 unsigned int fixed_reg:1;
190 190 unsigned int mem_coherent:1;
191 191 unsigned int mem_allocated:1;
  192 + unsigned int temp_local:1; /* If true, the temp is saved accross
  193 + basic blocks. Otherwise, it is not
  194 + preserved accross basic blocks. */
192 195 unsigned int temp_allocated:1; /* never used for code gen */
193 196 /* index of next free temp of same base type, -1 if end */
194 197 int next_free_temp;
... ... @@ -212,11 +215,8 @@ struct TCGContext {
212 215 TCGTemp *temps; /* globals first, temps after */
213 216 int nb_globals;
214 217 int nb_temps;
215   - int first_free_temp[TCG_TYPE_COUNT]; /* index of free temps, -1 if none */
216   -
217   - /* constant indexes (end of temp array) */
218   - int const_start;
219   - int const_end;
  218 + /* index of free temps, -1 if none */
  219 + int first_free_temp[TCG_TYPE_COUNT * 2];
220 220  
221 221 /* goto_tb support */
222 222 uint8_t *code_buf;
... ... @@ -224,8 +224,10 @@ struct TCGContext {
224 224 uint16_t *tb_next_offset;
225 225 uint16_t *tb_jmp_offset; /* != NULL if USE_DIRECT_JUMP */
226 226  
  227 + /* liveness analysis */
227 228 uint16_t *op_dead_iargs; /* for each operation, each bit tells if the
228 229 corresponding input argument is dead */
  230 +
229 231 /* tells in which temporary a given register is. It does not take
230 232 into account fixed registers */
231 233 int reg_to_temp[TCG_TARGET_NB_REGS];
... ... @@ -305,7 +307,15 @@ TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
305 307 const char *name);
306 308 TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
307 309 const char *name);
308   -TCGv tcg_temp_new(TCGType type);
  310 +TCGv tcg_temp_new_internal(TCGType type, int temp_local);
  311 +static inline TCGv tcg_temp_new(TCGType type)
  312 +{
  313 + return tcg_temp_new_internal(type, 0);
  314 +}
  315 +static inline TCGv tcg_temp_local_new(TCGType type)
  316 +{
  317 + return tcg_temp_new_internal(type, 1);
  318 +}
309 319 void tcg_temp_free(TCGv arg);
310 320 char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg);
311 321 void tcg_dump_info(FILE *f,
... ...