Statistics
| Branch: | Revision:

root / tcg / optimize.c @ 9f4facbc

History | View | Annotate | Download (16.3 kB)

1 8f2e8c07 Kirill Batuzov
/*
2 8f2e8c07 Kirill Batuzov
 * Optimizations for Tiny Code Generator for QEMU
3 8f2e8c07 Kirill Batuzov
 *
4 8f2e8c07 Kirill Batuzov
 * Copyright (c) 2010 Samsung Electronics.
5 8f2e8c07 Kirill Batuzov
 * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
6 8f2e8c07 Kirill Batuzov
 *
7 8f2e8c07 Kirill Batuzov
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 8f2e8c07 Kirill Batuzov
 * of this software and associated documentation files (the "Software"), to deal
9 8f2e8c07 Kirill Batuzov
 * in the Software without restriction, including without limitation the rights
10 8f2e8c07 Kirill Batuzov
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 8f2e8c07 Kirill Batuzov
 * copies of the Software, and to permit persons to whom the Software is
12 8f2e8c07 Kirill Batuzov
 * furnished to do so, subject to the following conditions:
13 8f2e8c07 Kirill Batuzov
 *
14 8f2e8c07 Kirill Batuzov
 * The above copyright notice and this permission notice shall be included in
15 8f2e8c07 Kirill Batuzov
 * all copies or substantial portions of the Software.
16 8f2e8c07 Kirill Batuzov
 *
17 8f2e8c07 Kirill Batuzov
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 8f2e8c07 Kirill Batuzov
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 8f2e8c07 Kirill Batuzov
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 8f2e8c07 Kirill Batuzov
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 8f2e8c07 Kirill Batuzov
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 8f2e8c07 Kirill Batuzov
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 8f2e8c07 Kirill Batuzov
 * THE SOFTWARE.
24 8f2e8c07 Kirill Batuzov
 */
25 8f2e8c07 Kirill Batuzov
26 8f2e8c07 Kirill Batuzov
#include "config.h"
27 8f2e8c07 Kirill Batuzov
28 8f2e8c07 Kirill Batuzov
#include <stdlib.h>
29 8f2e8c07 Kirill Batuzov
#include <stdio.h>
30 8f2e8c07 Kirill Batuzov
31 8f2e8c07 Kirill Batuzov
#include "qemu-common.h"
32 8f2e8c07 Kirill Batuzov
#include "tcg-op.h"
33 8f2e8c07 Kirill Batuzov
34 8f2e8c07 Kirill Batuzov
#define CASE_OP_32_64(x)                        \
35 8f2e8c07 Kirill Batuzov
        glue(glue(case INDEX_op_, x), _i32):    \
36 8f2e8c07 Kirill Batuzov
        glue(glue(case INDEX_op_, x), _i64)
37 8f2e8c07 Kirill Batuzov
38 22613af4 Kirill Batuzov
typedef enum {
39 22613af4 Kirill Batuzov
    TCG_TEMP_UNDEF = 0,
40 22613af4 Kirill Batuzov
    TCG_TEMP_CONST,
41 22613af4 Kirill Batuzov
    TCG_TEMP_COPY,
42 22613af4 Kirill Batuzov
    TCG_TEMP_HAS_COPY,
43 22613af4 Kirill Batuzov
    TCG_TEMP_ANY
44 22613af4 Kirill Batuzov
} tcg_temp_state;
45 22613af4 Kirill Batuzov
46 22613af4 Kirill Batuzov
struct tcg_temp_info {
47 22613af4 Kirill Batuzov
    tcg_temp_state state;
48 22613af4 Kirill Batuzov
    uint16_t prev_copy;
49 22613af4 Kirill Batuzov
    uint16_t next_copy;
50 22613af4 Kirill Batuzov
    tcg_target_ulong val;
51 22613af4 Kirill Batuzov
};
52 22613af4 Kirill Batuzov
53 22613af4 Kirill Batuzov
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
54 22613af4 Kirill Batuzov
55 22613af4 Kirill Batuzov
/* Reset TEMP's state to TCG_TEMP_ANY.  If TEMP was a representative of some
56 22613af4 Kirill Batuzov
   class of equivalent temp's, a new representative should be chosen in this
57 22613af4 Kirill Batuzov
   class. */
58 22613af4 Kirill Batuzov
static void reset_temp(TCGArg temp, int nb_temps, int nb_globals)
59 22613af4 Kirill Batuzov
{
60 22613af4 Kirill Batuzov
    int i;
61 22613af4 Kirill Batuzov
    TCGArg new_base = (TCGArg)-1;
62 22613af4 Kirill Batuzov
    if (temps[temp].state == TCG_TEMP_HAS_COPY) {
63 22613af4 Kirill Batuzov
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
64 22613af4 Kirill Batuzov
            if (i >= nb_globals) {
65 22613af4 Kirill Batuzov
                temps[i].state = TCG_TEMP_HAS_COPY;
66 22613af4 Kirill Batuzov
                new_base = i;
67 22613af4 Kirill Batuzov
                break;
68 22613af4 Kirill Batuzov
            }
69 22613af4 Kirill Batuzov
        }
70 22613af4 Kirill Batuzov
        for (i = temps[temp].next_copy; i != temp; i = temps[i].next_copy) {
71 22613af4 Kirill Batuzov
            if (new_base == (TCGArg)-1) {
72 22613af4 Kirill Batuzov
                temps[i].state = TCG_TEMP_ANY;
73 22613af4 Kirill Batuzov
            } else {
74 22613af4 Kirill Batuzov
                temps[i].val = new_base;
75 22613af4 Kirill Batuzov
            }
76 22613af4 Kirill Batuzov
        }
77 22613af4 Kirill Batuzov
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
78 22613af4 Kirill Batuzov
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
79 22613af4 Kirill Batuzov
    } else if (temps[temp].state == TCG_TEMP_COPY) {
80 22613af4 Kirill Batuzov
        temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
81 22613af4 Kirill Batuzov
        temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
82 22613af4 Kirill Batuzov
        new_base = temps[temp].val;
83 22613af4 Kirill Batuzov
    }
84 22613af4 Kirill Batuzov
    temps[temp].state = TCG_TEMP_ANY;
85 22613af4 Kirill Batuzov
    if (new_base != (TCGArg)-1 && temps[new_base].next_copy == new_base) {
86 22613af4 Kirill Batuzov
        temps[new_base].state = TCG_TEMP_ANY;
87 22613af4 Kirill Batuzov
    }
88 22613af4 Kirill Batuzov
}
89 22613af4 Kirill Batuzov
90 fe0de7aa Blue Swirl
static int op_bits(TCGOpcode op)
91 22613af4 Kirill Batuzov
{
92 8399ad59 Richard Henderson
    const TCGOpDef *def = &tcg_op_defs[op];
93 8399ad59 Richard Henderson
    return def->flags & TCG_OPF_64BIT ? 64 : 32;
94 22613af4 Kirill Batuzov
}
95 22613af4 Kirill Batuzov
96 fe0de7aa Blue Swirl
static TCGOpcode op_to_movi(TCGOpcode op)
97 22613af4 Kirill Batuzov
{
98 22613af4 Kirill Batuzov
    switch (op_bits(op)) {
99 22613af4 Kirill Batuzov
    case 32:
100 22613af4 Kirill Batuzov
        return INDEX_op_movi_i32;
101 22613af4 Kirill Batuzov
    case 64:
102 22613af4 Kirill Batuzov
        return INDEX_op_movi_i64;
103 22613af4 Kirill Batuzov
    default:
104 22613af4 Kirill Batuzov
        fprintf(stderr, "op_to_movi: unexpected return value of "
105 22613af4 Kirill Batuzov
                "function op_bits.\n");
106 22613af4 Kirill Batuzov
        tcg_abort();
107 22613af4 Kirill Batuzov
    }
108 22613af4 Kirill Batuzov
}
109 22613af4 Kirill Batuzov
110 e31b0a7c Blue Swirl
static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args, TCGArg dst,
111 e31b0a7c Blue Swirl
                            TCGArg src, int nb_temps, int nb_globals)
112 22613af4 Kirill Batuzov
{
113 22613af4 Kirill Batuzov
        reset_temp(dst, nb_temps, nb_globals);
114 22613af4 Kirill Batuzov
        assert(temps[src].state != TCG_TEMP_COPY);
115 e31b0a7c Blue Swirl
        /* Don't try to copy if one of temps is a global or either one
116 e31b0a7c Blue Swirl
           is local and another is register */
117 e31b0a7c Blue Swirl
        if (src >= nb_globals && dst >= nb_globals &&
118 e31b0a7c Blue Swirl
            tcg_arg_is_local(s, src) == tcg_arg_is_local(s, dst)) {
119 22613af4 Kirill Batuzov
            assert(temps[src].state != TCG_TEMP_CONST);
120 22613af4 Kirill Batuzov
            if (temps[src].state != TCG_TEMP_HAS_COPY) {
121 22613af4 Kirill Batuzov
                temps[src].state = TCG_TEMP_HAS_COPY;
122 22613af4 Kirill Batuzov
                temps[src].next_copy = src;
123 22613af4 Kirill Batuzov
                temps[src].prev_copy = src;
124 22613af4 Kirill Batuzov
            }
125 22613af4 Kirill Batuzov
            temps[dst].state = TCG_TEMP_COPY;
126 22613af4 Kirill Batuzov
            temps[dst].val = src;
127 22613af4 Kirill Batuzov
            temps[dst].next_copy = temps[src].next_copy;
128 22613af4 Kirill Batuzov
            temps[dst].prev_copy = src;
129 22613af4 Kirill Batuzov
            temps[temps[dst].next_copy].prev_copy = dst;
130 22613af4 Kirill Batuzov
            temps[src].next_copy = dst;
131 22613af4 Kirill Batuzov
        }
132 22613af4 Kirill Batuzov
        gen_args[0] = dst;
133 22613af4 Kirill Batuzov
        gen_args[1] = src;
134 22613af4 Kirill Batuzov
}
135 22613af4 Kirill Batuzov
136 22613af4 Kirill Batuzov
static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val,
137 22613af4 Kirill Batuzov
                             int nb_temps, int nb_globals)
138 22613af4 Kirill Batuzov
{
139 22613af4 Kirill Batuzov
        reset_temp(dst, nb_temps, nb_globals);
140 22613af4 Kirill Batuzov
        temps[dst].state = TCG_TEMP_CONST;
141 22613af4 Kirill Batuzov
        temps[dst].val = val;
142 22613af4 Kirill Batuzov
        gen_args[0] = dst;
143 22613af4 Kirill Batuzov
        gen_args[1] = val;
144 22613af4 Kirill Batuzov
}
145 22613af4 Kirill Batuzov
146 fe0de7aa Blue Swirl
static TCGOpcode op_to_mov(TCGOpcode op)
147 53108fb5 Kirill Batuzov
{
148 53108fb5 Kirill Batuzov
    switch (op_bits(op)) {
149 53108fb5 Kirill Batuzov
    case 32:
150 53108fb5 Kirill Batuzov
        return INDEX_op_mov_i32;
151 53108fb5 Kirill Batuzov
    case 64:
152 53108fb5 Kirill Batuzov
        return INDEX_op_mov_i64;
153 53108fb5 Kirill Batuzov
    default:
154 53108fb5 Kirill Batuzov
        fprintf(stderr, "op_to_mov: unexpected return value of "
155 53108fb5 Kirill Batuzov
                "function op_bits.\n");
156 53108fb5 Kirill Batuzov
        tcg_abort();
157 53108fb5 Kirill Batuzov
    }
158 53108fb5 Kirill Batuzov
}
159 53108fb5 Kirill Batuzov
160 fe0de7aa Blue Swirl
static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
161 53108fb5 Kirill Batuzov
{
162 53108fb5 Kirill Batuzov
    switch (op) {
163 53108fb5 Kirill Batuzov
    CASE_OP_32_64(add):
164 53108fb5 Kirill Batuzov
        return x + y;
165 53108fb5 Kirill Batuzov
166 53108fb5 Kirill Batuzov
    CASE_OP_32_64(sub):
167 53108fb5 Kirill Batuzov
        return x - y;
168 53108fb5 Kirill Batuzov
169 53108fb5 Kirill Batuzov
    CASE_OP_32_64(mul):
170 53108fb5 Kirill Batuzov
        return x * y;
171 53108fb5 Kirill Batuzov
172 9a81090b Kirill Batuzov
    CASE_OP_32_64(and):
173 9a81090b Kirill Batuzov
        return x & y;
174 9a81090b Kirill Batuzov
175 9a81090b Kirill Batuzov
    CASE_OP_32_64(or):
176 9a81090b Kirill Batuzov
        return x | y;
177 9a81090b Kirill Batuzov
178 9a81090b Kirill Batuzov
    CASE_OP_32_64(xor):
179 9a81090b Kirill Batuzov
        return x ^ y;
180 9a81090b Kirill Batuzov
181 55c0975c Kirill Batuzov
    case INDEX_op_shl_i32:
182 55c0975c Kirill Batuzov
        return (uint32_t)x << (uint32_t)y;
183 55c0975c Kirill Batuzov
184 55c0975c Kirill Batuzov
    case INDEX_op_shl_i64:
185 55c0975c Kirill Batuzov
        return (uint64_t)x << (uint64_t)y;
186 55c0975c Kirill Batuzov
187 55c0975c Kirill Batuzov
    case INDEX_op_shr_i32:
188 55c0975c Kirill Batuzov
        return (uint32_t)x >> (uint32_t)y;
189 55c0975c Kirill Batuzov
190 55c0975c Kirill Batuzov
    case INDEX_op_shr_i64:
191 55c0975c Kirill Batuzov
        return (uint64_t)x >> (uint64_t)y;
192 55c0975c Kirill Batuzov
193 55c0975c Kirill Batuzov
    case INDEX_op_sar_i32:
194 55c0975c Kirill Batuzov
        return (int32_t)x >> (int32_t)y;
195 55c0975c Kirill Batuzov
196 55c0975c Kirill Batuzov
    case INDEX_op_sar_i64:
197 55c0975c Kirill Batuzov
        return (int64_t)x >> (int64_t)y;
198 55c0975c Kirill Batuzov
199 55c0975c Kirill Batuzov
    case INDEX_op_rotr_i32:
200 25c4d9cc Richard Henderson
        x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y);
201 55c0975c Kirill Batuzov
        return x;
202 55c0975c Kirill Batuzov
203 55c0975c Kirill Batuzov
    case INDEX_op_rotr_i64:
204 25c4d9cc Richard Henderson
        x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y);
205 55c0975c Kirill Batuzov
        return x;
206 55c0975c Kirill Batuzov
207 55c0975c Kirill Batuzov
    case INDEX_op_rotl_i32:
208 25c4d9cc Richard Henderson
        x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y));
209 55c0975c Kirill Batuzov
        return x;
210 55c0975c Kirill Batuzov
211 55c0975c Kirill Batuzov
    case INDEX_op_rotl_i64:
212 25c4d9cc Richard Henderson
        x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y));
213 55c0975c Kirill Batuzov
        return x;
214 25c4d9cc Richard Henderson
215 25c4d9cc Richard Henderson
    CASE_OP_32_64(not):
216 a640f031 Kirill Batuzov
        return ~x;
217 25c4d9cc Richard Henderson
218 cb25c80a Richard Henderson
    CASE_OP_32_64(neg):
219 cb25c80a Richard Henderson
        return -x;
220 cb25c80a Richard Henderson
221 cb25c80a Richard Henderson
    CASE_OP_32_64(andc):
222 cb25c80a Richard Henderson
        return x & ~y;
223 cb25c80a Richard Henderson
224 cb25c80a Richard Henderson
    CASE_OP_32_64(orc):
225 cb25c80a Richard Henderson
        return x | ~y;
226 cb25c80a Richard Henderson
227 cb25c80a Richard Henderson
    CASE_OP_32_64(eqv):
228 cb25c80a Richard Henderson
        return ~(x ^ y);
229 cb25c80a Richard Henderson
230 cb25c80a Richard Henderson
    CASE_OP_32_64(nand):
231 cb25c80a Richard Henderson
        return ~(x & y);
232 cb25c80a Richard Henderson
233 cb25c80a Richard Henderson
    CASE_OP_32_64(nor):
234 cb25c80a Richard Henderson
        return ~(x | y);
235 cb25c80a Richard Henderson
236 25c4d9cc Richard Henderson
    CASE_OP_32_64(ext8s):
237 a640f031 Kirill Batuzov
        return (int8_t)x;
238 25c4d9cc Richard Henderson
239 25c4d9cc Richard Henderson
    CASE_OP_32_64(ext16s):
240 a640f031 Kirill Batuzov
        return (int16_t)x;
241 25c4d9cc Richard Henderson
242 25c4d9cc Richard Henderson
    CASE_OP_32_64(ext8u):
243 a640f031 Kirill Batuzov
        return (uint8_t)x;
244 25c4d9cc Richard Henderson
245 25c4d9cc Richard Henderson
    CASE_OP_32_64(ext16u):
246 a640f031 Kirill Batuzov
        return (uint16_t)x;
247 a640f031 Kirill Batuzov
248 a640f031 Kirill Batuzov
    case INDEX_op_ext32s_i64:
249 a640f031 Kirill Batuzov
        return (int32_t)x;
250 a640f031 Kirill Batuzov
251 a640f031 Kirill Batuzov
    case INDEX_op_ext32u_i64:
252 a640f031 Kirill Batuzov
        return (uint32_t)x;
253 a640f031 Kirill Batuzov
254 53108fb5 Kirill Batuzov
    default:
255 53108fb5 Kirill Batuzov
        fprintf(stderr,
256 53108fb5 Kirill Batuzov
                "Unrecognized operation %d in do_constant_folding.\n", op);
257 53108fb5 Kirill Batuzov
        tcg_abort();
258 53108fb5 Kirill Batuzov
    }
259 53108fb5 Kirill Batuzov
}
260 53108fb5 Kirill Batuzov
261 fe0de7aa Blue Swirl
static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
262 53108fb5 Kirill Batuzov
{
263 53108fb5 Kirill Batuzov
    TCGArg res = do_constant_folding_2(op, x, y);
264 53108fb5 Kirill Batuzov
    if (op_bits(op) == 32) {
265 53108fb5 Kirill Batuzov
        res &= 0xffffffff;
266 53108fb5 Kirill Batuzov
    }
267 53108fb5 Kirill Batuzov
    return res;
268 53108fb5 Kirill Batuzov
}
269 53108fb5 Kirill Batuzov
270 22613af4 Kirill Batuzov
/* Propagate constants and copies, fold constant expressions. */
271 8f2e8c07 Kirill Batuzov
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
272 8f2e8c07 Kirill Batuzov
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
273 8f2e8c07 Kirill Batuzov
{
274 fe0de7aa Blue Swirl
    int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
275 fe0de7aa Blue Swirl
    TCGOpcode op;
276 8f2e8c07 Kirill Batuzov
    const TCGOpDef *def;
277 8f2e8c07 Kirill Batuzov
    TCGArg *gen_args;
278 53108fb5 Kirill Batuzov
    TCGArg tmp;
279 22613af4 Kirill Batuzov
    /* Array VALS has an element for each temp.
280 22613af4 Kirill Batuzov
       If this temp holds a constant then its value is kept in VALS' element.
281 22613af4 Kirill Batuzov
       If this temp is a copy of other ones then this equivalence class'
282 22613af4 Kirill Batuzov
       representative is kept in VALS' element.
283 22613af4 Kirill Batuzov
       If this temp is neither copy nor constant then corresponding VALS'
284 22613af4 Kirill Batuzov
       element is unused. */
285 8f2e8c07 Kirill Batuzov
286 8f2e8c07 Kirill Batuzov
    nb_temps = s->nb_temps;
287 8f2e8c07 Kirill Batuzov
    nb_globals = s->nb_globals;
288 22613af4 Kirill Batuzov
    memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
289 8f2e8c07 Kirill Batuzov
290 8f2e8c07 Kirill Batuzov
    nb_ops = tcg_opc_ptr - gen_opc_buf;
291 8f2e8c07 Kirill Batuzov
    gen_args = args;
292 8f2e8c07 Kirill Batuzov
    for (op_index = 0; op_index < nb_ops; op_index++) {
293 8f2e8c07 Kirill Batuzov
        op = gen_opc_buf[op_index];
294 8f2e8c07 Kirill Batuzov
        def = &tcg_op_defs[op];
295 22613af4 Kirill Batuzov
        /* Do copy propagation */
296 22613af4 Kirill Batuzov
        if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS))) {
297 22613af4 Kirill Batuzov
            assert(op != INDEX_op_call);
298 22613af4 Kirill Batuzov
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
299 22613af4 Kirill Batuzov
                if (temps[args[i]].state == TCG_TEMP_COPY) {
300 22613af4 Kirill Batuzov
                    args[i] = temps[args[i]].val;
301 22613af4 Kirill Batuzov
                }
302 22613af4 Kirill Batuzov
            }
303 22613af4 Kirill Batuzov
        }
304 22613af4 Kirill Batuzov
305 53108fb5 Kirill Batuzov
        /* For commutative operations make constant second argument */
306 53108fb5 Kirill Batuzov
        switch (op) {
307 53108fb5 Kirill Batuzov
        CASE_OP_32_64(add):
308 53108fb5 Kirill Batuzov
        CASE_OP_32_64(mul):
309 9a81090b Kirill Batuzov
        CASE_OP_32_64(and):
310 9a81090b Kirill Batuzov
        CASE_OP_32_64(or):
311 9a81090b Kirill Batuzov
        CASE_OP_32_64(xor):
312 cb25c80a Richard Henderson
        CASE_OP_32_64(eqv):
313 cb25c80a Richard Henderson
        CASE_OP_32_64(nand):
314 cb25c80a Richard Henderson
        CASE_OP_32_64(nor):
315 53108fb5 Kirill Batuzov
            if (temps[args[1]].state == TCG_TEMP_CONST) {
316 53108fb5 Kirill Batuzov
                tmp = args[1];
317 53108fb5 Kirill Batuzov
                args[1] = args[2];
318 53108fb5 Kirill Batuzov
                args[2] = tmp;
319 53108fb5 Kirill Batuzov
            }
320 53108fb5 Kirill Batuzov
            break;
321 53108fb5 Kirill Batuzov
        default:
322 53108fb5 Kirill Batuzov
            break;
323 53108fb5 Kirill Batuzov
        }
324 53108fb5 Kirill Batuzov
325 53108fb5 Kirill Batuzov
        /* Simplify expression if possible. */
326 53108fb5 Kirill Batuzov
        switch (op) {
327 53108fb5 Kirill Batuzov
        CASE_OP_32_64(add):
328 53108fb5 Kirill Batuzov
        CASE_OP_32_64(sub):
329 55c0975c Kirill Batuzov
        CASE_OP_32_64(shl):
330 55c0975c Kirill Batuzov
        CASE_OP_32_64(shr):
331 55c0975c Kirill Batuzov
        CASE_OP_32_64(sar):
332 25c4d9cc Richard Henderson
        CASE_OP_32_64(rotl):
333 25c4d9cc Richard Henderson
        CASE_OP_32_64(rotr):
334 53108fb5 Kirill Batuzov
            if (temps[args[1]].state == TCG_TEMP_CONST) {
335 53108fb5 Kirill Batuzov
                /* Proceed with possible constant folding. */
336 53108fb5 Kirill Batuzov
                break;
337 53108fb5 Kirill Batuzov
            }
338 53108fb5 Kirill Batuzov
            if (temps[args[2]].state == TCG_TEMP_CONST
339 53108fb5 Kirill Batuzov
                && temps[args[2]].val == 0) {
340 53108fb5 Kirill Batuzov
                if ((temps[args[0]].state == TCG_TEMP_COPY
341 53108fb5 Kirill Batuzov
                    && temps[args[0]].val == args[1])
342 53108fb5 Kirill Batuzov
                    || args[0] == args[1]) {
343 53108fb5 Kirill Batuzov
                    args += 3;
344 53108fb5 Kirill Batuzov
                    gen_opc_buf[op_index] = INDEX_op_nop;
345 53108fb5 Kirill Batuzov
                } else {
346 53108fb5 Kirill Batuzov
                    gen_opc_buf[op_index] = op_to_mov(op);
347 e31b0a7c Blue Swirl
                    tcg_opt_gen_mov(s, gen_args, args[0], args[1],
348 53108fb5 Kirill Batuzov
                                    nb_temps, nb_globals);
349 53108fb5 Kirill Batuzov
                    gen_args += 2;
350 53108fb5 Kirill Batuzov
                    args += 3;
351 53108fb5 Kirill Batuzov
                }
352 53108fb5 Kirill Batuzov
                continue;
353 53108fb5 Kirill Batuzov
            }
354 53108fb5 Kirill Batuzov
            break;
355 53108fb5 Kirill Batuzov
        CASE_OP_32_64(mul):
356 53108fb5 Kirill Batuzov
            if ((temps[args[2]].state == TCG_TEMP_CONST
357 53108fb5 Kirill Batuzov
                && temps[args[2]].val == 0)) {
358 53108fb5 Kirill Batuzov
                gen_opc_buf[op_index] = op_to_movi(op);
359 53108fb5 Kirill Batuzov
                tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals);
360 53108fb5 Kirill Batuzov
                args += 3;
361 53108fb5 Kirill Batuzov
                gen_args += 2;
362 53108fb5 Kirill Batuzov
                continue;
363 53108fb5 Kirill Batuzov
            }
364 53108fb5 Kirill Batuzov
            break;
365 9a81090b Kirill Batuzov
        CASE_OP_32_64(or):
366 9a81090b Kirill Batuzov
        CASE_OP_32_64(and):
367 9a81090b Kirill Batuzov
            if (args[1] == args[2]) {
368 9a81090b Kirill Batuzov
                if (args[1] == args[0]) {
369 9a81090b Kirill Batuzov
                    args += 3;
370 9a81090b Kirill Batuzov
                    gen_opc_buf[op_index] = INDEX_op_nop;
371 9a81090b Kirill Batuzov
                } else {
372 9a81090b Kirill Batuzov
                    gen_opc_buf[op_index] = op_to_mov(op);
373 e31b0a7c Blue Swirl
                    tcg_opt_gen_mov(s, gen_args, args[0], args[1], nb_temps,
374 9a81090b Kirill Batuzov
                                    nb_globals);
375 9a81090b Kirill Batuzov
                    gen_args += 2;
376 9a81090b Kirill Batuzov
                    args += 3;
377 9a81090b Kirill Batuzov
                }
378 9a81090b Kirill Batuzov
                continue;
379 9a81090b Kirill Batuzov
            }
380 9a81090b Kirill Batuzov
            break;
381 fe0de7aa Blue Swirl
        default:
382 fe0de7aa Blue Swirl
            break;
383 53108fb5 Kirill Batuzov
        }
384 53108fb5 Kirill Batuzov
385 22613af4 Kirill Batuzov
        /* Propagate constants through copy operations and do constant
386 22613af4 Kirill Batuzov
           folding.  Constants will be substituted to arguments by register
387 22613af4 Kirill Batuzov
           allocator where needed and possible.  Also detect copies. */
388 8f2e8c07 Kirill Batuzov
        switch (op) {
389 22613af4 Kirill Batuzov
        CASE_OP_32_64(mov):
390 22613af4 Kirill Batuzov
            if ((temps[args[1]].state == TCG_TEMP_COPY
391 22613af4 Kirill Batuzov
                && temps[args[1]].val == args[0])
392 22613af4 Kirill Batuzov
                || args[0] == args[1]) {
393 22613af4 Kirill Batuzov
                args += 2;
394 22613af4 Kirill Batuzov
                gen_opc_buf[op_index] = INDEX_op_nop;
395 22613af4 Kirill Batuzov
                break;
396 22613af4 Kirill Batuzov
            }
397 22613af4 Kirill Batuzov
            if (temps[args[1]].state != TCG_TEMP_CONST) {
398 e31b0a7c Blue Swirl
                tcg_opt_gen_mov(s, gen_args, args[0], args[1],
399 22613af4 Kirill Batuzov
                                nb_temps, nb_globals);
400 22613af4 Kirill Batuzov
                gen_args += 2;
401 22613af4 Kirill Batuzov
                args += 2;
402 22613af4 Kirill Batuzov
                break;
403 22613af4 Kirill Batuzov
            }
404 22613af4 Kirill Batuzov
            /* Source argument is constant.  Rewrite the operation and
405 22613af4 Kirill Batuzov
               let movi case handle it. */
406 22613af4 Kirill Batuzov
            op = op_to_movi(op);
407 22613af4 Kirill Batuzov
            gen_opc_buf[op_index] = op;
408 22613af4 Kirill Batuzov
            args[1] = temps[args[1]].val;
409 22613af4 Kirill Batuzov
            /* fallthrough */
410 22613af4 Kirill Batuzov
        CASE_OP_32_64(movi):
411 22613af4 Kirill Batuzov
            tcg_opt_gen_movi(gen_args, args[0], args[1], nb_temps, nb_globals);
412 22613af4 Kirill Batuzov
            gen_args += 2;
413 22613af4 Kirill Batuzov
            args += 2;
414 22613af4 Kirill Batuzov
            break;
415 a640f031 Kirill Batuzov
        CASE_OP_32_64(not):
416 cb25c80a Richard Henderson
        CASE_OP_32_64(neg):
417 25c4d9cc Richard Henderson
        CASE_OP_32_64(ext8s):
418 25c4d9cc Richard Henderson
        CASE_OP_32_64(ext8u):
419 25c4d9cc Richard Henderson
        CASE_OP_32_64(ext16s):
420 25c4d9cc Richard Henderson
        CASE_OP_32_64(ext16u):
421 a640f031 Kirill Batuzov
        case INDEX_op_ext32s_i64:
422 a640f031 Kirill Batuzov
        case INDEX_op_ext32u_i64:
423 a640f031 Kirill Batuzov
            if (temps[args[1]].state == TCG_TEMP_CONST) {
424 a640f031 Kirill Batuzov
                gen_opc_buf[op_index] = op_to_movi(op);
425 a640f031 Kirill Batuzov
                tmp = do_constant_folding(op, temps[args[1]].val, 0);
426 a640f031 Kirill Batuzov
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
427 a640f031 Kirill Batuzov
                gen_args += 2;
428 a640f031 Kirill Batuzov
                args += 2;
429 a640f031 Kirill Batuzov
                break;
430 a640f031 Kirill Batuzov
            } else {
431 a640f031 Kirill Batuzov
                reset_temp(args[0], nb_temps, nb_globals);
432 a640f031 Kirill Batuzov
                gen_args[0] = args[0];
433 a640f031 Kirill Batuzov
                gen_args[1] = args[1];
434 a640f031 Kirill Batuzov
                gen_args += 2;
435 a640f031 Kirill Batuzov
                args += 2;
436 a640f031 Kirill Batuzov
                break;
437 a640f031 Kirill Batuzov
            }
438 53108fb5 Kirill Batuzov
        CASE_OP_32_64(add):
439 53108fb5 Kirill Batuzov
        CASE_OP_32_64(sub):
440 53108fb5 Kirill Batuzov
        CASE_OP_32_64(mul):
441 9a81090b Kirill Batuzov
        CASE_OP_32_64(or):
442 9a81090b Kirill Batuzov
        CASE_OP_32_64(and):
443 9a81090b Kirill Batuzov
        CASE_OP_32_64(xor):
444 55c0975c Kirill Batuzov
        CASE_OP_32_64(shl):
445 55c0975c Kirill Batuzov
        CASE_OP_32_64(shr):
446 55c0975c Kirill Batuzov
        CASE_OP_32_64(sar):
447 25c4d9cc Richard Henderson
        CASE_OP_32_64(rotl):
448 25c4d9cc Richard Henderson
        CASE_OP_32_64(rotr):
449 cb25c80a Richard Henderson
        CASE_OP_32_64(andc):
450 cb25c80a Richard Henderson
        CASE_OP_32_64(orc):
451 cb25c80a Richard Henderson
        CASE_OP_32_64(eqv):
452 cb25c80a Richard Henderson
        CASE_OP_32_64(nand):
453 cb25c80a Richard Henderson
        CASE_OP_32_64(nor):
454 53108fb5 Kirill Batuzov
            if (temps[args[1]].state == TCG_TEMP_CONST
455 53108fb5 Kirill Batuzov
                && temps[args[2]].state == TCG_TEMP_CONST) {
456 53108fb5 Kirill Batuzov
                gen_opc_buf[op_index] = op_to_movi(op);
457 53108fb5 Kirill Batuzov
                tmp = do_constant_folding(op, temps[args[1]].val,
458 53108fb5 Kirill Batuzov
                                          temps[args[2]].val);
459 53108fb5 Kirill Batuzov
                tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals);
460 53108fb5 Kirill Batuzov
                gen_args += 2;
461 53108fb5 Kirill Batuzov
                args += 3;
462 53108fb5 Kirill Batuzov
                break;
463 53108fb5 Kirill Batuzov
            } else {
464 53108fb5 Kirill Batuzov
                reset_temp(args[0], nb_temps, nb_globals);
465 53108fb5 Kirill Batuzov
                gen_args[0] = args[0];
466 53108fb5 Kirill Batuzov
                gen_args[1] = args[1];
467 53108fb5 Kirill Batuzov
                gen_args[2] = args[2];
468 53108fb5 Kirill Batuzov
                gen_args += 3;
469 53108fb5 Kirill Batuzov
                args += 3;
470 53108fb5 Kirill Batuzov
                break;
471 53108fb5 Kirill Batuzov
            }
472 8f2e8c07 Kirill Batuzov
        case INDEX_op_call:
473 22613af4 Kirill Batuzov
            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
474 22613af4 Kirill Batuzov
            if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
475 22613af4 Kirill Batuzov
                for (i = 0; i < nb_globals; i++) {
476 22613af4 Kirill Batuzov
                    reset_temp(i, nb_temps, nb_globals);
477 22613af4 Kirill Batuzov
                }
478 22613af4 Kirill Batuzov
            }
479 22613af4 Kirill Batuzov
            for (i = 0; i < (args[0] >> 16); i++) {
480 22613af4 Kirill Batuzov
                reset_temp(args[i + 1], nb_temps, nb_globals);
481 22613af4 Kirill Batuzov
            }
482 22613af4 Kirill Batuzov
            i = nb_call_args + 3;
483 8f2e8c07 Kirill Batuzov
            while (i) {
484 8f2e8c07 Kirill Batuzov
                *gen_args = *args;
485 8f2e8c07 Kirill Batuzov
                args++;
486 8f2e8c07 Kirill Batuzov
                gen_args++;
487 8f2e8c07 Kirill Batuzov
                i--;
488 8f2e8c07 Kirill Batuzov
            }
489 8f2e8c07 Kirill Batuzov
            break;
490 8f2e8c07 Kirill Batuzov
        case INDEX_op_set_label:
491 8f2e8c07 Kirill Batuzov
        case INDEX_op_jmp:
492 8f2e8c07 Kirill Batuzov
        case INDEX_op_br:
493 8f2e8c07 Kirill Batuzov
        CASE_OP_32_64(brcond):
494 22613af4 Kirill Batuzov
            memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
495 8f2e8c07 Kirill Batuzov
            for (i = 0; i < def->nb_args; i++) {
496 8f2e8c07 Kirill Batuzov
                *gen_args = *args;
497 8f2e8c07 Kirill Batuzov
                args++;
498 8f2e8c07 Kirill Batuzov
                gen_args++;
499 8f2e8c07 Kirill Batuzov
            }
500 8f2e8c07 Kirill Batuzov
            break;
501 8f2e8c07 Kirill Batuzov
        default:
502 22613af4 Kirill Batuzov
            /* Default case: we do know nothing about operation so no
503 22613af4 Kirill Batuzov
               propagation is done.  We only trash output args.  */
504 22613af4 Kirill Batuzov
            for (i = 0; i < def->nb_oargs; i++) {
505 22613af4 Kirill Batuzov
                reset_temp(args[i], nb_temps, nb_globals);
506 22613af4 Kirill Batuzov
            }
507 8f2e8c07 Kirill Batuzov
            for (i = 0; i < def->nb_args; i++) {
508 8f2e8c07 Kirill Batuzov
                gen_args[i] = args[i];
509 8f2e8c07 Kirill Batuzov
            }
510 8f2e8c07 Kirill Batuzov
            args += def->nb_args;
511 8f2e8c07 Kirill Batuzov
            gen_args += def->nb_args;
512 8f2e8c07 Kirill Batuzov
            break;
513 8f2e8c07 Kirill Batuzov
        }
514 8f2e8c07 Kirill Batuzov
    }
515 8f2e8c07 Kirill Batuzov
516 8f2e8c07 Kirill Batuzov
    return gen_args;
517 8f2e8c07 Kirill Batuzov
}
518 8f2e8c07 Kirill Batuzov
519 8f2e8c07 Kirill Batuzov
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
520 8f2e8c07 Kirill Batuzov
        TCGArg *args, TCGOpDef *tcg_op_defs)
521 8f2e8c07 Kirill Batuzov
{
522 8f2e8c07 Kirill Batuzov
    TCGArg *res;
523 8f2e8c07 Kirill Batuzov
    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
524 8f2e8c07 Kirill Batuzov
    return res;
525 8f2e8c07 Kirill Batuzov
}