Revision e590d4e6 tcg/optimize.c

b/tcg/optimize.c
39 39
    TCG_TEMP_UNDEF = 0,
40 40
    TCG_TEMP_CONST,
41 41
    TCG_TEMP_COPY,
42
    TCG_TEMP_HAS_COPY
43 42
} tcg_temp_state;
44 43

  
45 44
struct tcg_temp_info {
......
51 50

  
52 51
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
53 52

  
54
/* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP was a representative of some
55
   class of equivalent temp's, a new representative should be chosen in this
56
   class. */
57
static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
53
/* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP only had one copy, remove
54
   the copy flag from the left temp.  */
55
static void reset_temp(TCGArg temp)
58 56
{
59
    int i;
60
    TCGArg new_base = (TCGArg)-1;
61
    if (temps[temp].state == TCG_TEMP_HAS_COPY) {
62
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
63
            if (i >= nb_globals) {
64
                temps[i].state = TCG_TEMP_HAS_COPY;
65
                new_base = i;
66
                break;
67
            }
68
        }
69
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
70
            if (new_base == (TCGArg)-1) {
71
                temps[i].state = TCG_TEMP_UNDEF;
72
            } else {
73
                temps[i].val = new_base;
74
            }
57
    if (temps[temp].state == TCG_TEMP_COPY) {
58
        if (temps[temp].prev_copy == temps[temp].next_copy) {
59
            temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
60
        } else {
61
            temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
62
            temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
75 63
        }
76
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
77
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
78
    } else if (temps[temp].state == TCG_TEMP_COPY) {
79
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
80
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
81
        new_base = temps[temp].val;
82 64
    }
83 65
    temps[temp].state = TCG_TEMP_UNDEF;
84
    if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
85
        temps[new_base].state = TCG_TEMP_UNDEF;
86
    }
87 66
}
88 67

  
89 68
static int op_bits(TCGOpcode op)
......
106 85
    }
107 86
}
108 87

  
88
static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
89
{
90
    TCGArg i;
91

  
92
    /* If this is already a global, we can't do better. */
93
    if (temp < s->nb_globals) {
94
        return temp;
95
    }
96

  
97
    /* Search for a global first. */
98
    for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
99
        if (i < s->nb_globals) {
100
            return i;
101
        }
102
    }
103

  
104
    /* If it is a temp, search for a temp local. */
105
    if (!s->temps[temp].temp_local) {
106
        for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
107
            if (s->temps[i].temp_local) {
108
                return i;
109
            }
110
        }
111
    }
112

  
113
    /* Failure to find a better representation, return the same temp. */
114
    return temp;
115
}
116

  
117
static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
118
{
119
    TCGArg i;
120

  
121
    if (arg1 == arg2) {
122
        return true;
123
    }
124

  
125
    if (temps[arg1].state != TCG_TEMP_COPY
126
        || temps[arg2].state != TCG_TEMP_COPY) {
127
        return false;
128
    }
129

  
130
    for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
131
        if (i == arg2) {
132
            return true;
133
        }
134
    }
135

  
136
    return false;
137
}
138

  
109 139
static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
110 140
                            TCGArg dst, TCGArg src)
111 141
{
112
        reset_temp(dst, s->nb_temps, s->nb_globals);
113
        assert(temps[src].state != TCG_TEMP_COPY);
114
        /* Only consider temps with the same type (width) as copies. */
115
        if (src >= s->nb_globals && s->temps[dst].type == s->temps[src].type) {
116
            assert(temps[src].state != TCG_TEMP_CONST);
117
            if (temps[src].state != TCG_TEMP_HAS_COPY) {
118
                temps[src].state = TCG_TEMP_HAS_COPY;
142
        reset_temp(dst);
143
        assert(temps[src].state != TCG_TEMP_CONST);
144

  
145
        if (s->temps[src].type == s->temps[dst].type) {
146
            if (temps[src].state != TCG_TEMP_COPY) {
147
                temps[src].state = TCG_TEMP_COPY;
119 148
                temps[src].next_copy = src;
120 149
                temps[src].prev_copy = src;
121 150
            }
122 151
            temps[dst].state = TCG_TEMP_COPY;
123
            temps[dst].val = src;
124 152
            temps[dst].next_copy = temps[src].next_copy;
125 153
            temps[dst].prev_copy = src;
126 154
            temps[temps[dst].next_copy].prev_copy = dst;
127 155
            temps[src].next_copy = dst;
128 156
        }
157

  
129 158
        gen_args[0] = dst;
130 159
        gen_args[1] = src;
131 160
}
132 161

  
133
static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
134
                             int nb_temps, int nb_globals)
162
static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
135 163
{
136
        reset_temp(dst, nb_temps, nb_globals);
164
        reset_temp(dst);
137 165
        temps[dst].state = TCG_TEMP_CONST;
138 166
        temps[dst].val = val;
139 167
        gen_args[0] = dst;
......
324 352
    tcg_abort();
325 353
}
326 354

  
327

  
328 355
/* Propagate constants and copies, fold constant expressions. */
329 356
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
330 357
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
......
338 365

  
339 366
    /* Array VALS has an element for each temp.
340 367
       If this temp holds a constant then its value is kept in VALS' element.
341
       If this temp is a copy of other ones then this equivalence class'
342
       representative is kept in VALS' element.
343
       If this temp is neither copy nor constant then corresponding VALS'
344
       element is unused. */
368
       If this temp is a copy of other ones then the other copies are
369
       available through the doubly linked circular list. */
345 370

  
346 371
    nb_temps = s->nb_temps;
347 372
    nb_globals = s->nb_globals;
......
357 382
            assert(op != INDEX_op_call);
358 383
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
359 384
                if (temps[args[i]].state == TCG_TEMP_COPY) {
360
                    args[i] = temps[args[i]].val;
385
                    args[i] = find_better_copy(s, args[i]);
361 386
                }
362 387
            }
363 388
        }
......
429 454
            if (temps[args[1]].state == TCG_TEMP_CONST
430 455
                && temps[args[1]].val == 0) {
431 456
                gen_opc_buf[op_index] = op_to_movi(op);
432
                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
457
                tcg_opt_gen_movi(gen_args, args[0], 0);
433 458
                args += 3;
434 459
                gen_args += 2;
435 460
                continue;
......
456 481
            }
457 482
            if (temps[args[2]].state == TCG_TEMP_CONST
458 483
                && temps[args[2]].val == 0) {
459
                if ((temps[args[0]].state == TCG_TEMP_COPY
460
                    && temps[args[0]].val == args[1])
461
                    || args[0] == args[1]) {
484
                if (temps_are_copies(args[0], args[1])) {
462 485
                    gen_opc_buf[op_index] = INDEX_op_nop;
463 486
                } else {
464 487
                    gen_opc_buf[op_index] = op_to_mov(op);
......
480 503
            if ((temps[args[2]].state == TCG_TEMP_CONST
481 504
                && temps[args[2]].val == 0)) {
482 505
                gen_opc_buf[op_index] = op_to_movi(op);
483
                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
506
                tcg_opt_gen_movi(gen_args, args[0], 0);
484 507
                args += 3;
485 508
                gen_args += 2;
486 509
                continue;
......
495 518
        CASE_OP_32_64(or):
496 519
        CASE_OP_32_64(and):
497 520
            if (args[1] == args[2]) {
498
                if (args[1] == args[0]) {
521
                if (temps_are_copies(args[0], args[1])) {
499 522
                    gen_opc_buf[op_index] = INDEX_op_nop;
500 523
                } else {
501 524
                    gen_opc_buf[op_index] = op_to_mov(op);
......
515 538
           allocator where needed and possible.  Also detect copies. */
516 539
        switch (op) {
517 540
        CASE_OP_32_64(mov):
518
            if ((temps[args[1]].state == TCG_TEMP_COPY
519
                && temps[args[1]].val == args[0])
520
                || args[0] == args[1]) {
541
            if (temps_are_copies(args[0], args[1])) {
521 542
                args += 2;
522 543
                gen_opc_buf[op_index] = INDEX_op_nop;
523 544
                break;
......
535 556
            args[1] = temps[args[1]].val;
536 557
            /* fallthrough */
537 558
        CASE_OP_32_64(movi):
538
            tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
559
            tcg_opt_gen_movi(gen_args, args[0], args[1]);
539 560
            gen_args += 2;
540 561
            args += 2;
541 562
            break;
......
550 571
            if (temps[args[1]].state == TCG_TEMP_CONST) {
551 572
                gen_opc_buf[op_index] = op_to_movi(op);
552 573
                tmp = do_constant_folding(op, temps[args[1]].val, 0);
553
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
574
                tcg_opt_gen_movi(gen_args, args[0], tmp);
554 575
            } else {
555
                reset_temp(args[0], nb_temps, nb_globals);
576
                reset_temp(args[0]);
556 577
                gen_args[0] = args[0];
557 578
                gen_args[1] = args[1];
558 579
            }
......
580 601
                gen_opc_buf[op_index] = op_to_movi(op);
581 602
                tmp = do_constant_folding(op, temps[args[1]].val,
582 603
                                          temps[args[2]].val);
583
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
604
                tcg_opt_gen_movi(gen_args, args[0], tmp);
584 605
                gen_args += 2;
585 606
            } else {
586
                reset_temp(args[0], nb_temps, nb_globals);
607
                reset_temp(args[0]);
587 608
                gen_args[0] = args[0];
588 609
                gen_args[1] = args[1];
589 610
                gen_args[2] = args[2];
......
597 618
                gen_opc_buf[op_index] = op_to_movi(op);
598 619
                tmp = do_constant_folding_cond(op, temps[args[1]].val,
599 620
                                               temps[args[2]].val, args[3]);
600
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
621
                tcg_opt_gen_movi(gen_args, args[0], tmp);
601 622
                gen_args += 2;
602 623
            } else {
603
                reset_temp(args[0], nb_temps, nb_globals);
624
                reset_temp(args[0]);
604 625
                gen_args[0] = args[0];
605 626
                gen_args[1] = args[1];
606 627
                gen_args[2] = args[2];
......
623 644
                }
624 645
            } else {
625 646
                memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
626
                reset_temp(args[0], nb_temps, nb_globals);
647
                reset_temp(args[0]);
627 648
                gen_args[0] = args[0];
628 649
                gen_args[1] = args[1];
629 650
                gen_args[2] = args[2];
......
637 658
                && temps[args[2]].state == TCG_TEMP_CONST) {
638 659
                tmp = do_constant_folding_cond(op, temps[args[1]].val,
639 660
                                               temps[args[2]].val, args[5]);
640
                if (args[0] == args[4-tmp]
641
                    || (temps[args[4-tmp]].state == TCG_TEMP_COPY
642
                        && temps[args[4-tmp]].val == args[0])) {
661
                if (temps_are_copies(args[0], args[4-tmp])) {
643 662
                    gen_opc_buf[op_index] = INDEX_op_nop;
644 663
                } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
645 664
                    gen_opc_buf[op_index] = op_to_movi(op);
646
                    tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val,
647
                                     nb_temps, nb_globals);
665
                    tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
648 666
                    gen_args += 2;
649 667
                } else {
650 668
                    gen_opc_buf[op_index] = op_to_mov(op);
651
                    tcg_opt_gen_mov(gen_args, args[0], args[4-tmp],
652
                                    nb_temps, nb_globals);
669
                    tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
653 670
                    gen_args += 2;
654 671
                }
655 672
            } else {
656
                reset_temp(args[0], nb_temps, nb_globals);
673
                reset_temp(args[0]);
657 674
                gen_args[0] = args[0];
658 675
                gen_args[1] = args[1];
659 676
                gen_args[2] = args[2];
......
668 685
            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
669 686
            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
670 687
                for (i = 0; i < nb_globals; i++) {
671
                    reset_temp(i, nb_temps, nb_globals);
688
                    reset_temp(i);
672 689
                }
673 690
            }
674 691
            for (i = 0; i < (args[0] >> 16); i++) {
675
                reset_temp(args[i + 1], nb_temps, nb_globals);
692
                reset_temp(args[i + 1]);
676 693
            }
677 694
            i = nb_call_args + 3;
678 695
            while (i) {
......
691 708
                memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
692 709
            } else {
693 710
                for (i = 0; i < def->nb_oargs; i++) {
694
                    reset_temp(args[i], nb_temps, nb_globals);
711
                    reset_temp(args[i]);
695 712
                }
696 713
            }
697 714
            for (i = 0; i < def->nb_args; i++) {

Also available in: Unified diff