Statistics
| Branch: | Revision:

root / tcg / optimize.c @ e590d4e6

History | View | Annotate | Download (22.4 kB)

1
/*
2
 * Optimizations for Tiny Code Generator for QEMU
3
 *
4
 * Copyright (c) 2010 Samsung Electronics.
5
 * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25

    
26
#include "config.h"
27

    
28
#include <stdlib.h>
29
#include <stdio.h>
30

    
31
#include "qemu-common.h"
32
#include "tcg-op.h"
33

    
34
#define CASE_OP_32_64(x)                        \
35
        glue(glue(case INDEX_op_, x), _i32):    \
36
        glue(glue(case INDEX_op_, x), _i64)
37

    
38
typedef enum {
39
    TCG_TEMP_UNDEF = 0,
40
    TCG_TEMP_CONST,
41
    TCG_TEMP_COPY,
42
} tcg_temp_state;
43

    
44
struct tcg_temp_info {
45
    tcg_temp_state state;
46
    uint16_t prev_copy;
47
    uint16_t next_copy;
48
    tcg_target_ulong val;
49
};
50

    
51
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
52

    
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)
56
{
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;
63
        }
64
    }
65
    temps[temp].state = TCG_TEMP_UNDEF;
66
}
67

    
68
static int op_bits(TCGOpcode op)
69
{
70
    const TCGOpDef *def = &tcg_op_defs[op];
71
    return def->flags & TCG_OPF_64BIT ? 64 : 32;
72
}
73

    
74
static TCGOpcode op_to_movi(TCGOpcode op)
75
{
76
    switch (op_bits(op)) {
77
    case 32:
78
        return INDEX_op_movi_i32;
79
    case 64:
80
        return INDEX_op_movi_i64;
81
    default:
82
        fprintf(stderr, "op_to_movi: unexpected return value of "
83
                "function op_bits.\n");
84
        tcg_abort();
85
    }
86
}
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

    
139
static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
140
                            TCGArg dst, TCGArg src)
141
{
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;
148
                temps[src].next_copy = src;
149
                temps[src].prev_copy = src;
150
            }
151
            temps[dst].state = TCG_TEMP_COPY;
152
            temps[dst].next_copy = temps[src].next_copy;
153
            temps[dst].prev_copy = src;
154
            temps[temps[dst].next_copy].prev_copy = dst;
155
            temps[src].next_copy = dst;
156
        }
157

    
158
        gen_args[0] = dst;
159
        gen_args[1] = src;
160
}
161

    
162
static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
163
{
164
        reset_temp(dst);
165
        temps[dst].state = TCG_TEMP_CONST;
166
        temps[dst].val = val;
167
        gen_args[0] = dst;
168
        gen_args[1] = val;
169
}
170

    
171
static TCGOpcode op_to_mov(TCGOpcode op)
172
{
173
    switch (op_bits(op)) {
174
    case 32:
175
        return INDEX_op_mov_i32;
176
    case 64:
177
        return INDEX_op_mov_i64;
178
    default:
179
        fprintf(stderr, "op_to_mov: unexpected return value of "
180
                "function op_bits.\n");
181
        tcg_abort();
182
    }
183
}
184

    
185
static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
186
{
187
    switch (op) {
188
    CASE_OP_32_64(add):
189
        return x + y;
190

    
191
    CASE_OP_32_64(sub):
192
        return x - y;
193

    
194
    CASE_OP_32_64(mul):
195
        return x * y;
196

    
197
    CASE_OP_32_64(and):
198
        return x & y;
199

    
200
    CASE_OP_32_64(or):
201
        return x | y;
202

    
203
    CASE_OP_32_64(xor):
204
        return x ^ y;
205

    
206
    case INDEX_op_shl_i32:
207
        return (uint32_t)x << (uint32_t)y;
208

    
209
    case INDEX_op_shl_i64:
210
        return (uint64_t)x << (uint64_t)y;
211

    
212
    case INDEX_op_shr_i32:
213
        return (uint32_t)x >> (uint32_t)y;
214

    
215
    case INDEX_op_shr_i64:
216
        return (uint64_t)x >> (uint64_t)y;
217

    
218
    case INDEX_op_sar_i32:
219
        return (int32_t)x >> (int32_t)y;
220

    
221
    case INDEX_op_sar_i64:
222
        return (int64_t)x >> (int64_t)y;
223

    
224
    case INDEX_op_rotr_i32:
225
        x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y);
226
        return x;
227

    
228
    case INDEX_op_rotr_i64:
229
        x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y);
230
        return x;
231

    
232
    case INDEX_op_rotl_i32:
233
        x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y));
234
        return x;
235

    
236
    case INDEX_op_rotl_i64:
237
        x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y));
238
        return x;
239

    
240
    CASE_OP_32_64(not):
241
        return ~x;
242

    
243
    CASE_OP_32_64(neg):
244
        return -x;
245

    
246
    CASE_OP_32_64(andc):
247
        return x & ~y;
248

    
249
    CASE_OP_32_64(orc):
250
        return x | ~y;
251

    
252
    CASE_OP_32_64(eqv):
253
        return ~(x ^ y);
254

    
255
    CASE_OP_32_64(nand):
256
        return ~(x & y);
257

    
258
    CASE_OP_32_64(nor):
259
        return ~(x | y);
260

    
261
    CASE_OP_32_64(ext8s):
262
        return (int8_t)x;
263

    
264
    CASE_OP_32_64(ext16s):
265
        return (int16_t)x;
266

    
267
    CASE_OP_32_64(ext8u):
268
        return (uint8_t)x;
269

    
270
    CASE_OP_32_64(ext16u):
271
        return (uint16_t)x;
272

    
273
    case INDEX_op_ext32s_i64:
274
        return (int32_t)x;
275

    
276
    case INDEX_op_ext32u_i64:
277
        return (uint32_t)x;
278

    
279
    default:
280
        fprintf(stderr,
281
                "Unrecognized operation %d in do_constant_folding.\n", op);
282
        tcg_abort();
283
    }
284
}
285

    
286
static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
287
{
288
    TCGArg res = do_constant_folding_2(op, x, y);
289
    if (op_bits(op) == 32) {
290
        res &= 0xffffffff;
291
    }
292
    return res;
293
}
294

    
295
static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
296
                                       TCGArg y, TCGCond c)
297
{
298
    switch (op_bits(op)) {
299
    case 32:
300
        switch (c) {
301
        case TCG_COND_EQ:
302
            return (uint32_t)x == (uint32_t)y;
303
        case TCG_COND_NE:
304
            return (uint32_t)x != (uint32_t)y;
305
        case TCG_COND_LT:
306
            return (int32_t)x < (int32_t)y;
307
        case TCG_COND_GE:
308
            return (int32_t)x >= (int32_t)y;
309
        case TCG_COND_LE:
310
            return (int32_t)x <= (int32_t)y;
311
        case TCG_COND_GT:
312
            return (int32_t)x > (int32_t)y;
313
        case TCG_COND_LTU:
314
            return (uint32_t)x < (uint32_t)y;
315
        case TCG_COND_GEU:
316
            return (uint32_t)x >= (uint32_t)y;
317
        case TCG_COND_LEU:
318
            return (uint32_t)x <= (uint32_t)y;
319
        case TCG_COND_GTU:
320
            return (uint32_t)x > (uint32_t)y;
321
        }
322
        break;
323
    case 64:
324
        switch (c) {
325
        case TCG_COND_EQ:
326
            return (uint64_t)x == (uint64_t)y;
327
        case TCG_COND_NE:
328
            return (uint64_t)x != (uint64_t)y;
329
        case TCG_COND_LT:
330
            return (int64_t)x < (int64_t)y;
331
        case TCG_COND_GE:
332
            return (int64_t)x >= (int64_t)y;
333
        case TCG_COND_LE:
334
            return (int64_t)x <= (int64_t)y;
335
        case TCG_COND_GT:
336
            return (int64_t)x > (int64_t)y;
337
        case TCG_COND_LTU:
338
            return (uint64_t)x < (uint64_t)y;
339
        case TCG_COND_GEU:
340
            return (uint64_t)x >= (uint64_t)y;
341
        case TCG_COND_LEU:
342
            return (uint64_t)x <= (uint64_t)y;
343
        case TCG_COND_GTU:
344
            return (uint64_t)x > (uint64_t)y;
345
        }
346
        break;
347
    }
348

    
349
    fprintf(stderr,
350
            "Unrecognized bitness %d or condition %d in "
351
            "do_constant_folding_cond.\n", op_bits(op), c);
352
    tcg_abort();
353
}
354

    
355
/* Propagate constants and copies, fold constant expressions. */
356
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
357
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
358
{
359
    int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
360
    TCGOpcode op;
361
    const TCGOpDef *def;
362
    TCGArg *gen_args;
363
    TCGArg tmp;
364
    TCGCond cond;
365

    
366
    /* Array VALS has an element for each temp.
367
       If this temp holds a constant then its value is kept in VALS' element.
368
       If this temp is a copy of other ones then the other copies are
369
       available through the doubly linked circular list. */
370

    
371
    nb_temps = s->nb_temps;
372
    nb_globals = s->nb_globals;
373
    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
374

    
375
    nb_ops = tcg_opc_ptr - gen_opc_buf;
376
    gen_args = args;
377
    for (op_index = 0; op_index < nb_ops; op_index++) {
378
        op = gen_opc_buf[op_index];
379
        def = &tcg_op_defs[op];
380
        /* Do copy propagation */
381
        if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
382
            assert(op != INDEX_op_call);
383
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
384
                if (temps[args[i]].state == TCG_TEMP_COPY) {
385
                    args[i] = find_better_copy(s, args[i]);
386
                }
387
            }
388
        }
389

    
390
        /* For commutative operations make constant second argument */
391
        switch (op) {
392
        CASE_OP_32_64(add):
393
        CASE_OP_32_64(mul):
394
        CASE_OP_32_64(and):
395
        CASE_OP_32_64(or):
396
        CASE_OP_32_64(xor):
397
        CASE_OP_32_64(eqv):
398
        CASE_OP_32_64(nand):
399
        CASE_OP_32_64(nor):
400
            if (temps[args[1]].state == TCG_TEMP_CONST) {
401
                tmp = args[1];
402
                args[1] = args[2];
403
                args[2] = tmp;
404
            }
405
            break;
406
        CASE_OP_32_64(brcond):
407
            if (temps[args[0]].state == TCG_TEMP_CONST
408
                && temps[args[1]].state != TCG_TEMP_CONST) {
409
                tmp = args[0];
410
                args[0] = args[1];
411
                args[1] = tmp;
412
                args[2] = tcg_swap_cond(args[2]);
413
            }
414
            break;
415
        CASE_OP_32_64(setcond):
416
            if (temps[args[1]].state == TCG_TEMP_CONST
417
                && temps[args[2]].state != TCG_TEMP_CONST) {
418
                tmp = args[1];
419
                args[1] = args[2];
420
                args[2] = tmp;
421
                args[3] = tcg_swap_cond(args[3]);
422
            }
423
            break;
424
        CASE_OP_32_64(movcond):
425
            cond = args[5];
426
            if (temps[args[1]].state == TCG_TEMP_CONST
427
                && temps[args[2]].state != TCG_TEMP_CONST) {
428
                tmp = args[1];
429
                args[1] = args[2];
430
                args[2] = tmp;
431
                cond = tcg_swap_cond(cond);
432
            }
433
            /* For movcond, we canonicalize the "false" input reg to match
434
               the destination reg so that the tcg backend can implement
435
               a "move if true" operation.  */
436
            if (args[0] == args[3]) {
437
                tmp = args[3];
438
                args[3] = args[4];
439
                args[4] = tmp;
440
                cond = tcg_invert_cond(cond);
441
            }
442
            args[5] = cond;
443
        default:
444
            break;
445
        }
446

    
447
        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */
448
        switch (op) {
449
        CASE_OP_32_64(shl):
450
        CASE_OP_32_64(shr):
451
        CASE_OP_32_64(sar):
452
        CASE_OP_32_64(rotl):
453
        CASE_OP_32_64(rotr):
454
            if (temps[args[1]].state == TCG_TEMP_CONST
455
                && temps[args[1]].val == 0) {
456
                gen_opc_buf[op_index] = op_to_movi(op);
457
                tcg_opt_gen_movi(gen_args, args[0], 0);
458
                args += 3;
459
                gen_args += 2;
460
                continue;
461
            }
462
            break;
463
        default:
464
            break;
465
        }
466

    
467
        /* Simplify expression for "op r, a, 0 => mov r, a" cases */
468
        switch (op) {
469
        CASE_OP_32_64(add):
470
        CASE_OP_32_64(sub):
471
        CASE_OP_32_64(shl):
472
        CASE_OP_32_64(shr):
473
        CASE_OP_32_64(sar):
474
        CASE_OP_32_64(rotl):
475
        CASE_OP_32_64(rotr):
476
        CASE_OP_32_64(or):
477
        CASE_OP_32_64(xor):
478
            if (temps[args[1]].state == TCG_TEMP_CONST) {
479
                /* Proceed with possible constant folding. */
480
                break;
481
            }
482
            if (temps[args[2]].state == TCG_TEMP_CONST
483
                && temps[args[2]].val == 0) {
484
                if (temps_are_copies(args[0], args[1])) {
485
                    gen_opc_buf[op_index] = INDEX_op_nop;
486
                } else {
487
                    gen_opc_buf[op_index] = op_to_mov(op);
488
                    tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
489
                    gen_args += 2;
490
                }
491
                args += 3;
492
                continue;
493
            }
494
            break;
495
        default:
496
            break;
497
        }
498

    
499
        /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
500
        switch (op) {
501
        CASE_OP_32_64(and):
502
        CASE_OP_32_64(mul):
503
            if ((temps[args[2]].state == TCG_TEMP_CONST
504
                && temps[args[2]].val == 0)) {
505
                gen_opc_buf[op_index] = op_to_movi(op);
506
                tcg_opt_gen_movi(gen_args, args[0], 0);
507
                args += 3;
508
                gen_args += 2;
509
                continue;
510
            }
511
            break;
512
        default:
513
            break;
514
        }
515

    
516
        /* Simplify expression for "op r, a, a => mov r, a" cases */
517
        switch (op) {
518
        CASE_OP_32_64(or):
519
        CASE_OP_32_64(and):
520
            if (args[1] == args[2]) {
521
                if (temps_are_copies(args[0], args[1])) {
522
                    gen_opc_buf[op_index] = INDEX_op_nop;
523
                } else {
524
                    gen_opc_buf[op_index] = op_to_mov(op);
525
                    tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
526
                    gen_args += 2;
527
                }
528
                args += 3;
529
                continue;
530
            }
531
            break;
532
        default:
533
            break;
534
        }
535

    
536
        /* Propagate constants through copy operations and do constant
537
           folding.  Constants will be substituted to arguments by register
538
           allocator where needed and possible.  Also detect copies. */
539
        switch (op) {
540
        CASE_OP_32_64(mov):
541
            if (temps_are_copies(args[0], args[1])) {
542
                args += 2;
543
                gen_opc_buf[op_index] = INDEX_op_nop;
544
                break;
545
            }
546
            if (temps[args[1]].state != TCG_TEMP_CONST) {
547
                tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
548
                gen_args += 2;
549
                args += 2;
550
                break;
551
            }
552
            /* Source argument is constant.  Rewrite the operation and
553
               let movi case handle it. */
554
            op = op_to_movi(op);
555
            gen_opc_buf[op_index] = op;
556
            args[1] = temps[args[1]].val;
557
            /* fallthrough */
558
        CASE_OP_32_64(movi):
559
            tcg_opt_gen_movi(gen_args, args[0], args[1]);
560
            gen_args += 2;
561
            args += 2;
562
            break;
563
        CASE_OP_32_64(not):
564
        CASE_OP_32_64(neg):
565
        CASE_OP_32_64(ext8s):
566
        CASE_OP_32_64(ext8u):
567
        CASE_OP_32_64(ext16s):
568
        CASE_OP_32_64(ext16u):
569
        case INDEX_op_ext32s_i64:
570
        case INDEX_op_ext32u_i64:
571
            if (temps[args[1]].state == TCG_TEMP_CONST) {
572
                gen_opc_buf[op_index] = op_to_movi(op);
573
                tmp = do_constant_folding(op, temps[args[1]].val, 0);
574
                tcg_opt_gen_movi(gen_args, args[0], tmp);
575
            } else {
576
                reset_temp(args[0]);
577
                gen_args[0] = args[0];
578
                gen_args[1] = args[1];
579
            }
580
            gen_args += 2;
581
            args += 2;
582
            break;
583
        CASE_OP_32_64(add):
584
        CASE_OP_32_64(sub):
585
        CASE_OP_32_64(mul):
586
        CASE_OP_32_64(or):
587
        CASE_OP_32_64(and):
588
        CASE_OP_32_64(xor):
589
        CASE_OP_32_64(shl):
590
        CASE_OP_32_64(shr):
591
        CASE_OP_32_64(sar):
592
        CASE_OP_32_64(rotl):
593
        CASE_OP_32_64(rotr):
594
        CASE_OP_32_64(andc):
595
        CASE_OP_32_64(orc):
596
        CASE_OP_32_64(eqv):
597
        CASE_OP_32_64(nand):
598
        CASE_OP_32_64(nor):
599
            if (temps[args[1]].state == TCG_TEMP_CONST
600
                && temps[args[2]].state == TCG_TEMP_CONST) {
601
                gen_opc_buf[op_index] = op_to_movi(op);
602
                tmp = do_constant_folding(op, temps[args[1]].val,
603
                                          temps[args[2]].val);
604
                tcg_opt_gen_movi(gen_args, args[0], tmp);
605
                gen_args += 2;
606
            } else {
607
                reset_temp(args[0]);
608
                gen_args[0] = args[0];
609
                gen_args[1] = args[1];
610
                gen_args[2] = args[2];
611
                gen_args += 3;
612
            }
613
            args += 3;
614
            break;
615
        CASE_OP_32_64(setcond):
616
            if (temps[args[1]].state == TCG_TEMP_CONST
617
                && temps[args[2]].state == TCG_TEMP_CONST) {
618
                gen_opc_buf[op_index] = op_to_movi(op);
619
                tmp = do_constant_folding_cond(op, temps[args[1]].val,
620
                                               temps[args[2]].val, args[3]);
621
                tcg_opt_gen_movi(gen_args, args[0], tmp);
622
                gen_args += 2;
623
            } else {
624
                reset_temp(args[0]);
625
                gen_args[0] = args[0];
626
                gen_args[1] = args[1];
627
                gen_args[2] = args[2];
628
                gen_args[3] = args[3];
629
                gen_args += 4;
630
            }
631
            args += 4;
632
            break;
633
        CASE_OP_32_64(brcond):
634
            if (temps[args[0]].state == TCG_TEMP_CONST
635
                && temps[args[1]].state == TCG_TEMP_CONST) {
636
                if (do_constant_folding_cond(op, temps[args[0]].val,
637
                                             temps[args[1]].val, args[2])) {
638
                    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
639
                    gen_opc_buf[op_index] = INDEX_op_br;
640
                    gen_args[0] = args[3];
641
                    gen_args += 1;
642
                } else {
643
                    gen_opc_buf[op_index] = INDEX_op_nop;
644
                }
645
            } else {
646
                memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
647
                reset_temp(args[0]);
648
                gen_args[0] = args[0];
649
                gen_args[1] = args[1];
650
                gen_args[2] = args[2];
651
                gen_args[3] = args[3];
652
                gen_args += 4;
653
            }
654
            args += 4;
655
            break;
656
        CASE_OP_32_64(movcond):
657
            if (temps[args[1]].state == TCG_TEMP_CONST
658
                && temps[args[2]].state == TCG_TEMP_CONST) {
659
                tmp = do_constant_folding_cond(op, temps[args[1]].val,
660
                                               temps[args[2]].val, args[5]);
661
                if (temps_are_copies(args[0], args[4-tmp])) {
662
                    gen_opc_buf[op_index] = INDEX_op_nop;
663
                } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
664
                    gen_opc_buf[op_index] = op_to_movi(op);
665
                    tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
666
                    gen_args += 2;
667
                } else {
668
                    gen_opc_buf[op_index] = op_to_mov(op);
669
                    tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
670
                    gen_args += 2;
671
                }
672
            } else {
673
                reset_temp(args[0]);
674
                gen_args[0] = args[0];
675
                gen_args[1] = args[1];
676
                gen_args[2] = args[2];
677
                gen_args[3] = args[3];
678
                gen_args[4] = args[4];
679
                gen_args[5] = args[5];
680
                gen_args += 6;
681
            }
682
            args += 6;
683
            break;
684
        case INDEX_op_call:
685
            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
686
            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
687
                for (i = 0; i < nb_globals; i++) {
688
                    reset_temp(i);
689
                }
690
            }
691
            for (i = 0; i < (args[0] >> 16); i++) {
692
                reset_temp(args[i + 1]);
693
            }
694
            i = nb_call_args + 3;
695
            while (i) {
696
                *gen_args = *args;
697
                args++;
698
                gen_args++;
699
                i--;
700
            }
701
            break;
702
        default:
703
            /* Default case: we do know nothing about operation so no
704
               propagation is done.  We trash everything if the operation
705
               is the end of a basic block, otherwise we only trash the
706
               output args.  */
707
            if (def->flags & TCG_OPF_BB_END) {
708
                memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
709
            } else {
710
                for (i = 0; i < def->nb_oargs; i++) {
711
                    reset_temp(args[i]);
712
                }
713
            }
714
            for (i = 0; i < def->nb_args; i++) {
715
                gen_args[i] = args[i];
716
            }
717
            args += def->nb_args;
718
            gen_args += def->nb_args;
719
            break;
720
        }
721
    }
722

    
723
    return gen_args;
724
}
725

    
726
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
727
        TCGArg *args, TCGOpDef *tcg_op_defs)
728
{
729
    TCGArg *res;
730
    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
731
    return res;
732
}