Statistics
| Branch: | Revision:

root / tcg / optimize.c @ 1ff8c541

History | View | Annotate | Download (22.6 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 (op == INDEX_op_call) {
382
            int nb_oargs = args[0] >> 16;
383
            int nb_iargs = args[0] & 0xffff;
384
            for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
385
                if (temps[args[i]].state == TCG_TEMP_COPY) {
386
                    args[i] = find_better_copy(s, args[i]);
387
                }
388
            }
389
        } else {
390
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
391
                if (temps[args[i]].state == TCG_TEMP_COPY) {
392
                    args[i] = find_better_copy(s, args[i]);
393
                }
394
            }
395
        }
396

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

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

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

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

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

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

    
730
    return gen_args;
731
}
732

    
733
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
734
        TCGArg *args, TCGOpDef *tcg_op_defs)
735
{
736
    TCGArg *res;
737
    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
738
    return res;
739
}