blob: 6a0a4ddb33103c8d7c7be35c3b4aa5777f3f3b96 [file] [log] [blame]
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001/*
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
Kirill Batuzov22613af2011-07-07 16:37:13 +040043typedef 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
51struct 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
58static 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. */
63static 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
95static int op_bits(int op)
96{
97 switch (op) {
98 case INDEX_op_mov_i32:
Kirill Batuzov53108fb2011-07-07 16:37:14 +040099 case INDEX_op_add_i32:
100 case INDEX_op_sub_i32:
101 case INDEX_op_mul_i32:
Kirill Batuzov9a810902011-07-07 16:37:15 +0400102 case INDEX_op_and_i32:
103 case INDEX_op_or_i32:
104 case INDEX_op_xor_i32:
Kirill Batuzov55c09752011-07-07 16:37:16 +0400105 case INDEX_op_shl_i32:
106 case INDEX_op_shr_i32:
107 case INDEX_op_sar_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000108#ifdef TCG_TARGET_HAS_rot_i32
Kirill Batuzov55c09752011-07-07 16:37:16 +0400109 case INDEX_op_rotl_i32:
110 case INDEX_op_rotr_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000111#endif
112#ifdef TCG_TARGET_HAS_not_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400113 case INDEX_op_not_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000114#endif
115#ifdef TCG_TARGET_HAS_ext8s_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400116 case INDEX_op_ext8s_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000117#endif
118#ifdef TCG_TARGET_HAS_ext16s_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400119 case INDEX_op_ext16s_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000120#endif
121#ifdef TCG_TARGET_HAS_ext8u_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400122 case INDEX_op_ext8u_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000123#endif
124#ifdef TCG_TARGET_HAS_ext16u_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400125 case INDEX_op_ext16u_i32:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000126#endif
Kirill Batuzov22613af2011-07-07 16:37:13 +0400127 return 32;
128#if TCG_TARGET_REG_BITS == 64
129 case INDEX_op_mov_i64:
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400130 case INDEX_op_add_i64:
131 case INDEX_op_sub_i64:
132 case INDEX_op_mul_i64:
Kirill Batuzov9a810902011-07-07 16:37:15 +0400133 case INDEX_op_and_i64:
134 case INDEX_op_or_i64:
135 case INDEX_op_xor_i64:
Kirill Batuzov55c09752011-07-07 16:37:16 +0400136 case INDEX_op_shl_i64:
137 case INDEX_op_shr_i64:
138 case INDEX_op_sar_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000139#ifdef TCG_TARGET_HAS_rot_i64
Kirill Batuzov55c09752011-07-07 16:37:16 +0400140 case INDEX_op_rotl_i64:
141 case INDEX_op_rotr_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000142#endif
143#ifdef TCG_TARGET_HAS_not_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400144 case INDEX_op_not_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000145#endif
146#ifdef TCG_TARGET_HAS_ext8s_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400147 case INDEX_op_ext8s_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000148#endif
149#ifdef TCG_TARGET_HAS_ext16s_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400150 case INDEX_op_ext16s_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000151#endif
152#ifdef TCG_TARGET_HAS_ext32s_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400153 case INDEX_op_ext32s_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000154#endif
155#ifdef TCG_TARGET_HAS_ext8u_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400156 case INDEX_op_ext8u_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000157#endif
158#ifdef TCG_TARGET_HAS_ext16u_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400159 case INDEX_op_ext16u_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000160#endif
161#ifdef TCG_TARGET_HAS_ext32u_i64
Kirill Batuzova640f032011-07-07 16:37:17 +0400162 case INDEX_op_ext32u_i64:
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000163#endif
Kirill Batuzov22613af2011-07-07 16:37:13 +0400164 return 64;
165#endif
166 default:
167 fprintf(stderr, "Unrecognized operation %d in op_bits.\n", op);
168 tcg_abort();
169 }
170}
171
172static 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
188static 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
211static 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
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400221static 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
237static 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
Kirill Batuzov9a810902011-07-07 16:37:15 +0400249 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
Kirill Batuzov55c09752011-07-07 16:37:16 +0400258 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
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000282#ifdef TCG_TARGET_HAS_rot_i32
Kirill Batuzov55c09752011-07-07 16:37:16 +0400283 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;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000290#endif
Kirill Batuzov55c09752011-07-07 16:37:16 +0400291
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000292#ifdef TCG_TARGET_HAS_rot_i64
Kirill Batuzov55c09752011-07-07 16:37:16 +0400293#if TCG_TARGET_REG_BITS == 64
294 case INDEX_op_rotr_i64:
295 x = (x << (64 - y)) | (x >> y);
296 return x;
297#endif
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000298#endif
Kirill Batuzov55c09752011-07-07 16:37:16 +0400299
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000300#ifdef TCG_TARGET_HAS_rot_i32
Kirill Batuzov55c09752011-07-07 16:37:16 +0400301 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;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000308#endif
Kirill Batuzov55c09752011-07-07 16:37:16 +0400309
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000310#ifdef TCG_TARGET_HAS_rot_i64
Kirill Batuzov55c09752011-07-07 16:37:16 +0400311#if TCG_TARGET_REG_BITS == 64
312 case INDEX_op_rotl_i64:
313 x = (x << y) | (x >> (64 - y));
314 return x;
315#endif
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000316#endif
Kirill Batuzov55c09752011-07-07 16:37:16 +0400317
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000318#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400324 return ~x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000325#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400326
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000327#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400333 return (int8_t)x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000334#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400335
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000336#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400342 return (int16_t)x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000343#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400344
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000345#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400351 return (uint8_t)x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000352#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400353
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000354#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400360 return (uint16_t)x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000361#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400362
363#if TCG_TARGET_REG_BITS == 64
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000364#ifdef TCG_TARGET_HAS_ext32s_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400365 case INDEX_op_ext32s_i64:
366 return (int32_t)x;
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000367#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400368
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000369#ifdef TCG_TARGET_HAS_ext32u_i32
Kirill Batuzova640f032011-07-07 16:37:17 +0400370 case INDEX_op_ext32u_i64:
371 return (uint32_t)x;
372#endif
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000373#endif
Kirill Batuzova640f032011-07-07 16:37:17 +0400374
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400375 default:
376 fprintf(stderr,
377 "Unrecognized operation %d in do_constant_folding.\n", op);
378 tcg_abort();
379 }
380}
381
382static 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
Kirill Batuzov22613af2011-07-07 16:37:13 +0400393/* Propagate constants and copies, fold constant expressions. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400394static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
395 TCGArg *args, TCGOpDef *tcg_op_defs)
396{
Kirill Batuzov22613af2011-07-07 16:37:13 +0400397 int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args;
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400398 const TCGOpDef *def;
399 TCGArg *gen_args;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400400 TCGArg tmp;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400401 /* 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. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400407
408 nb_temps = s->nb_temps;
409 nb_globals = s->nb_globals;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400410 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400411
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];
Kirill Batuzov22613af2011-07-07 16:37:13 +0400417 /* 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
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400427 /* For commutative operations make constant second argument */
428 switch (op) {
429 CASE_OP_32_64(add):
430 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +0400431 CASE_OP_32_64(and):
432 CASE_OP_32_64(or):
433 CASE_OP_32_64(xor):
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400434 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):
Kirill Batuzov55c09752011-07-07 16:37:16 +0400448 CASE_OP_32_64(shl):
449 CASE_OP_32_64(shr):
450 CASE_OP_32_64(sar):
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000451#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
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400459 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;
Kirill Batuzov9a810902011-07-07 16:37:15 +0400490 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;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400506 }
507
Kirill Batuzov22613af2011-07-07 16:37:13 +0400508 /* 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. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400511 switch (op) {
Kirill Batuzov22613af2011-07-07 16:37:13 +0400512 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;
Kirill Batuzova640f032011-07-07 16:37:17 +0400538 CASE_OP_32_64(not):
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000539#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
Kirill Batuzova640f032011-07-07 16:37:17 +0400563#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 }
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400582 CASE_OP_32_64(add):
583 CASE_OP_32_64(sub):
584 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +0400585 CASE_OP_32_64(or):
586 CASE_OP_32_64(and):
587 CASE_OP_32_64(xor):
Kirill Batuzov55c09752011-07-07 16:37:16 +0400588 CASE_OP_32_64(shl):
589 CASE_OP_32_64(shr):
590 CASE_OP_32_64(sar):
Blue Swirl1bfd07b2011-07-30 12:21:33 +0000591#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
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400599 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 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400617 case INDEX_op_call:
Kirill Batuzov22613af2011-07-07 16:37:13 +0400618 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;
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400628 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):
Kirill Batuzov22613af2011-07-07 16:37:13 +0400639 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400640 for (i = 0; i < def->nb_args; i++) {
641 *gen_args = *args;
642 args++;
643 gen_args++;
644 }
645 break;
646 default:
Kirill Batuzov22613af2011-07-07 16:37:13 +0400647 /* 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 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400652 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
664TCGArg *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}