blob: 8df7fc7f6918fa7125dabfd2d9c31c107a0318fe [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
Peter Maydell757e7252016-01-26 18:17:08 +000026#include "qemu/osdep.h"
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +040027#include "qemu-common.h"
Paolo Bonzini00f6da62016-03-15 13:16:36 +010028#include "exec/cpu-common.h"
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +040029#include "tcg-op.h"
30
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +040031#define CASE_OP_32_64(x) \
32 glue(glue(case INDEX_op_, x), _i32): \
33 glue(glue(case INDEX_op_, x), _i64)
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +040034
Kirill Batuzov22613af2011-07-07 16:37:13 +040035struct tcg_temp_info {
Aurelien Jarnob41059d2015-07-27 12:41:44 +020036 bool is_const;
Kirill Batuzov22613af2011-07-07 16:37:13 +040037 uint16_t prev_copy;
38 uint16_t next_copy;
39 tcg_target_ulong val;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -080040 tcg_target_ulong mask;
Kirill Batuzov22613af2011-07-07 16:37:13 +040041};
42
43static struct tcg_temp_info temps[TCG_MAX_TEMPS];
Aurelien Jarno1208d7d2015-07-27 12:41:44 +020044static TCGTempSet temps_used;
Kirill Batuzov22613af2011-07-07 16:37:13 +040045
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020046static inline bool temp_is_const(TCGArg arg)
47{
Aurelien Jarnob41059d2015-07-27 12:41:44 +020048 return temps[arg].is_const;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020049}
50
51static inline bool temp_is_copy(TCGArg arg)
52{
Aurelien Jarnob41059d2015-07-27 12:41:44 +020053 return temps[arg].next_copy != arg;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020054}
55
Aurelien Jarnob41059d2015-07-27 12:41:44 +020056/* Reset TEMP's state, possibly removing the temp for the list of copies. */
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +020057static void reset_temp(TCGArg temp)
Kirill Batuzov22613af2011-07-07 16:37:13 +040058{
Aurelien Jarnob41059d2015-07-27 12:41:44 +020059 temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
60 temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
61 temps[temp].next_copy = temp;
62 temps[temp].prev_copy = temp;
63 temps[temp].is_const = false;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -080064 temps[temp].mask = -1;
Kirill Batuzov22613af2011-07-07 16:37:13 +040065}
66
Aurelien Jarno1208d7d2015-07-27 12:41:44 +020067/* Reset all temporaries, given that there are NB_TEMPS of them. */
68static void reset_all_temps(int nb_temps)
69{
70 bitmap_zero(temps_used.l, nb_temps);
71}
72
73/* Initialize and activate a temporary. */
74static void init_temp_info(TCGArg temp)
75{
76 if (!test_bit(temp, temps_used.l)) {
Aurelien Jarnob41059d2015-07-27 12:41:44 +020077 temps[temp].next_copy = temp;
78 temps[temp].prev_copy = temp;
79 temps[temp].is_const = false;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +020080 temps[temp].mask = -1;
81 set_bit(temp, temps_used.l);
82 }
83}
84
Richard Hendersona4ce0992014-03-30 17:14:02 -070085static TCGOp *insert_op_before(TCGContext *s, TCGOp *old_op,
86 TCGOpcode opc, int nargs)
87{
88 int oi = s->gen_next_op_idx;
89 int pi = s->gen_next_parm_idx;
90 int prev = old_op->prev;
91 int next = old_op - s->gen_op_buf;
92 TCGOp *new_op;
93
94 tcg_debug_assert(oi < OPC_BUF_SIZE);
95 tcg_debug_assert(pi + nargs <= OPPARAM_BUF_SIZE);
96 s->gen_next_op_idx = oi + 1;
97 s->gen_next_parm_idx = pi + nargs;
98
99 new_op = &s->gen_op_buf[oi];
100 *new_op = (TCGOp){
101 .opc = opc,
102 .args = pi,
103 .prev = prev,
104 .next = next
105 };
Richard Hendersondcb8e752016-06-22 19:42:31 -0700106 s->gen_op_buf[prev].next = oi;
Richard Hendersona4ce0992014-03-30 17:14:02 -0700107 old_op->prev = oi;
108
109 return new_op;
110}
111
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000112static int op_bits(TCGOpcode op)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400113{
Richard Henderson8399ad52011-08-17 14:11:45 -0700114 const TCGOpDef *def = &tcg_op_defs[op];
115 return def->flags & TCG_OPF_64BIT ? 64 : 32;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400116}
117
Richard Hendersona62f6f52014-05-22 10:59:12 -0700118static TCGOpcode op_to_mov(TCGOpcode op)
119{
120 switch (op_bits(op)) {
121 case 32:
122 return INDEX_op_mov_i32;
123 case 64:
124 return INDEX_op_mov_i64;
125 default:
126 fprintf(stderr, "op_to_mov: unexpected return value of "
127 "function op_bits.\n");
128 tcg_abort();
129 }
130}
131
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000132static TCGOpcode op_to_movi(TCGOpcode op)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400133{
134 switch (op_bits(op)) {
135 case 32:
136 return INDEX_op_movi_i32;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400137 case 64:
138 return INDEX_op_movi_i64;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400139 default:
140 fprintf(stderr, "op_to_movi: unexpected return value of "
141 "function op_bits.\n");
142 tcg_abort();
143 }
144}
145
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200146static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
147{
148 TCGArg i;
149
150 /* If this is already a global, we can't do better. */
151 if (temp < s->nb_globals) {
152 return temp;
153 }
154
155 /* Search for a global first. */
156 for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
157 if (i < s->nb_globals) {
158 return i;
159 }
160 }
161
162 /* If it is a temp, search for a temp local. */
163 if (!s->temps[temp].temp_local) {
164 for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
165 if (s->temps[i].temp_local) {
166 return i;
167 }
168 }
169 }
170
171 /* Failure to find a better representation, return the same temp. */
172 return temp;
173}
174
175static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
176{
177 TCGArg i;
178
179 if (arg1 == arg2) {
180 return true;
181 }
182
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200183 if (!temp_is_copy(arg1) || !temp_is_copy(arg2)) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200184 return false;
185 }
186
187 for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
188 if (i == arg2) {
189 return true;
190 }
191 }
192
193 return false;
194}
195
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200196static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
197 TCGArg dst, TCGArg val)
198{
199 TCGOpcode new_op = op_to_movi(op->opc);
200 tcg_target_ulong mask;
201
202 op->opc = new_op;
203
204 reset_temp(dst);
Aurelien Jarnob41059d2015-07-27 12:41:44 +0200205 temps[dst].is_const = true;
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200206 temps[dst].val = val;
207 mask = val;
Aurelien Jarno96152122015-07-10 18:03:30 +0200208 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200209 /* High bits of the destination are now garbage. */
210 mask |= ~0xffffffffull;
211 }
212 temps[dst].mask = mask;
213
214 args[0] = dst;
215 args[1] = val;
216}
217
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700218static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
Aurelien Jarno8d6a9162015-06-04 21:53:24 +0200219 TCGArg dst, TCGArg src)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400220{
Aurelien Jarno53657182015-06-04 21:53:25 +0200221 if (temps_are_copies(dst, src)) {
222 tcg_op_remove(s, op);
223 return;
224 }
225
Aurelien Jarno8d6a9162015-06-04 21:53:24 +0200226 TCGOpcode new_op = op_to_mov(op->opc);
Richard Henderson24666ba2014-05-22 11:14:10 -0700227 tcg_target_ulong mask;
Richard Hendersona62f6f52014-05-22 10:59:12 -0700228
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700229 op->opc = new_op;
Richard Hendersona62f6f52014-05-22 10:59:12 -0700230
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800231 reset_temp(dst);
Richard Henderson24666ba2014-05-22 11:14:10 -0700232 mask = temps[src].mask;
233 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
234 /* High bits of the destination are now garbage. */
235 mask |= ~0xffffffffull;
236 }
237 temps[dst].mask = mask;
238
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800239 if (s->temps[src].type == s->temps[dst].type) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800240 temps[dst].next_copy = temps[src].next_copy;
241 temps[dst].prev_copy = src;
242 temps[temps[dst].next_copy].prev_copy = dst;
243 temps[src].next_copy = dst;
Aurelien Jarno299f8012015-07-27 12:41:44 +0200244 temps[dst].is_const = temps[src].is_const;
245 temps[dst].val = temps[src].val;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800246 }
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200247
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700248 args[0] = dst;
249 args[1] = src;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400250}
251
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000252static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400253{
Richard Henderson03271522013-08-14 14:35:56 -0700254 uint64_t l64, h64;
255
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400256 switch (op) {
257 CASE_OP_32_64(add):
258 return x + y;
259
260 CASE_OP_32_64(sub):
261 return x - y;
262
263 CASE_OP_32_64(mul):
264 return x * y;
265
Kirill Batuzov9a810902011-07-07 16:37:15 +0400266 CASE_OP_32_64(and):
267 return x & y;
268
269 CASE_OP_32_64(or):
270 return x | y;
271
272 CASE_OP_32_64(xor):
273 return x ^ y;
274
Kirill Batuzov55c09752011-07-07 16:37:16 +0400275 case INDEX_op_shl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700276 return (uint32_t)x << (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400277
Kirill Batuzov55c09752011-07-07 16:37:16 +0400278 case INDEX_op_shl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700279 return (uint64_t)x << (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400280
281 case INDEX_op_shr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700282 return (uint32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400283
Kirill Batuzov55c09752011-07-07 16:37:16 +0400284 case INDEX_op_shr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700285 return (uint64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400286
287 case INDEX_op_sar_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700288 return (int32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400289
Kirill Batuzov55c09752011-07-07 16:37:16 +0400290 case INDEX_op_sar_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700291 return (int64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400292
293 case INDEX_op_rotr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700294 return ror32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400295
Kirill Batuzov55c09752011-07-07 16:37:16 +0400296 case INDEX_op_rotr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700297 return ror64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400298
299 case INDEX_op_rotl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700300 return rol32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400301
Kirill Batuzov55c09752011-07-07 16:37:16 +0400302 case INDEX_op_rotl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700303 return rol64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400304
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700305 CASE_OP_32_64(not):
Kirill Batuzova640f032011-07-07 16:37:17 +0400306 return ~x;
307
Richard Hendersoncb25c802011-08-17 14:11:47 -0700308 CASE_OP_32_64(neg):
309 return -x;
310
311 CASE_OP_32_64(andc):
312 return x & ~y;
313
314 CASE_OP_32_64(orc):
315 return x | ~y;
316
317 CASE_OP_32_64(eqv):
318 return ~(x ^ y);
319
320 CASE_OP_32_64(nand):
321 return ~(x & y);
322
323 CASE_OP_32_64(nor):
324 return ~(x | y);
325
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700326 CASE_OP_32_64(ext8s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400327 return (int8_t)x;
328
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700329 CASE_OP_32_64(ext16s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400330 return (int16_t)x;
331
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700332 CASE_OP_32_64(ext8u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400333 return (uint8_t)x;
334
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700335 CASE_OP_32_64(ext16u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400336 return (uint16_t)x;
337
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200338 case INDEX_op_ext_i32_i64:
Kirill Batuzova640f032011-07-07 16:37:17 +0400339 case INDEX_op_ext32s_i64:
340 return (int32_t)x;
341
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200342 case INDEX_op_extu_i32_i64:
Richard Henderson609ad702015-07-24 07:16:00 -0700343 case INDEX_op_extrl_i64_i32:
Kirill Batuzova640f032011-07-07 16:37:17 +0400344 case INDEX_op_ext32u_i64:
345 return (uint32_t)x;
Kirill Batuzova640f032011-07-07 16:37:17 +0400346
Richard Henderson609ad702015-07-24 07:16:00 -0700347 case INDEX_op_extrh_i64_i32:
348 return (uint64_t)x >> 32;
349
Richard Henderson03271522013-08-14 14:35:56 -0700350 case INDEX_op_muluh_i32:
351 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
352 case INDEX_op_mulsh_i32:
353 return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
354
355 case INDEX_op_muluh_i64:
356 mulu64(&l64, &h64, x, y);
357 return h64;
358 case INDEX_op_mulsh_i64:
359 muls64(&l64, &h64, x, y);
360 return h64;
361
Richard Henderson01547f72013-08-14 15:22:46 -0700362 case INDEX_op_div_i32:
363 /* Avoid crashing on divide by zero, otherwise undefined. */
364 return (int32_t)x / ((int32_t)y ? : 1);
365 case INDEX_op_divu_i32:
366 return (uint32_t)x / ((uint32_t)y ? : 1);
367 case INDEX_op_div_i64:
368 return (int64_t)x / ((int64_t)y ? : 1);
369 case INDEX_op_divu_i64:
370 return (uint64_t)x / ((uint64_t)y ? : 1);
371
372 case INDEX_op_rem_i32:
373 return (int32_t)x % ((int32_t)y ? : 1);
374 case INDEX_op_remu_i32:
375 return (uint32_t)x % ((uint32_t)y ? : 1);
376 case INDEX_op_rem_i64:
377 return (int64_t)x % ((int64_t)y ? : 1);
378 case INDEX_op_remu_i64:
379 return (uint64_t)x % ((uint64_t)y ? : 1);
380
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400381 default:
382 fprintf(stderr,
383 "Unrecognized operation %d in do_constant_folding.\n", op);
384 tcg_abort();
385 }
386}
387
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000388static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400389{
390 TCGArg res = do_constant_folding_2(op, x, y);
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400391 if (op_bits(op) == 32) {
Aurelien Jarno29f3ff82015-07-10 18:03:31 +0200392 res = (int32_t)res;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400393 }
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400394 return res;
395}
396
Richard Henderson9519da72012-10-02 11:32:26 -0700397static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
398{
399 switch (c) {
400 case TCG_COND_EQ:
401 return x == y;
402 case TCG_COND_NE:
403 return x != y;
404 case TCG_COND_LT:
405 return (int32_t)x < (int32_t)y;
406 case TCG_COND_GE:
407 return (int32_t)x >= (int32_t)y;
408 case TCG_COND_LE:
409 return (int32_t)x <= (int32_t)y;
410 case TCG_COND_GT:
411 return (int32_t)x > (int32_t)y;
412 case TCG_COND_LTU:
413 return x < y;
414 case TCG_COND_GEU:
415 return x >= y;
416 case TCG_COND_LEU:
417 return x <= y;
418 case TCG_COND_GTU:
419 return x > y;
420 default:
421 tcg_abort();
422 }
423}
424
425static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
426{
427 switch (c) {
428 case TCG_COND_EQ:
429 return x == y;
430 case TCG_COND_NE:
431 return x != y;
432 case TCG_COND_LT:
433 return (int64_t)x < (int64_t)y;
434 case TCG_COND_GE:
435 return (int64_t)x >= (int64_t)y;
436 case TCG_COND_LE:
437 return (int64_t)x <= (int64_t)y;
438 case TCG_COND_GT:
439 return (int64_t)x > (int64_t)y;
440 case TCG_COND_LTU:
441 return x < y;
442 case TCG_COND_GEU:
443 return x >= y;
444 case TCG_COND_LEU:
445 return x <= y;
446 case TCG_COND_GTU:
447 return x > y;
448 default:
449 tcg_abort();
450 }
451}
452
453static bool do_constant_folding_cond_eq(TCGCond c)
454{
455 switch (c) {
456 case TCG_COND_GT:
457 case TCG_COND_LTU:
458 case TCG_COND_LT:
459 case TCG_COND_GTU:
460 case TCG_COND_NE:
461 return 0;
462 case TCG_COND_GE:
463 case TCG_COND_GEU:
464 case TCG_COND_LE:
465 case TCG_COND_LEU:
466 case TCG_COND_EQ:
467 return 1;
468 default:
469 tcg_abort();
470 }
471}
472
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200473/* Return 2 if the condition can't be simplified, and the result
474 of the condition (0 or 1) if it can */
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200475static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
476 TCGArg y, TCGCond c)
477{
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200478 if (temp_is_const(x) && temp_is_const(y)) {
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200479 switch (op_bits(op)) {
480 case 32:
Richard Henderson9519da72012-10-02 11:32:26 -0700481 return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200482 case 64:
Richard Henderson9519da72012-10-02 11:32:26 -0700483 return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
484 default:
485 tcg_abort();
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200486 }
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200487 } else if (temps_are_copies(x, y)) {
Richard Henderson9519da72012-10-02 11:32:26 -0700488 return do_constant_folding_cond_eq(c);
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200489 } else if (temp_is_const(y) && temps[y].val == 0) {
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200490 switch (c) {
491 case TCG_COND_LTU:
492 return 0;
493 case TCG_COND_GEU:
494 return 1;
495 default:
496 return 2;
497 }
498 } else {
499 return 2;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200500 }
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200501}
502
Richard Henderson6c4382f2012-10-02 11:32:27 -0700503/* Return 2 if the condition can't be simplified, and the result
504 of the condition (0 or 1) if it can */
505static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
506{
507 TCGArg al = p1[0], ah = p1[1];
508 TCGArg bl = p2[0], bh = p2[1];
509
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200510 if (temp_is_const(bl) && temp_is_const(bh)) {
Richard Henderson6c4382f2012-10-02 11:32:27 -0700511 uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val;
512
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200513 if (temp_is_const(al) && temp_is_const(ah)) {
Richard Henderson6c4382f2012-10-02 11:32:27 -0700514 uint64_t a;
515 a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val;
516 return do_constant_folding_cond_64(a, b, c);
517 }
518 if (b == 0) {
519 switch (c) {
520 case TCG_COND_LTU:
521 return 0;
522 case TCG_COND_GEU:
523 return 1;
524 default:
525 break;
526 }
527 }
528 }
529 if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) {
530 return do_constant_folding_cond_eq(c);
531 }
532 return 2;
533}
534
Richard Henderson24c9ae42012-10-02 11:32:21 -0700535static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
536{
537 TCGArg a1 = *p1, a2 = *p2;
538 int sum = 0;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200539 sum += temp_is_const(a1);
540 sum -= temp_is_const(a2);
Richard Henderson24c9ae42012-10-02 11:32:21 -0700541
542 /* Prefer the constant in second argument, and then the form
543 op a, a, b, which is better handled on non-RISC hosts. */
544 if (sum > 0 || (sum == 0 && dest == a2)) {
545 *p1 = a2;
546 *p2 = a1;
547 return true;
548 }
549 return false;
550}
551
Richard Henderson0bfcb862012-10-02 11:32:23 -0700552static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
553{
554 int sum = 0;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200555 sum += temp_is_const(p1[0]);
556 sum += temp_is_const(p1[1]);
557 sum -= temp_is_const(p2[0]);
558 sum -= temp_is_const(p2[1]);
Richard Henderson0bfcb862012-10-02 11:32:23 -0700559 if (sum > 0) {
560 TCGArg t;
561 t = p1[0], p1[0] = p2[0], p2[0] = t;
562 t = p1[1], p1[1] = p2[1], p2[1] = t;
563 return true;
564 }
565 return false;
566}
567
Kirill Batuzov22613af2011-07-07 16:37:13 +0400568/* Propagate constants and copies, fold constant expressions. */
Aurelien Jarno36e60ef2015-06-04 21:53:27 +0200569void tcg_optimize(TCGContext *s)
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400570{
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700571 int oi, oi_next, nb_temps, nb_globals;
Richard Henderson5d8f5362012-09-21 10:13:38 -0700572
Kirill Batuzov22613af2011-07-07 16:37:13 +0400573 /* Array VALS has an element for each temp.
574 If this temp holds a constant then its value is kept in VALS' element.
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200575 If this temp is a copy of other ones then the other copies are
576 available through the doubly linked circular list. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400577
578 nb_temps = s->nb_temps;
579 nb_globals = s->nb_globals;
Paolo Bonzinid193a142013-01-11 15:42:51 -0800580 reset_all_temps(nb_temps);
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400581
Richard Hendersondcb8e752016-06-22 19:42:31 -0700582 for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
Richard Henderson24666ba2014-05-22 11:14:10 -0700583 tcg_target_ulong mask, partmask, affected;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700584 int nb_oargs, nb_iargs, i;
Richard Hendersoncf066672014-03-22 20:06:52 -0700585 TCGArg tmp;
586
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700587 TCGOp * const op = &s->gen_op_buf[oi];
588 TCGArg * const args = &s->gen_opparam_buf[op->args];
589 TCGOpcode opc = op->opc;
590 const TCGOpDef *def = &tcg_op_defs[opc];
591
592 oi_next = op->next;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200593
594 /* Count the arguments, and initialize the temps that are
595 going to be used */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700596 if (opc == INDEX_op_call) {
597 nb_oargs = op->callo;
598 nb_iargs = op->calli;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200599 for (i = 0; i < nb_oargs + nb_iargs; i++) {
600 tmp = args[i];
601 if (tmp != TCG_CALL_DUMMY_ARG) {
602 init_temp_info(tmp);
603 }
604 }
Aurelien Jarno1ff8c542012-09-11 16:18:49 +0200605 } else {
Richard Hendersoncf066672014-03-22 20:06:52 -0700606 nb_oargs = def->nb_oargs;
607 nb_iargs = def->nb_iargs;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200608 for (i = 0; i < nb_oargs + nb_iargs; i++) {
609 init_temp_info(args[i]);
610 }
Richard Hendersoncf066672014-03-22 20:06:52 -0700611 }
612
613 /* Do copy propagation */
614 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200615 if (temp_is_copy(args[i])) {
Richard Hendersoncf066672014-03-22 20:06:52 -0700616 args[i] = find_better_copy(s, args[i]);
Kirill Batuzov22613af2011-07-07 16:37:13 +0400617 }
618 }
619
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400620 /* For commutative operations make constant second argument */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700621 switch (opc) {
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400622 CASE_OP_32_64(add):
623 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +0400624 CASE_OP_32_64(and):
625 CASE_OP_32_64(or):
626 CASE_OP_32_64(xor):
Richard Hendersoncb25c802011-08-17 14:11:47 -0700627 CASE_OP_32_64(eqv):
628 CASE_OP_32_64(nand):
629 CASE_OP_32_64(nor):
Richard Henderson03271522013-08-14 14:35:56 -0700630 CASE_OP_32_64(muluh):
631 CASE_OP_32_64(mulsh):
Richard Henderson24c9ae42012-10-02 11:32:21 -0700632 swap_commutative(args[0], &args[1], &args[2]);
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400633 break;
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200634 CASE_OP_32_64(brcond):
Richard Henderson24c9ae42012-10-02 11:32:21 -0700635 if (swap_commutative(-1, &args[0], &args[1])) {
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200636 args[2] = tcg_swap_cond(args[2]);
637 }
638 break;
639 CASE_OP_32_64(setcond):
Richard Henderson24c9ae42012-10-02 11:32:21 -0700640 if (swap_commutative(args[0], &args[1], &args[2])) {
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200641 args[3] = tcg_swap_cond(args[3]);
642 }
643 break;
Richard Hendersonfa01a202012-09-21 10:13:37 -0700644 CASE_OP_32_64(movcond):
Richard Henderson24c9ae42012-10-02 11:32:21 -0700645 if (swap_commutative(-1, &args[1], &args[2])) {
646 args[5] = tcg_swap_cond(args[5]);
Richard Hendersonfa01a202012-09-21 10:13:37 -0700647 }
Richard Henderson5d8f5362012-09-21 10:13:38 -0700648 /* For movcond, we canonicalize the "false" input reg to match
649 the destination reg so that the tcg backend can implement
650 a "move if true" operation. */
Richard Henderson24c9ae42012-10-02 11:32:21 -0700651 if (swap_commutative(args[0], &args[4], &args[3])) {
652 args[5] = tcg_invert_cond(args[5]);
Richard Henderson5d8f5362012-09-21 10:13:38 -0700653 }
Richard Henderson1e484e62012-10-02 11:32:22 -0700654 break;
Richard Hendersond7156f72013-02-19 23:51:52 -0800655 CASE_OP_32_64(add2):
Richard Henderson1e484e62012-10-02 11:32:22 -0700656 swap_commutative(args[0], &args[2], &args[4]);
657 swap_commutative(args[1], &args[3], &args[5]);
658 break;
Richard Hendersond7156f72013-02-19 23:51:52 -0800659 CASE_OP_32_64(mulu2):
Richard Henderson4d3203f2013-02-19 23:51:53 -0800660 CASE_OP_32_64(muls2):
Richard Henderson14149682012-10-02 11:32:30 -0700661 swap_commutative(args[0], &args[2], &args[3]);
662 break;
Richard Henderson0bfcb862012-10-02 11:32:23 -0700663 case INDEX_op_brcond2_i32:
664 if (swap_commutative2(&args[0], &args[2])) {
665 args[4] = tcg_swap_cond(args[4]);
666 }
667 break;
668 case INDEX_op_setcond2_i32:
669 if (swap_commutative2(&args[1], &args[3])) {
670 args[5] = tcg_swap_cond(args[5]);
671 }
672 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400673 default:
674 break;
675 }
676
Richard Henderson2d497542013-03-21 09:13:33 -0700677 /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
678 and "sub r, 0, a => neg r, a" case. */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700679 switch (opc) {
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200680 CASE_OP_32_64(shl):
681 CASE_OP_32_64(shr):
682 CASE_OP_32_64(sar):
683 CASE_OP_32_64(rotl):
684 CASE_OP_32_64(rotr):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200685 if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
Aurelien Jarnoebd27392015-06-04 21:53:23 +0200686 tcg_opt_gen_movi(s, op, args, args[0], 0);
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200687 continue;
688 }
689 break;
Richard Henderson2d497542013-03-21 09:13:33 -0700690 CASE_OP_32_64(sub):
691 {
692 TCGOpcode neg_op;
693 bool have_neg;
694
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200695 if (temp_is_const(args[2])) {
Richard Henderson2d497542013-03-21 09:13:33 -0700696 /* Proceed with possible constant folding. */
697 break;
698 }
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700699 if (opc == INDEX_op_sub_i32) {
Richard Henderson2d497542013-03-21 09:13:33 -0700700 neg_op = INDEX_op_neg_i32;
701 have_neg = TCG_TARGET_HAS_neg_i32;
702 } else {
703 neg_op = INDEX_op_neg_i64;
704 have_neg = TCG_TARGET_HAS_neg_i64;
705 }
706 if (!have_neg) {
707 break;
708 }
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200709 if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700710 op->opc = neg_op;
Richard Henderson2d497542013-03-21 09:13:33 -0700711 reset_temp(args[0]);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700712 args[1] = args[2];
Richard Henderson2d497542013-03-21 09:13:33 -0700713 continue;
714 }
715 }
716 break;
Richard Hendersone201b562014-01-28 13:15:38 -0800717 CASE_OP_32_64(xor):
718 CASE_OP_32_64(nand):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200719 if (!temp_is_const(args[1])
720 && temp_is_const(args[2]) && temps[args[2]].val == -1) {
Richard Hendersone201b562014-01-28 13:15:38 -0800721 i = 1;
722 goto try_not;
723 }
724 break;
725 CASE_OP_32_64(nor):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200726 if (!temp_is_const(args[1])
727 && temp_is_const(args[2]) && temps[args[2]].val == 0) {
Richard Hendersone201b562014-01-28 13:15:38 -0800728 i = 1;
729 goto try_not;
730 }
731 break;
732 CASE_OP_32_64(andc):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200733 if (!temp_is_const(args[2])
734 && temp_is_const(args[1]) && temps[args[1]].val == -1) {
Richard Hendersone201b562014-01-28 13:15:38 -0800735 i = 2;
736 goto try_not;
737 }
738 break;
739 CASE_OP_32_64(orc):
740 CASE_OP_32_64(eqv):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200741 if (!temp_is_const(args[2])
742 && temp_is_const(args[1]) && temps[args[1]].val == 0) {
Richard Hendersone201b562014-01-28 13:15:38 -0800743 i = 2;
744 goto try_not;
745 }
746 break;
747 try_not:
748 {
749 TCGOpcode not_op;
750 bool have_not;
751
752 if (def->flags & TCG_OPF_64BIT) {
753 not_op = INDEX_op_not_i64;
754 have_not = TCG_TARGET_HAS_not_i64;
755 } else {
756 not_op = INDEX_op_not_i32;
757 have_not = TCG_TARGET_HAS_not_i32;
758 }
759 if (!have_not) {
760 break;
761 }
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700762 op->opc = not_op;
Richard Hendersone201b562014-01-28 13:15:38 -0800763 reset_temp(args[0]);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700764 args[1] = args[i];
Richard Hendersone201b562014-01-28 13:15:38 -0800765 continue;
766 }
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200767 default:
768 break;
769 }
770
Richard Henderson464a1442014-01-31 07:42:11 -0600771 /* Simplify expression for "op r, a, const => mov r, a" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700772 switch (opc) {
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400773 CASE_OP_32_64(add):
774 CASE_OP_32_64(sub):
Kirill Batuzov55c09752011-07-07 16:37:16 +0400775 CASE_OP_32_64(shl):
776 CASE_OP_32_64(shr):
777 CASE_OP_32_64(sar):
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700778 CASE_OP_32_64(rotl):
779 CASE_OP_32_64(rotr):
Aurelien Jarno38ee1882012-09-06 16:47:14 +0200780 CASE_OP_32_64(or):
781 CASE_OP_32_64(xor):
Richard Henderson464a1442014-01-31 07:42:11 -0600782 CASE_OP_32_64(andc):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200783 if (!temp_is_const(args[1])
784 && temp_is_const(args[2]) && temps[args[2]].val == 0) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200785 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
786 continue;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400787 }
788 break;
Richard Henderson464a1442014-01-31 07:42:11 -0600789 CASE_OP_32_64(and):
790 CASE_OP_32_64(orc):
791 CASE_OP_32_64(eqv):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200792 if (!temp_is_const(args[1])
793 && temp_is_const(args[2]) && temps[args[2]].val == -1) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200794 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
795 continue;
Richard Henderson464a1442014-01-31 07:42:11 -0600796 }
797 break;
Aurelien Jarno56e49432012-09-06 16:47:13 +0200798 default:
799 break;
800 }
801
Aurelien Jarno30312442013-09-03 08:27:38 +0200802 /* Simplify using known-zero bits. Currently only ops with a single
803 output argument is supported. */
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800804 mask = -1;
Paolo Bonzini633f6502013-01-11 15:42:53 -0800805 affected = -1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700806 switch (opc) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800807 CASE_OP_32_64(ext8s):
808 if ((temps[args[1]].mask & 0x80) != 0) {
809 break;
810 }
811 CASE_OP_32_64(ext8u):
812 mask = 0xff;
813 goto and_const;
814 CASE_OP_32_64(ext16s):
815 if ((temps[args[1]].mask & 0x8000) != 0) {
816 break;
817 }
818 CASE_OP_32_64(ext16u):
819 mask = 0xffff;
820 goto and_const;
821 case INDEX_op_ext32s_i64:
822 if ((temps[args[1]].mask & 0x80000000) != 0) {
823 break;
824 }
825 case INDEX_op_ext32u_i64:
826 mask = 0xffffffffU;
827 goto and_const;
828
829 CASE_OP_32_64(and):
830 mask = temps[args[2]].mask;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200831 if (temp_is_const(args[2])) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800832 and_const:
Paolo Bonzini633f6502013-01-11 15:42:53 -0800833 affected = temps[args[1]].mask & ~mask;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800834 }
835 mask = temps[args[1]].mask & mask;
836 break;
837
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200838 case INDEX_op_ext_i32_i64:
839 if ((temps[args[1]].mask & 0x80000000) != 0) {
840 break;
841 }
842 case INDEX_op_extu_i32_i64:
843 /* We do not compute affected as it is a size changing op. */
844 mask = (uint32_t)temps[args[1]].mask;
845 break;
846
Richard Henderson23ec69ed2014-01-28 12:03:24 -0800847 CASE_OP_32_64(andc):
848 /* Known-zeros does not imply known-ones. Therefore unless
849 args[2] is constant, we can't infer anything from it. */
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200850 if (temp_is_const(args[2])) {
Richard Henderson23ec69ed2014-01-28 12:03:24 -0800851 mask = ~temps[args[2]].mask;
852 goto and_const;
853 }
854 /* But we certainly know nothing outside args[1] may be set. */
855 mask = temps[args[1]].mask;
856 break;
857
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200858 case INDEX_op_sar_i32:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200859 if (temp_is_const(args[2])) {
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700860 tmp = temps[args[2]].val & 31;
861 mask = (int32_t)temps[args[1]].mask >> tmp;
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200862 }
863 break;
864 case INDEX_op_sar_i64:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200865 if (temp_is_const(args[2])) {
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700866 tmp = temps[args[2]].val & 63;
867 mask = (int64_t)temps[args[1]].mask >> tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800868 }
869 break;
870
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200871 case INDEX_op_shr_i32:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200872 if (temp_is_const(args[2])) {
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700873 tmp = temps[args[2]].val & 31;
874 mask = (uint32_t)temps[args[1]].mask >> tmp;
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200875 }
876 break;
877 case INDEX_op_shr_i64:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200878 if (temp_is_const(args[2])) {
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700879 tmp = temps[args[2]].val & 63;
880 mask = (uint64_t)temps[args[1]].mask >> tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800881 }
882 break;
883
Richard Henderson609ad702015-07-24 07:16:00 -0700884 case INDEX_op_extrl_i64_i32:
885 mask = (uint32_t)temps[args[1]].mask;
886 break;
887 case INDEX_op_extrh_i64_i32:
888 mask = (uint64_t)temps[args[1]].mask >> 32;
Richard Henderson4bb7a412013-09-09 17:03:24 -0700889 break;
890
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800891 CASE_OP_32_64(shl):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200892 if (temp_is_const(args[2])) {
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700893 tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
894 mask = temps[args[1]].mask << tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800895 }
896 break;
897
898 CASE_OP_32_64(neg):
899 /* Set to 1 all bits to the left of the rightmost. */
900 mask = -(temps[args[1]].mask & -temps[args[1]].mask);
901 break;
902
903 CASE_OP_32_64(deposit):
Richard Hendersond998e552014-03-18 14:23:52 -0700904 mask = deposit64(temps[args[1]].mask, args[3], args[4],
905 temps[args[2]].mask);
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800906 break;
907
908 CASE_OP_32_64(or):
909 CASE_OP_32_64(xor):
910 mask = temps[args[1]].mask | temps[args[2]].mask;
911 break;
912
913 CASE_OP_32_64(setcond):
Richard Hendersona7635512014-04-23 22:18:30 -0700914 case INDEX_op_setcond2_i32:
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800915 mask = 1;
916 break;
917
918 CASE_OP_32_64(movcond):
919 mask = temps[args[3]].mask | temps[args[4]].mask;
920 break;
921
Aurelien Jarnoc8d70272013-09-03 08:27:39 +0200922 CASE_OP_32_64(ld8u):
Aurelien Jarnoc8d70272013-09-03 08:27:39 +0200923 mask = 0xff;
924 break;
925 CASE_OP_32_64(ld16u):
Aurelien Jarnoc8d70272013-09-03 08:27:39 +0200926 mask = 0xffff;
927 break;
928 case INDEX_op_ld32u_i64:
Aurelien Jarnoc8d70272013-09-03 08:27:39 +0200929 mask = 0xffffffffu;
930 break;
931
932 CASE_OP_32_64(qemu_ld):
933 {
Richard Henderson59227d52015-05-12 11:51:44 -0700934 TCGMemOpIdx oi = args[nb_oargs + nb_iargs];
935 TCGMemOp mop = get_memop(oi);
Aurelien Jarnoc8d70272013-09-03 08:27:39 +0200936 if (!(mop & MO_SIGN)) {
937 mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
938 }
939 }
940 break;
941
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800942 default:
943 break;
944 }
945
Richard Hendersonbc8d6882014-06-08 18:24:14 -0700946 /* 32-bit ops generate 32-bit results. For the result is zero test
947 below, we can ignore high bits, but for further optimizations we
948 need to record that the high bits contain garbage. */
Richard Henderson24666ba2014-05-22 11:14:10 -0700949 partmask = mask;
Richard Hendersonbc8d6882014-06-08 18:24:14 -0700950 if (!(def->flags & TCG_OPF_64BIT)) {
Richard Henderson24666ba2014-05-22 11:14:10 -0700951 mask |= ~(tcg_target_ulong)0xffffffffu;
952 partmask &= 0xffffffffu;
953 affected &= 0xffffffffu;
Aurelien Jarnof096dc92013-09-03 08:27:38 +0200954 }
955
Richard Henderson24666ba2014-05-22 11:14:10 -0700956 if (partmask == 0) {
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +0200957 tcg_debug_assert(nb_oargs == 1);
Aurelien Jarnoebd27392015-06-04 21:53:23 +0200958 tcg_opt_gen_movi(s, op, args, args[0], 0);
Paolo Bonzini633f6502013-01-11 15:42:53 -0800959 continue;
960 }
961 if (affected == 0) {
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +0200962 tcg_debug_assert(nb_oargs == 1);
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200963 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
Paolo Bonzini633f6502013-01-11 15:42:53 -0800964 continue;
965 }
966
Aurelien Jarno56e49432012-09-06 16:47:13 +0200967 /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700968 switch (opc) {
Aurelien Jarno61251c02012-09-06 16:47:14 +0200969 CASE_OP_32_64(and):
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400970 CASE_OP_32_64(mul):
Richard Henderson03271522013-08-14 14:35:56 -0700971 CASE_OP_32_64(muluh):
972 CASE_OP_32_64(mulsh):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200973 if ((temp_is_const(args[2]) && temps[args[2]].val == 0)) {
Aurelien Jarnoebd27392015-06-04 21:53:23 +0200974 tcg_opt_gen_movi(s, op, args, args[0], 0);
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400975 continue;
976 }
977 break;
Aurelien Jarno56e49432012-09-06 16:47:13 +0200978 default:
979 break;
980 }
981
982 /* Simplify expression for "op r, a, a => mov r, a" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700983 switch (opc) {
Kirill Batuzov9a810902011-07-07 16:37:15 +0400984 CASE_OP_32_64(or):
985 CASE_OP_32_64(and):
Aurelien Jarno0aba1c72012-09-18 19:11:32 +0200986 if (temps_are_copies(args[1], args[2])) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200987 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
Kirill Batuzov9a810902011-07-07 16:37:15 +0400988 continue;
989 }
990 break;
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000991 default:
992 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400993 }
994
Aurelien Jarno3c941932012-09-18 19:12:36 +0200995 /* Simplify expression for "op r, a, a => movi r, 0" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700996 switch (opc) {
Richard Hendersone64e9582014-01-28 13:26:17 -0800997 CASE_OP_32_64(andc):
Aurelien Jarno3c941932012-09-18 19:12:36 +0200998 CASE_OP_32_64(sub):
999 CASE_OP_32_64(xor):
1000 if (temps_are_copies(args[1], args[2])) {
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001001 tcg_opt_gen_movi(s, op, args, args[0], 0);
Aurelien Jarno3c941932012-09-18 19:12:36 +02001002 continue;
1003 }
1004 break;
1005 default:
1006 break;
1007 }
1008
Kirill Batuzov22613af2011-07-07 16:37:13 +04001009 /* Propagate constants through copy operations and do constant
1010 folding. Constants will be substituted to arguments by register
1011 allocator where needed and possible. Also detect copies. */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001012 switch (opc) {
Kirill Batuzov22613af2011-07-07 16:37:13 +04001013 CASE_OP_32_64(mov):
Aurelien Jarno97a79eb2015-06-05 11:19:18 +02001014 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
1015 break;
Kirill Batuzov22613af2011-07-07 16:37:13 +04001016 CASE_OP_32_64(movi):
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001017 tcg_opt_gen_movi(s, op, args, args[0], args[1]);
Kirill Batuzov22613af2011-07-07 16:37:13 +04001018 break;
Richard Henderson6e14e912012-10-02 11:32:24 -07001019
Kirill Batuzova640f032011-07-07 16:37:17 +04001020 CASE_OP_32_64(not):
Richard Hendersoncb25c802011-08-17 14:11:47 -07001021 CASE_OP_32_64(neg):
Richard Henderson25c4d9c2011-08-17 14:11:46 -07001022 CASE_OP_32_64(ext8s):
1023 CASE_OP_32_64(ext8u):
1024 CASE_OP_32_64(ext16s):
1025 CASE_OP_32_64(ext16u):
Kirill Batuzova640f032011-07-07 16:37:17 +04001026 case INDEX_op_ext32s_i64:
1027 case INDEX_op_ext32u_i64:
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +02001028 case INDEX_op_ext_i32_i64:
1029 case INDEX_op_extu_i32_i64:
Richard Henderson609ad702015-07-24 07:16:00 -07001030 case INDEX_op_extrl_i64_i32:
1031 case INDEX_op_extrh_i64_i32:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001032 if (temp_is_const(args[1])) {
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001033 tmp = do_constant_folding(opc, temps[args[1]].val, 0);
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001034 tcg_opt_gen_movi(s, op, args, args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001035 break;
Kirill Batuzova640f032011-07-07 16:37:17 +04001036 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001037 goto do_default;
1038
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001039 CASE_OP_32_64(add):
1040 CASE_OP_32_64(sub):
1041 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +04001042 CASE_OP_32_64(or):
1043 CASE_OP_32_64(and):
1044 CASE_OP_32_64(xor):
Kirill Batuzov55c09752011-07-07 16:37:16 +04001045 CASE_OP_32_64(shl):
1046 CASE_OP_32_64(shr):
1047 CASE_OP_32_64(sar):
Richard Henderson25c4d9c2011-08-17 14:11:46 -07001048 CASE_OP_32_64(rotl):
1049 CASE_OP_32_64(rotr):
Richard Hendersoncb25c802011-08-17 14:11:47 -07001050 CASE_OP_32_64(andc):
1051 CASE_OP_32_64(orc):
1052 CASE_OP_32_64(eqv):
1053 CASE_OP_32_64(nand):
1054 CASE_OP_32_64(nor):
Richard Henderson03271522013-08-14 14:35:56 -07001055 CASE_OP_32_64(muluh):
1056 CASE_OP_32_64(mulsh):
Richard Henderson01547f72013-08-14 15:22:46 -07001057 CASE_OP_32_64(div):
1058 CASE_OP_32_64(divu):
1059 CASE_OP_32_64(rem):
1060 CASE_OP_32_64(remu):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001061 if (temp_is_const(args[1]) && temp_is_const(args[2])) {
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001062 tmp = do_constant_folding(opc, temps[args[1]].val,
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001063 temps[args[2]].val);
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001064 tcg_opt_gen_movi(s, op, args, args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001065 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001066 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001067 goto do_default;
1068
Aurelien Jarno7ef55fc2012-09-21 11:07:29 +02001069 CASE_OP_32_64(deposit):
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001070 if (temp_is_const(args[1]) && temp_is_const(args[2])) {
Richard Hendersond998e552014-03-18 14:23:52 -07001071 tmp = deposit64(temps[args[1]].val, args[3], args[4],
1072 temps[args[2]].val);
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001073 tcg_opt_gen_movi(s, op, args, args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001074 break;
Aurelien Jarno7ef55fc2012-09-21 11:07:29 +02001075 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001076 goto do_default;
1077
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +02001078 CASE_OP_32_64(setcond):
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001079 tmp = do_constant_folding_cond(opc, args[1], args[2], args[3]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001080 if (tmp != 2) {
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001081 tcg_opt_gen_movi(s, op, args, args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001082 break;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +02001083 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001084 goto do_default;
1085
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001086 CASE_OP_32_64(brcond):
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001087 tmp = do_constant_folding_cond(opc, args[0], args[1], args[2]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001088 if (tmp != 2) {
1089 if (tmp) {
Paolo Bonzinid193a142013-01-11 15:42:51 -08001090 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001091 op->opc = INDEX_op_br;
1092 args[0] = args[3];
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001093 } else {
Richard Henderson0c627cd2014-03-30 16:51:54 -07001094 tcg_op_remove(s, op);
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001095 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001096 break;
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001097 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001098 goto do_default;
1099
Richard Hendersonfa01a202012-09-21 10:13:37 -07001100 CASE_OP_32_64(movcond):
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001101 tmp = do_constant_folding_cond(opc, args[1], args[2], args[5]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001102 if (tmp != 2) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +02001103 tcg_opt_gen_mov(s, op, args, args[0], args[4-tmp]);
Richard Henderson6e14e912012-10-02 11:32:24 -07001104 break;
Richard Hendersonfa01a202012-09-21 10:13:37 -07001105 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001106 goto do_default;
1107
Richard Henderson212c3282012-10-02 11:32:28 -07001108 case INDEX_op_add2_i32:
1109 case INDEX_op_sub2_i32:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001110 if (temp_is_const(args[2]) && temp_is_const(args[3])
1111 && temp_is_const(args[4]) && temp_is_const(args[5])) {
Richard Henderson212c3282012-10-02 11:32:28 -07001112 uint32_t al = temps[args[2]].val;
1113 uint32_t ah = temps[args[3]].val;
1114 uint32_t bl = temps[args[4]].val;
1115 uint32_t bh = temps[args[5]].val;
1116 uint64_t a = ((uint64_t)ah << 32) | al;
1117 uint64_t b = ((uint64_t)bh << 32) | bl;
1118 TCGArg rl, rh;
Richard Hendersona4ce0992014-03-30 17:14:02 -07001119 TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
1120 TCGArg *args2 = &s->gen_opparam_buf[op2->args];
Richard Henderson212c3282012-10-02 11:32:28 -07001121
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001122 if (opc == INDEX_op_add2_i32) {
Richard Henderson212c3282012-10-02 11:32:28 -07001123 a += b;
1124 } else {
1125 a -= b;
1126 }
1127
Richard Henderson212c3282012-10-02 11:32:28 -07001128 rl = args[0];
1129 rh = args[1];
Aurelien Jarno29f3ff82015-07-10 18:03:31 +02001130 tcg_opt_gen_movi(s, op, args, rl, (int32_t)a);
1131 tcg_opt_gen_movi(s, op2, args2, rh, (int32_t)(a >> 32));
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001132
1133 /* We've done all we need to do with the movi. Skip it. */
1134 oi_next = op2->next;
Richard Henderson212c3282012-10-02 11:32:28 -07001135 break;
1136 }
1137 goto do_default;
1138
Richard Henderson14149682012-10-02 11:32:30 -07001139 case INDEX_op_mulu2_i32:
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001140 if (temp_is_const(args[2]) && temp_is_const(args[3])) {
Richard Henderson14149682012-10-02 11:32:30 -07001141 uint32_t a = temps[args[2]].val;
1142 uint32_t b = temps[args[3]].val;
1143 uint64_t r = (uint64_t)a * b;
1144 TCGArg rl, rh;
Richard Hendersona4ce0992014-03-30 17:14:02 -07001145 TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
1146 TCGArg *args2 = &s->gen_opparam_buf[op2->args];
Richard Henderson14149682012-10-02 11:32:30 -07001147
1148 rl = args[0];
1149 rh = args[1];
Aurelien Jarno29f3ff82015-07-10 18:03:31 +02001150 tcg_opt_gen_movi(s, op, args, rl, (int32_t)r);
1151 tcg_opt_gen_movi(s, op2, args2, rh, (int32_t)(r >> 32));
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001152
1153 /* We've done all we need to do with the movi. Skip it. */
1154 oi_next = op2->next;
Richard Henderson14149682012-10-02 11:32:30 -07001155 break;
1156 }
1157 goto do_default;
1158
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001159 case INDEX_op_brcond2_i32:
Richard Henderson6c4382f2012-10-02 11:32:27 -07001160 tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]);
1161 if (tmp != 2) {
1162 if (tmp) {
Richard Hendersona7635512014-04-23 22:18:30 -07001163 do_brcond_true:
Paolo Bonzinid193a142013-01-11 15:42:51 -08001164 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001165 op->opc = INDEX_op_br;
1166 args[0] = args[5];
Richard Henderson6c4382f2012-10-02 11:32:27 -07001167 } else {
Richard Hendersona7635512014-04-23 22:18:30 -07001168 do_brcond_false:
Richard Henderson0c627cd2014-03-30 16:51:54 -07001169 tcg_op_remove(s, op);
Richard Henderson6c4382f2012-10-02 11:32:27 -07001170 }
1171 } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001172 && temp_is_const(args[2]) && temps[args[2]].val == 0
1173 && temp_is_const(args[3]) && temps[args[3]].val == 0) {
Richard Henderson6c4382f2012-10-02 11:32:27 -07001174 /* Simplify LT/GE comparisons vs zero to a single compare
1175 vs the high word of the input. */
Richard Hendersona7635512014-04-23 22:18:30 -07001176 do_brcond_high:
Paolo Bonzinid193a142013-01-11 15:42:51 -08001177 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001178 op->opc = INDEX_op_brcond_i32;
1179 args[0] = args[1];
1180 args[1] = args[3];
1181 args[2] = args[4];
1182 args[3] = args[5];
Richard Hendersona7635512014-04-23 22:18:30 -07001183 } else if (args[4] == TCG_COND_EQ) {
1184 /* Simplify EQ comparisons where one of the pairs
1185 can be simplified. */
1186 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1187 args[0], args[2], TCG_COND_EQ);
1188 if (tmp == 0) {
1189 goto do_brcond_false;
1190 } else if (tmp == 1) {
1191 goto do_brcond_high;
1192 }
1193 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1194 args[1], args[3], TCG_COND_EQ);
1195 if (tmp == 0) {
1196 goto do_brcond_false;
1197 } else if (tmp != 1) {
1198 goto do_default;
1199 }
1200 do_brcond_low:
1201 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001202 op->opc = INDEX_op_brcond_i32;
1203 args[1] = args[2];
1204 args[2] = args[4];
1205 args[3] = args[5];
Richard Hendersona7635512014-04-23 22:18:30 -07001206 } else if (args[4] == TCG_COND_NE) {
1207 /* Simplify NE comparisons where one of the pairs
1208 can be simplified. */
1209 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1210 args[0], args[2], TCG_COND_NE);
1211 if (tmp == 0) {
1212 goto do_brcond_high;
1213 } else if (tmp == 1) {
1214 goto do_brcond_true;
1215 }
1216 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1217 args[1], args[3], TCG_COND_NE);
1218 if (tmp == 0) {
1219 goto do_brcond_low;
1220 } else if (tmp == 1) {
1221 goto do_brcond_true;
1222 }
1223 goto do_default;
Richard Henderson6c4382f2012-10-02 11:32:27 -07001224 } else {
1225 goto do_default;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001226 }
Richard Henderson6c4382f2012-10-02 11:32:27 -07001227 break;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001228
1229 case INDEX_op_setcond2_i32:
Richard Henderson6c4382f2012-10-02 11:32:27 -07001230 tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
1231 if (tmp != 2) {
Richard Hendersona7635512014-04-23 22:18:30 -07001232 do_setcond_const:
Aurelien Jarnoebd27392015-06-04 21:53:23 +02001233 tcg_opt_gen_movi(s, op, args, args[0], tmp);
Richard Henderson6c4382f2012-10-02 11:32:27 -07001234 } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +02001235 && temp_is_const(args[3]) && temps[args[3]].val == 0
1236 && temp_is_const(args[4]) && temps[args[4]].val == 0) {
Richard Henderson6c4382f2012-10-02 11:32:27 -07001237 /* Simplify LT/GE comparisons vs zero to a single compare
1238 vs the high word of the input. */
Richard Hendersona7635512014-04-23 22:18:30 -07001239 do_setcond_high:
Aurelien Jarno66e61b52013-05-08 22:36:39 +02001240 reset_temp(args[0]);
Richard Hendersona7635512014-04-23 22:18:30 -07001241 temps[args[0]].mask = 1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001242 op->opc = INDEX_op_setcond_i32;
1243 args[1] = args[2];
1244 args[2] = args[4];
1245 args[3] = args[5];
Richard Hendersona7635512014-04-23 22:18:30 -07001246 } else if (args[5] == TCG_COND_EQ) {
1247 /* Simplify EQ comparisons where one of the pairs
1248 can be simplified. */
1249 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1250 args[1], args[3], TCG_COND_EQ);
1251 if (tmp == 0) {
1252 goto do_setcond_const;
1253 } else if (tmp == 1) {
1254 goto do_setcond_high;
1255 }
1256 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1257 args[2], args[4], TCG_COND_EQ);
1258 if (tmp == 0) {
1259 goto do_setcond_high;
1260 } else if (tmp != 1) {
1261 goto do_default;
1262 }
1263 do_setcond_low:
1264 reset_temp(args[0]);
1265 temps[args[0]].mask = 1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001266 op->opc = INDEX_op_setcond_i32;
1267 args[2] = args[3];
1268 args[3] = args[5];
Richard Hendersona7635512014-04-23 22:18:30 -07001269 } else if (args[5] == TCG_COND_NE) {
1270 /* Simplify NE comparisons where one of the pairs
1271 can be simplified. */
1272 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1273 args[1], args[3], TCG_COND_NE);
1274 if (tmp == 0) {
1275 goto do_setcond_high;
1276 } else if (tmp == 1) {
1277 goto do_setcond_const;
1278 }
1279 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1280 args[2], args[4], TCG_COND_NE);
1281 if (tmp == 0) {
1282 goto do_setcond_low;
1283 } else if (tmp == 1) {
1284 goto do_setcond_const;
1285 }
1286 goto do_default;
Richard Henderson6c4382f2012-10-02 11:32:27 -07001287 } else {
1288 goto do_default;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001289 }
Richard Henderson6c4382f2012-10-02 11:32:27 -07001290 break;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001291
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001292 case INDEX_op_call:
Richard Hendersoncf066672014-03-22 20:06:52 -07001293 if (!(args[nb_oargs + nb_iargs + 1]
1294 & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
Kirill Batuzov22613af2011-07-07 16:37:13 +04001295 for (i = 0; i < nb_globals; i++) {
Aurelien Jarno1208d7d2015-07-27 12:41:44 +02001296 if (test_bit(i, temps_used.l)) {
1297 reset_temp(i);
1298 }
Kirill Batuzov22613af2011-07-07 16:37:13 +04001299 }
1300 }
Richard Hendersoncf066672014-03-22 20:06:52 -07001301 goto do_reset_output;
Richard Henderson6e14e912012-10-02 11:32:24 -07001302
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001303 default:
Richard Henderson6e14e912012-10-02 11:32:24 -07001304 do_default:
1305 /* Default case: we know nothing about operation (or were unable
1306 to compute the operation result) so no propagation is done.
1307 We trash everything if the operation is the end of a basic
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -08001308 block, otherwise we only trash the output args. "mask" is
1309 the non-zero bits mask for the first output arg. */
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001310 if (def->flags & TCG_OPF_BB_END) {
Paolo Bonzinid193a142013-01-11 15:42:51 -08001311 reset_all_temps(nb_temps);
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001312 } else {
Richard Hendersoncf066672014-03-22 20:06:52 -07001313 do_reset_output:
1314 for (i = 0; i < nb_oargs; i++) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +02001315 reset_temp(args[i]);
Aurelien Jarno30312442013-09-03 08:27:38 +02001316 /* Save the corresponding known-zero bits mask for the
1317 first output argument (only one supported so far). */
1318 if (i == 0) {
1319 temps[args[i]].mask = mask;
1320 }
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001321 }
Kirill Batuzov22613af2011-07-07 16:37:13 +04001322 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001323 break;
1324 }
1325 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001326}