Statistics
| Branch: | Revision:

root / tcg / optimize.c @ 1bfd07bd

History | View | Annotate | Download (19.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
#if TCG_TARGET_REG_BITS == 64
35
#define CASE_OP_32_64(x)                        \
36
        glue(glue(case INDEX_op_, x), _i32):    \
37
        glue(glue(case INDEX_op_, x), _i64)
38
#else
39
#define CASE_OP_32_64(x)                        \
40
        glue(glue(case INDEX_op_, x), _i32)
41
#endif
42

    
43
typedef enum {
44
    TCG_TEMP_UNDEF = 0,
45
    TCG_TEMP_CONST,
46
    TCG_TEMP_COPY,
47
    TCG_TEMP_HAS_COPY,
48
    TCG_TEMP_ANY
49
} tcg_temp_state;
50

    
51
struct tcg_temp_info {
52
    tcg_temp_state state;
53
    uint16_t prev_copy;
54
    uint16_t next_copy;
55
    tcg_target_ulong val;
56
};
57

    
58
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
59

    
60
/* Reset TEMP's state to TCG_TEMP_ANY.  If TEMP was a representative of some
61
   class of equivalent temp's, a new representative should be chosen in this
62
   class. */
63
static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
64
{
65
    int i;
66
    TCGArg new_base = (TCGArg)-1;
67
    if (temps[temp].state == TCG_TEMP_HAS_COPY) {
68
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
69
            if (i >= nb_globals) {
70
                temps[i].state = TCG_TEMP_HAS_COPY;
71
                new_base = i;
72
                break;
73
            }
74
        }
75
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
76
            if (new_base == (TCGArg)-1) {
77
                temps[i].state = TCG_TEMP_ANY;
78
            } else {
79
                temps[i].val = new_base;
80
            }
81
        }
82
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
83
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
84
    } else if (temps[temp].state == TCG_TEMP_COPY) {
85
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
86
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
87
        new_base = temps[temp].val;
88
    }
89
    temps[temp].state = TCG_TEMP_ANY;
90
    if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
91
        temps[new_base].state = TCG_TEMP_ANY;
92
    }
93
}
94

    
95
static int op_bits(int op)
96
{
97
    switch (op) {
98
    case INDEX_op_mov_i32:
99
    case INDEX_op_add_i32:
100
    case INDEX_op_sub_i32:
101
    case INDEX_op_mul_i32:
102
    case INDEX_op_and_i32:
103
    case INDEX_op_or_i32:
104
    case INDEX_op_xor_i32:
105
    case INDEX_op_shl_i32:
106
    case INDEX_op_shr_i32:
107
    case INDEX_op_sar_i32:
108
#ifdef TCG_TARGET_HAS_rot_i32
109
    case INDEX_op_rotl_i32:
110
    case INDEX_op_rotr_i32:
111
#endif
112
#ifdef TCG_TARGET_HAS_not_i32
113
    case INDEX_op_not_i32:
114
#endif
115
#ifdef TCG_TARGET_HAS_ext8s_i32
116
    case INDEX_op_ext8s_i32:
117
#endif
118
#ifdef TCG_TARGET_HAS_ext16s_i32
119
    case INDEX_op_ext16s_i32:
120
#endif
121
#ifdef TCG_TARGET_HAS_ext8u_i32
122
    case INDEX_op_ext8u_i32:
123
#endif
124
#ifdef TCG_TARGET_HAS_ext16u_i32
125
    case INDEX_op_ext16u_i32:
126
#endif
127
        return 32;
128
#if TCG_TARGET_REG_BITS == 64
129
    case INDEX_op_mov_i64:
130
    case INDEX_op_add_i64:
131
    case INDEX_op_sub_i64:
132
    case INDEX_op_mul_i64:
133
    case INDEX_op_and_i64:
134
    case INDEX_op_or_i64:
135
    case INDEX_op_xor_i64:
136
    case INDEX_op_shl_i64:
137
    case INDEX_op_shr_i64:
138
    case INDEX_op_sar_i64:
139
#ifdef TCG_TARGET_HAS_rot_i64
140
    case INDEX_op_rotl_i64:
141
    case INDEX_op_rotr_i64:
142
#endif
143
#ifdef TCG_TARGET_HAS_not_i64
144
    case INDEX_op_not_i64:
145
#endif
146
#ifdef TCG_TARGET_HAS_ext8s_i64
147
    case INDEX_op_ext8s_i64:
148
#endif
149
#ifdef TCG_TARGET_HAS_ext16s_i64
150
    case INDEX_op_ext16s_i64:
151
#endif
152
#ifdef TCG_TARGET_HAS_ext32s_i64
153
    case INDEX_op_ext32s_i64:
154
#endif
155
#ifdef TCG_TARGET_HAS_ext8u_i64
156
    case INDEX_op_ext8u_i64:
157
#endif
158
#ifdef TCG_TARGET_HAS_ext16u_i64
159
    case INDEX_op_ext16u_i64:
160
#endif
161
#ifdef TCG_TARGET_HAS_ext32u_i64
162
    case INDEX_op_ext32u_i64:
163
#endif
164
        return 64;
165
#endif
166
    default:
167
        fprintf(stderr, "Unrecognized operation %d in op_bits.\n", op);
168
        tcg_abort();
169
    }
170
}
171

    
172
static int op_to_movi(int op)
173
{
174
    switch (op_bits(op)) {
175
    case 32:
176
        return INDEX_op_movi_i32;
177
#if TCG_TARGET_REG_BITS == 64
178
    case 64:
179
        return INDEX_op_movi_i64;
180
#endif
181
    default:
182
        fprintf(stderr, "op_to_movi: unexpected return value of "
183
                "function op_bits.\n");
184
        tcg_abort();
185
    }
186
}
187

    
188
static void tcg_opt_gen_mov(TCGArg *gen_args, TCGArg dst, TCGArg src,
189
                            int nb_temps, int nb_globals)
190
{
191
        reset_temp(dst, nb_temps, nb_globals);
192
        assert(temps[src].state != TCG_TEMP_COPY);
193
        if (src >= nb_globals) {
194
            assert(temps[src].state != TCG_TEMP_CONST);
195
            if (temps[src].state != TCG_TEMP_HAS_COPY) {
196
                temps[src].state = TCG_TEMP_HAS_COPY;
197
                temps[src].next_copy = src;
198
                temps[src].prev_copy = src;
199
            }
200
            temps[dst].state = TCG_TEMP_COPY;
201
            temps[dst].val = src;
202
            temps[dst].next_copy = temps[src].next_copy;
203
            temps[dst].prev_copy = src;
204
            temps[temps[dst].next_copy].prev_copy = dst;
205
            temps[src].next_copy = dst;
206
        }
207
        gen_args[0] = dst;
208
        gen_args[1] = src;
209
}
210

    
211
static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
212
                             int nb_temps, int nb_globals)
213
{
214
        reset_temp(dst, nb_temps, nb_globals);
215
        temps[dst].state = TCG_TEMP_CONST;
216
        temps[dst].val = val;
217
        gen_args[0] = dst;
218
        gen_args[1] = val;
219
}
220

    
221
static int op_to_mov(int op)
222
{
223
    switch (op_bits(op)) {
224
    case 32:
225
        return INDEX_op_mov_i32;
226
#if TCG_TARGET_REG_BITS == 64
227
    case 64:
228
        return INDEX_op_mov_i64;
229
#endif
230
    default:
231
        fprintf(stderr, "op_to_mov: unexpected return value of "
232
                "function op_bits.\n");
233
        tcg_abort();
234
    }
235
}
236

    
237
static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y)
238
{
239
    switch (op) {
240
    CASE_OP_32_64(add):
241
        return x + y;
242

    
243
    CASE_OP_32_64(sub):
244
        return x - y;
245

    
246
    CASE_OP_32_64(mul):
247
        return x * y;
248

    
249
    CASE_OP_32_64(and):
250
        return x & y;
251

    
252
    CASE_OP_32_64(or):
253
        return x | y;
254

    
255
    CASE_OP_32_64(xor):
256
        return x ^ y;
257

    
258
    case INDEX_op_shl_i32:
259
        return (uint32_t)x << (uint32_t)y;
260

    
261
#if TCG_TARGET_REG_BITS == 64
262
    case INDEX_op_shl_i64:
263
        return (uint64_t)x << (uint64_t)y;
264
#endif
265

    
266
    case INDEX_op_shr_i32:
267
        return (uint32_t)x >> (uint32_t)y;
268

    
269
#if TCG_TARGET_REG_BITS == 64
270
    case INDEX_op_shr_i64:
271
        return (uint64_t)x >> (uint64_t)y;
272
#endif
273

    
274
    case INDEX_op_sar_i32:
275
        return (int32_t)x >> (int32_t)y;
276

    
277
#if TCG_TARGET_REG_BITS == 64
278
    case INDEX_op_sar_i64:
279
        return (int64_t)x >> (int64_t)y;
280
#endif
281

    
282
#ifdef TCG_TARGET_HAS_rot_i32
283
    case INDEX_op_rotr_i32:
284
#if TCG_TARGET_REG_BITS == 64
285
        x &= 0xffffffff;
286
        y &= 0xffffffff;
287
#endif
288
        x = (x << (32 - y)) | (x >> y);
289
        return x;
290
#endif
291

    
292
#ifdef TCG_TARGET_HAS_rot_i64
293
#if TCG_TARGET_REG_BITS == 64
294
    case INDEX_op_rotr_i64:
295
        x = (x << (64 - y)) | (x >> y);
296
        return x;
297
#endif
298
#endif
299

    
300
#ifdef TCG_TARGET_HAS_rot_i32
301
    case INDEX_op_rotl_i32:
302
#if TCG_TARGET_REG_BITS == 64
303
        x &= 0xffffffff;
304
        y &= 0xffffffff;
305
#endif
306
        x = (x << y) | (x >> (32 - y));
307
        return x;
308
#endif
309

    
310
#ifdef TCG_TARGET_HAS_rot_i64
311
#if TCG_TARGET_REG_BITS == 64
312
    case INDEX_op_rotl_i64:
313
        x = (x << y) | (x >> (64 - y));
314
        return x;
315
#endif
316
#endif
317

    
318
#if defined(TCG_TARGET_HAS_not_i32) || defined(TCG_TARGET_HAS_not_i64)
319
#ifdef TCG_TARGET_HAS_not_i32
320
    case INDEX_op_not_i32:
321
#else
322
    case INDEX_op_not_i64:
323
#endif
324
        return ~x;
325
#endif
326

    
327
#if defined(TCG_TARGET_HAS_ext8s_i32) || defined(TCG_TARGET_HAS_ext8s_i64)
328
#ifdef TCG_TARGET_HAS_ext8s_i32
329
    case INDEX_op_ext8s_i32:
330
#else
331
    case INDEX_op_ext8s_i64:
332
#endif
333
        return (int8_t)x;
334
#endif
335

    
336
#if defined(TCG_TARGET_HAS_ext16s_i32) || defined(TCG_TARGET_HAS_ext16s_i64)
337
#ifdef TCG_TARGET_HAS_ext16s_i32
338
    case INDEX_op_ext16s_i32:
339
#else
340
    case INDEX_op_ext16s_i64:
341
#endif
342
        return (int16_t)x;
343
#endif
344

    
345
#if defined(TCG_TARGET_HAS_ext8u_i32) || defined(TCG_TARGET_HAS_ext8u_i64)
346
#ifdef TCG_TARGET_HAS_ext8u_i32
347
    case INDEX_op_ext8u_i32:
348
#else
349
    case INDEX_op_ext8u_i64:
350
#endif
351
        return (uint8_t)x;
352
#endif
353

    
354
#if defined(TCG_TARGET_HAS_ext16u_i32) || defined(TCG_TARGET_HAS_ext16u_i64)
355
#ifdef TCG_TARGET_HAS_ext16u_i32
356
    case INDEX_op_ext16u_i32:
357
#else
358
    case INDEX_op_ext16u_i64:
359
#endif
360
        return (uint16_t)x;
361
#endif
362

    
363
#if TCG_TARGET_REG_BITS == 64
364
#ifdef TCG_TARGET_HAS_ext32s_i32
365
    case INDEX_op_ext32s_i64:
366
        return (int32_t)x;
367
#endif
368

    
369
#ifdef TCG_TARGET_HAS_ext32u_i32
370
    case INDEX_op_ext32u_i64:
371
        return (uint32_t)x;
372
#endif
373
#endif
374

    
375
    default:
376
        fprintf(stderr,
377
                "Unrecognized operation %d in do_constant_folding.\n", op);
378
        tcg_abort();
379
    }
380
}
381

    
382
static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y)
383
{
384
    TCGArg res = do_constant_folding_2(op, x, y);
385
#if TCG_TARGET_REG_BITS == 64
386
    if (op_bits(op) == 32) {
387
        res &= 0xffffffff;
388
    }
389
#endif
390
    return res;
391
}
392

    
393
/* Propagate constants and copies, fold constant expressions. */
394
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
395
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
396
{
397
    int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
398
    const TCGOpDef *def;
399
    TCGArg *gen_args;
400
    TCGArg tmp;
401
    /* Array VALS has an element for each temp.
402
       If this temp holds a constant then its value is kept in VALS' element.
403
       If this temp is a copy of other ones then this equivalence class'
404
       representative is kept in VALS' element.
405
       If this temp is neither copy nor constant then corresponding VALS'
406
       element is unused. */
407

    
408
    nb_temps = s->nb_temps;
409
    nb_globals = s->nb_globals;
410
    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
411

    
412
    nb_ops = tcg_opc_ptr - gen_opc_buf;
413
    gen_args = args;
414
    for (op_index = 0; op_index < nb_ops; op_index++) {
415
        op = gen_opc_buf[op_index];
416
        def = &tcg_op_defs[op];
417
        /* Do copy propagation */
418
        if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
419
            assert(op != INDEX_op_call);
420
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
421
                if (temps[args[i]].state == TCG_TEMP_COPY) {
422
                    args[i] = temps[args[i]].val;
423
                }
424
            }
425
        }
426

    
427
        /* For commutative operations make constant second argument */
428
        switch (op) {
429
        CASE_OP_32_64(add):
430
        CASE_OP_32_64(mul):
431
        CASE_OP_32_64(and):
432
        CASE_OP_32_64(or):
433
        CASE_OP_32_64(xor):
434
            if (temps[args[1]].state == TCG_TEMP_CONST) {
435
                tmp = args[1];
436
                args[1] = args[2];
437
                args[2] = tmp;
438
            }
439
            break;
440
        default:
441
            break;
442
        }
443

    
444
        /* Simplify expression if possible. */
445
        switch (op) {
446
        CASE_OP_32_64(add):
447
        CASE_OP_32_64(sub):
448
        CASE_OP_32_64(shl):
449
        CASE_OP_32_64(shr):
450
        CASE_OP_32_64(sar):
451
#ifdef TCG_TARGET_HAS_rot_i32
452
        case INDEX_op_rotl_i32:
453
        case INDEX_op_rotr_i32:
454
#endif
455
#ifdef TCG_TARGET_HAS_rot_i64
456
        case INDEX_op_rotl_i64:
457
        case INDEX_op_rotr_i64:
458
#endif
459
            if (temps[args[1]].state == TCG_TEMP_CONST) {
460
                /* Proceed with possible constant folding. */
461
                break;
462
            }
463
            if (temps[args[2]].state == TCG_TEMP_CONST
464
                && temps[args[2]].val == 0) {
465
                if ((temps[args[0]].state == TCG_TEMP_COPY
466
                    && temps[args[0]].val == args[1])
467
                    || args[0] == args[1]) {
468
                    args += 3;
469
                    gen_opc_buf[op_index] = INDEX_op_nop;
470
                } else {
471
                    gen_opc_buf[op_index] = op_to_mov(op);
472
                    tcg_opt_gen_mov(gen_args, args[0], args[1],
473
                                    nb_temps, nb_globals);
474
                    gen_args += 2;
475
                    args += 3;
476
                }
477
                continue;
478
            }
479
            break;
480
        CASE_OP_32_64(mul):
481
            if ((temps[args[2]].state == TCG_TEMP_CONST
482
                && temps[args[2]].val == 0)) {
483
                gen_opc_buf[op_index] = op_to_movi(op);
484
                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
485
                args += 3;
486
                gen_args += 2;
487
                continue;
488
            }
489
            break;
490
        CASE_OP_32_64(or):
491
        CASE_OP_32_64(and):
492
            if (args[1] == args[2]) {
493
                if (args[1] == args[0]) {
494
                    args += 3;
495
                    gen_opc_buf[op_index] = INDEX_op_nop;
496
                } else {
497
                    gen_opc_buf[op_index] = op_to_mov(op);
498
                    tcg_opt_gen_mov(gen_args, args[0], args[1], nb_temps,
499
                                    nb_globals);
500
                    gen_args += 2;
501
                    args += 3;
502
                }
503
                continue;
504
            }
505
            break;
506
        }
507

    
508
        /* Propagate constants through copy operations and do constant
509
           folding.  Constants will be substituted to arguments by register
510
           allocator where needed and possible.  Also detect copies. */
511
        switch (op) {
512
        CASE_OP_32_64(mov):
513
            if ((temps[args[1]].state == TCG_TEMP_COPY
514
                && temps[args[1]].val == args[0])
515
                || args[0] == args[1]) {
516
                args += 2;
517
                gen_opc_buf[op_index] = INDEX_op_nop;
518
                break;
519
            }
520
            if (temps[args[1]].state != TCG_TEMP_CONST) {
521
                tcg_opt_gen_mov(gen_args, args[0], args[1],
522
                                nb_temps, nb_globals);
523
                gen_args += 2;
524
                args += 2;
525
                break;
526
            }
527
            /* Source argument is constant.  Rewrite the operation and
528
               let movi case handle it. */
529
            op = op_to_movi(op);
530
            gen_opc_buf[op_index] = op;
531
            args[1] = temps[args[1]].val;
532
            /* fallthrough */
533
        CASE_OP_32_64(movi):
534
            tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
535
            gen_args += 2;
536
            args += 2;
537
            break;
538
        CASE_OP_32_64(not):
539
#ifdef TCG_TARGET_HAS_ext8s_i32
540
        case INDEX_op_ext8s_i32:
541
#endif
542
#ifdef TCG_TARGET_HAS_ext8s_i64
543
        case INDEX_op_ext8s_i64:
544
#endif
545
#ifdef TCG_TARGET_HAS_ext16s_i32
546
        case INDEX_op_ext16s_i32:
547
#endif
548
#ifdef TCG_TARGET_HAS_ext16s_i64
549
        case INDEX_op_ext16s_i64:
550
#endif
551
#ifdef TCG_TARGET_HAS_ext8u_i32
552
        case INDEX_op_ext8u_i32:
553
#endif
554
#ifdef TCG_TARGET_HAS_ext8u_i64
555
        case INDEX_op_ext8u_i64:
556
#endif
557
#ifdef TCG_TARGET_HAS_ext16u_i32
558
        case INDEX_op_ext16u_i32:
559
#endif
560
#ifdef TCG_TARGET_HAS_ext16u_i64
561
        case INDEX_op_ext16u_i64:
562
#endif
563
#if TCG_TARGET_REG_BITS == 64
564
        case INDEX_op_ext32s_i64:
565
        case INDEX_op_ext32u_i64:
566
#endif
567
            if (temps[args[1]].state == TCG_TEMP_CONST) {
568
                gen_opc_buf[op_index] = op_to_movi(op);
569
                tmp = do_constant_folding(op, temps[args[1]].val, 0);
570
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
571
                gen_args += 2;
572
                args += 2;
573
                break;
574
            } else {
575
                reset_temp(args[0], nb_temps, nb_globals);
576
                gen_args[0] = args[0];
577
                gen_args[1] = args[1];
578
                gen_args += 2;
579
                args += 2;
580
                break;
581
            }
582
        CASE_OP_32_64(add):
583
        CASE_OP_32_64(sub):
584
        CASE_OP_32_64(mul):
585
        CASE_OP_32_64(or):
586
        CASE_OP_32_64(and):
587
        CASE_OP_32_64(xor):
588
        CASE_OP_32_64(shl):
589
        CASE_OP_32_64(shr):
590
        CASE_OP_32_64(sar):
591
#ifdef TCG_TARGET_HAS_rot_i32
592
        case INDEX_op_rotl_i32:
593
        case INDEX_op_rotr_i32:
594
#endif
595
#ifdef TCG_TARGET_HAS_rot_i64
596
        case INDEX_op_rotl_i64:
597
        case INDEX_op_rotr_i64:
598
#endif
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, nb_temps, nb_globals);
605
                gen_args += 2;
606
                args += 3;
607
                break;
608
            } else {
609
                reset_temp(args[0], nb_temps, nb_globals);
610
                gen_args[0] = args[0];
611
                gen_args[1] = args[1];
612
                gen_args[2] = args[2];
613
                gen_args += 3;
614
                args += 3;
615
                break;
616
            }
617
        case INDEX_op_call:
618
            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
619
            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
620
                for (i = 0; i < nb_globals; i++) {
621
                    reset_temp(i, nb_temps, nb_globals);
622
                }
623
            }
624
            for (i = 0; i < (args[0] >> 16); i++) {
625
                reset_temp(args[i + 1], nb_temps, nb_globals);
626
            }
627
            i = nb_call_args + 3;
628
            while (i) {
629
                *gen_args = *args;
630
                args++;
631
                gen_args++;
632
                i--;
633
            }
634
            break;
635
        case INDEX_op_set_label:
636
        case INDEX_op_jmp:
637
        case INDEX_op_br:
638
        CASE_OP_32_64(brcond):
639
            memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
640
            for (i = 0; i < def->nb_args; i++) {
641
                *gen_args = *args;
642
                args++;
643
                gen_args++;
644
            }
645
            break;
646
        default:
647
            /* Default case: we do know nothing about operation so no
648
               propagation is done.  We only trash output args.  */
649
            for (i = 0; i < def->nb_oargs; i++) {
650
                reset_temp(args[i], nb_temps, nb_globals);
651
            }
652
            for (i = 0; i < def->nb_args; i++) {
653
                gen_args[i] = args[i];
654
            }
655
            args += def->nb_args;
656
            gen_args += def->nb_args;
657
            break;
658
        }
659
    }
660

    
661
    return gen_args;
662
}
663

    
664
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
665
        TCGArg *args, TCGOpDef *tcg_op_defs)
666
{
667
    TCGArg *res;
668
    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
669
    return res;
670
}