blob: 66daced1671f67721090ade7d7e9c43383271296 [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;
Richard Henderson63490392017-06-20 13:43:15 -070037 TCGTemp *prev_copy;
38 TCGTemp *next_copy;
Kirill Batuzov22613af2011-07-07 16:37:13 +040039 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
Richard Henderson63490392017-06-20 13:43:15 -070046static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020047{
Richard Henderson63490392017-06-20 13:43:15 -070048 return ts->state_ptr;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020049}
50
Richard Henderson63490392017-06-20 13:43:15 -070051static inline struct tcg_temp_info *arg_info(TCGArg arg)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020052{
Richard Henderson63490392017-06-20 13:43:15 -070053 return ts_info(arg_temp(arg));
54}
55
56static inline bool ts_is_const(TCGTemp *ts)
57{
58 return ts_info(ts)->is_const;
59}
60
61static inline bool arg_is_const(TCGArg arg)
62{
63 return ts_is_const(arg_temp(arg));
64}
65
66static inline bool ts_is_copy(TCGTemp *ts)
67{
68 return ts_info(ts)->next_copy != ts;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020069}
70
Aurelien Jarnob41059d2015-07-27 12:41:44 +020071/* Reset TEMP's state, possibly removing the temp for the list of copies. */
Richard Henderson63490392017-06-20 13:43:15 -070072static void reset_ts(TCGTemp *ts)
Kirill Batuzov22613af2011-07-07 16:37:13 +040073{
Richard Henderson63490392017-06-20 13:43:15 -070074 struct tcg_temp_info *ti = ts_info(ts);
75 struct tcg_temp_info *pi = ts_info(ti->prev_copy);
76 struct tcg_temp_info *ni = ts_info(ti->next_copy);
77
78 ni->prev_copy = ti->prev_copy;
79 pi->next_copy = ti->next_copy;
80 ti->next_copy = ts;
81 ti->prev_copy = ts;
82 ti->is_const = false;
83 ti->mask = -1;
84}
85
86static void reset_temp(TCGArg arg)
87{
88 reset_ts(arg_temp(arg));
Kirill Batuzov22613af2011-07-07 16:37:13 +040089}
90
Aurelien Jarno1208d7d2015-07-27 12:41:44 +020091/* Reset all temporaries, given that there are NB_TEMPS of them. */
92static void reset_all_temps(int nb_temps)
93{
94 bitmap_zero(temps_used.l, nb_temps);
95}
96
97/* Initialize and activate a temporary. */
Richard Henderson63490392017-06-20 13:43:15 -070098static void init_ts_info(TCGTemp *ts)
Aurelien Jarno1208d7d2015-07-27 12:41:44 +020099{
Richard Henderson63490392017-06-20 13:43:15 -0700100 size_t idx = temp_idx(ts);
101 if (!test_bit(idx, temps_used.l)) {
102 struct tcg_temp_info *ti = &temps[idx];
103
104 ts->state_ptr = ti;
105 ti->next_copy = ts;
106 ti->prev_copy = ts;
107 ti->is_const = false;
108 ti->mask = -1;
109 set_bit(idx, temps_used.l);
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200110 }
111}
112
Richard Henderson63490392017-06-20 13:43:15 -0700113static void init_arg_info(TCGArg arg)
114{
115 init_ts_info(arg_temp(arg));
116}
117
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000118static int op_bits(TCGOpcode op)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400119{
Richard Henderson8399ad52011-08-17 14:11:45 -0700120 const TCGOpDef *def = &tcg_op_defs[op];
121 return def->flags & TCG_OPF_64BIT ? 64 : 32;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400122}
123
Richard Hendersona62f6f52014-05-22 10:59:12 -0700124static TCGOpcode op_to_mov(TCGOpcode op)
125{
126 switch (op_bits(op)) {
127 case 32:
128 return INDEX_op_mov_i32;
129 case 64:
130 return INDEX_op_mov_i64;
131 default:
132 fprintf(stderr, "op_to_mov: unexpected return value of "
133 "function op_bits.\n");
134 tcg_abort();
135 }
136}
137
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000138static TCGOpcode op_to_movi(TCGOpcode op)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400139{
140 switch (op_bits(op)) {
141 case 32:
142 return INDEX_op_movi_i32;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400143 case 64:
144 return INDEX_op_movi_i64;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400145 default:
146 fprintf(stderr, "op_to_movi: unexpected return value of "
147 "function op_bits.\n");
148 tcg_abort();
149 }
150}
151
Richard Henderson63490392017-06-20 13:43:15 -0700152static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200153{
Richard Henderson63490392017-06-20 13:43:15 -0700154 TCGTemp *i;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200155
156 /* If this is already a global, we can't do better. */
Richard Hendersonfa477d22016-11-02 11:20:15 -0600157 if (ts->temp_global) {
Richard Henderson63490392017-06-20 13:43:15 -0700158 return ts;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200159 }
160
161 /* Search for a global first. */
Richard Henderson63490392017-06-20 13:43:15 -0700162 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
163 if (i->temp_global) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200164 return i;
165 }
166 }
167
168 /* If it is a temp, search for a temp local. */
Richard Hendersonfa477d22016-11-02 11:20:15 -0600169 if (!ts->temp_local) {
Richard Henderson63490392017-06-20 13:43:15 -0700170 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
171 if (ts->temp_local) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200172 return i;
173 }
174 }
175 }
176
177 /* Failure to find a better representation, return the same temp. */
Richard Henderson63490392017-06-20 13:43:15 -0700178 return ts;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200179}
180
Richard Henderson63490392017-06-20 13:43:15 -0700181static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200182{
Richard Henderson63490392017-06-20 13:43:15 -0700183 TCGTemp *i;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200184
Richard Henderson63490392017-06-20 13:43:15 -0700185 if (ts1 == ts2) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200186 return true;
187 }
188
Richard Henderson63490392017-06-20 13:43:15 -0700189 if (!ts_is_copy(ts1) || !ts_is_copy(ts2)) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200190 return false;
191 }
192
Richard Henderson63490392017-06-20 13:43:15 -0700193 for (i = ts_info(ts1)->next_copy; i != ts1; i = ts_info(i)->next_copy) {
194 if (i == ts2) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200195 return true;
196 }
197 }
198
199 return false;
200}
201
Richard Henderson63490392017-06-20 13:43:15 -0700202static bool args_are_copies(TCGArg arg1, TCGArg arg2)
203{
204 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
205}
206
Richard Hendersonacd93702016-12-08 12:28:42 -0800207static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200208{
209 TCGOpcode new_op = op_to_movi(op->opc);
210 tcg_target_ulong mask;
Richard Henderson63490392017-06-20 13:43:15 -0700211 struct tcg_temp_info *di = arg_info(dst);
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200212
213 op->opc = new_op;
214
215 reset_temp(dst);
Richard Henderson63490392017-06-20 13:43:15 -0700216 di->is_const = true;
217 di->val = val;
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200218 mask = val;
Aurelien Jarno96152122015-07-10 18:03:30 +0200219 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200220 /* High bits of the destination are now garbage. */
221 mask |= ~0xffffffffull;
222 }
Richard Henderson63490392017-06-20 13:43:15 -0700223 di->mask = mask;
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200224
Richard Hendersonacd93702016-12-08 12:28:42 -0800225 op->args[0] = dst;
226 op->args[1] = val;
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200227}
228
Richard Hendersonacd93702016-12-08 12:28:42 -0800229static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400230{
Richard Henderson63490392017-06-20 13:43:15 -0700231 TCGTemp *dst_ts = arg_temp(dst);
232 TCGTemp *src_ts = arg_temp(src);
233 struct tcg_temp_info *di;
234 struct tcg_temp_info *si;
235 tcg_target_ulong mask;
236 TCGOpcode new_op;
237
238 if (ts_are_copies(dst_ts, src_ts)) {
Aurelien Jarno53657182015-06-04 21:53:25 +0200239 tcg_op_remove(s, op);
240 return;
241 }
242
Richard Henderson63490392017-06-20 13:43:15 -0700243 reset_ts(dst_ts);
244 di = ts_info(dst_ts);
245 si = ts_info(src_ts);
246 new_op = op_to_mov(op->opc);
Richard Hendersona62f6f52014-05-22 10:59:12 -0700247
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700248 op->opc = new_op;
Richard Henderson63490392017-06-20 13:43:15 -0700249 op->args[0] = dst;
250 op->args[1] = src;
Richard Hendersona62f6f52014-05-22 10:59:12 -0700251
Richard Henderson63490392017-06-20 13:43:15 -0700252 mask = si->mask;
Richard Henderson24666ba2014-05-22 11:14:10 -0700253 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
254 /* High bits of the destination are now garbage. */
255 mask |= ~0xffffffffull;
256 }
Richard Henderson63490392017-06-20 13:43:15 -0700257 di->mask = mask;
Richard Henderson24666ba2014-05-22 11:14:10 -0700258
Richard Henderson63490392017-06-20 13:43:15 -0700259 if (src_ts->type == dst_ts->type) {
260 struct tcg_temp_info *ni = ts_info(si->next_copy);
261
262 di->next_copy = si->next_copy;
263 di->prev_copy = src_ts;
264 ni->prev_copy = dst_ts;
265 si->next_copy = dst_ts;
266 di->is_const = si->is_const;
267 di->val = si->val;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800268 }
Kirill Batuzov22613af2011-07-07 16:37:13 +0400269}
270
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000271static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400272{
Richard Henderson03271522013-08-14 14:35:56 -0700273 uint64_t l64, h64;
274
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400275 switch (op) {
276 CASE_OP_32_64(add):
277 return x + y;
278
279 CASE_OP_32_64(sub):
280 return x - y;
281
282 CASE_OP_32_64(mul):
283 return x * y;
284
Kirill Batuzov9a810902011-07-07 16:37:15 +0400285 CASE_OP_32_64(and):
286 return x & y;
287
288 CASE_OP_32_64(or):
289 return x | y;
290
291 CASE_OP_32_64(xor):
292 return x ^ y;
293
Kirill Batuzov55c09752011-07-07 16:37:16 +0400294 case INDEX_op_shl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700295 return (uint32_t)x << (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400296
Kirill Batuzov55c09752011-07-07 16:37:16 +0400297 case INDEX_op_shl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700298 return (uint64_t)x << (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400299
300 case INDEX_op_shr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700301 return (uint32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400302
Kirill Batuzov55c09752011-07-07 16:37:16 +0400303 case INDEX_op_shr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700304 return (uint64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400305
306 case INDEX_op_sar_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700307 return (int32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400308
Kirill Batuzov55c09752011-07-07 16:37:16 +0400309 case INDEX_op_sar_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700310 return (int64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400311
312 case INDEX_op_rotr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700313 return ror32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400314
Kirill Batuzov55c09752011-07-07 16:37:16 +0400315 case INDEX_op_rotr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700316 return ror64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400317
318 case INDEX_op_rotl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700319 return rol32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400320
Kirill Batuzov55c09752011-07-07 16:37:16 +0400321 case INDEX_op_rotl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700322 return rol64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400323
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700324 CASE_OP_32_64(not):
Kirill Batuzova640f032011-07-07 16:37:17 +0400325 return ~x;
326
Richard Hendersoncb25c802011-08-17 14:11:47 -0700327 CASE_OP_32_64(neg):
328 return -x;
329
330 CASE_OP_32_64(andc):
331 return x & ~y;
332
333 CASE_OP_32_64(orc):
334 return x | ~y;
335
336 CASE_OP_32_64(eqv):
337 return ~(x ^ y);
338
339 CASE_OP_32_64(nand):
340 return ~(x & y);
341
342 CASE_OP_32_64(nor):
343 return ~(x | y);
344
Richard Henderson0e28d002016-11-16 09:23:28 +0100345 case INDEX_op_clz_i32:
346 return (uint32_t)x ? clz32(x) : y;
347
348 case INDEX_op_clz_i64:
349 return x ? clz64(x) : y;
350
351 case INDEX_op_ctz_i32:
352 return (uint32_t)x ? ctz32(x) : y;
353
354 case INDEX_op_ctz_i64:
355 return x ? ctz64(x) : y;
356
Richard Hendersona768e4e2016-11-21 11:13:39 +0100357 case INDEX_op_ctpop_i32:
358 return ctpop32(x);
359
360 case INDEX_op_ctpop_i64:
361 return ctpop64(x);
362
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700363 CASE_OP_32_64(ext8s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400364 return (int8_t)x;
365
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700366 CASE_OP_32_64(ext16s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400367 return (int16_t)x;
368
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700369 CASE_OP_32_64(ext8u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400370 return (uint8_t)x;
371
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700372 CASE_OP_32_64(ext16u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400373 return (uint16_t)x;
374
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200375 case INDEX_op_ext_i32_i64:
Kirill Batuzova640f032011-07-07 16:37:17 +0400376 case INDEX_op_ext32s_i64:
377 return (int32_t)x;
378
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200379 case INDEX_op_extu_i32_i64:
Richard Henderson609ad702015-07-24 07:16:00 -0700380 case INDEX_op_extrl_i64_i32:
Kirill Batuzova640f032011-07-07 16:37:17 +0400381 case INDEX_op_ext32u_i64:
382 return (uint32_t)x;
Kirill Batuzova640f032011-07-07 16:37:17 +0400383
Richard Henderson609ad702015-07-24 07:16:00 -0700384 case INDEX_op_extrh_i64_i32:
385 return (uint64_t)x >> 32;
386
Richard Henderson03271522013-08-14 14:35:56 -0700387 case INDEX_op_muluh_i32:
388 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
389 case INDEX_op_mulsh_i32:
390 return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
391
392 case INDEX_op_muluh_i64:
393 mulu64(&l64, &h64, x, y);
394 return h64;
395 case INDEX_op_mulsh_i64:
396 muls64(&l64, &h64, x, y);
397 return h64;
398
Richard Henderson01547f72013-08-14 15:22:46 -0700399 case INDEX_op_div_i32:
400 /* Avoid crashing on divide by zero, otherwise undefined. */
401 return (int32_t)x / ((int32_t)y ? : 1);
402 case INDEX_op_divu_i32:
403 return (uint32_t)x / ((uint32_t)y ? : 1);
404 case INDEX_op_div_i64:
405 return (int64_t)x / ((int64_t)y ? : 1);
406 case INDEX_op_divu_i64:
407 return (uint64_t)x / ((uint64_t)y ? : 1);
408
409 case INDEX_op_rem_i32:
410 return (int32_t)x % ((int32_t)y ? : 1);
411 case INDEX_op_remu_i32:
412 return (uint32_t)x % ((uint32_t)y ? : 1);
413 case INDEX_op_rem_i64:
414 return (int64_t)x % ((int64_t)y ? : 1);
415 case INDEX_op_remu_i64:
416 return (uint64_t)x % ((uint64_t)y ? : 1);
417
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400418 default:
419 fprintf(stderr,
420 "Unrecognized operation %d in do_constant_folding.\n", op);
421 tcg_abort();
422 }
423}
424
Blue Swirlfe0de7a2011-07-30 19:18:32 +0000425static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400426{
427 TCGArg res = do_constant_folding_2(op, x, y);
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400428 if (op_bits(op) == 32) {
Aurelien Jarno29f3ff82015-07-10 18:03:31 +0200429 res = (int32_t)res;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400430 }
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400431 return res;
432}
433
Richard Henderson9519da72012-10-02 11:32:26 -0700434static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
435{
436 switch (c) {
437 case TCG_COND_EQ:
438 return x == y;
439 case TCG_COND_NE:
440 return x != y;
441 case TCG_COND_LT:
442 return (int32_t)x < (int32_t)y;
443 case TCG_COND_GE:
444 return (int32_t)x >= (int32_t)y;
445 case TCG_COND_LE:
446 return (int32_t)x <= (int32_t)y;
447 case TCG_COND_GT:
448 return (int32_t)x > (int32_t)y;
449 case TCG_COND_LTU:
450 return x < y;
451 case TCG_COND_GEU:
452 return x >= y;
453 case TCG_COND_LEU:
454 return x <= y;
455 case TCG_COND_GTU:
456 return x > y;
457 default:
458 tcg_abort();
459 }
460}
461
462static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
463{
464 switch (c) {
465 case TCG_COND_EQ:
466 return x == y;
467 case TCG_COND_NE:
468 return x != y;
469 case TCG_COND_LT:
470 return (int64_t)x < (int64_t)y;
471 case TCG_COND_GE:
472 return (int64_t)x >= (int64_t)y;
473 case TCG_COND_LE:
474 return (int64_t)x <= (int64_t)y;
475 case TCG_COND_GT:
476 return (int64_t)x > (int64_t)y;
477 case TCG_COND_LTU:
478 return x < y;
479 case TCG_COND_GEU:
480 return x >= y;
481 case TCG_COND_LEU:
482 return x <= y;
483 case TCG_COND_GTU:
484 return x > y;
485 default:
486 tcg_abort();
487 }
488}
489
490static bool do_constant_folding_cond_eq(TCGCond c)
491{
492 switch (c) {
493 case TCG_COND_GT:
494 case TCG_COND_LTU:
495 case TCG_COND_LT:
496 case TCG_COND_GTU:
497 case TCG_COND_NE:
498 return 0;
499 case TCG_COND_GE:
500 case TCG_COND_GEU:
501 case TCG_COND_LE:
502 case TCG_COND_LEU:
503 case TCG_COND_EQ:
504 return 1;
505 default:
506 tcg_abort();
507 }
508}
509
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200510/* Return 2 if the condition can't be simplified, and the result
511 of the condition (0 or 1) if it can */
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200512static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
513 TCGArg y, TCGCond c)
514{
Richard Henderson63490392017-06-20 13:43:15 -0700515 tcg_target_ulong xv = arg_info(x)->val;
516 tcg_target_ulong yv = arg_info(y)->val;
517 if (arg_is_const(x) && arg_is_const(y)) {
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200518 switch (op_bits(op)) {
519 case 32:
Richard Henderson63490392017-06-20 13:43:15 -0700520 return do_constant_folding_cond_32(xv, yv, c);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200521 case 64:
Richard Henderson63490392017-06-20 13:43:15 -0700522 return do_constant_folding_cond_64(xv, yv, c);
Richard Henderson9519da72012-10-02 11:32:26 -0700523 default:
524 tcg_abort();
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200525 }
Richard Henderson63490392017-06-20 13:43:15 -0700526 } else if (args_are_copies(x, y)) {
Richard Henderson9519da72012-10-02 11:32:26 -0700527 return do_constant_folding_cond_eq(c);
Richard Henderson63490392017-06-20 13:43:15 -0700528 } else if (arg_is_const(y) && yv == 0) {
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200529 switch (c) {
530 case TCG_COND_LTU:
531 return 0;
532 case TCG_COND_GEU:
533 return 1;
534 default:
535 return 2;
536 }
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200537 }
Alex Bennée550276a2016-09-30 22:30:55 +0100538 return 2;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200539}
540
Richard Henderson6c4382f2012-10-02 11:32:27 -0700541/* Return 2 if the condition can't be simplified, and the result
542 of the condition (0 or 1) if it can */
543static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
544{
545 TCGArg al = p1[0], ah = p1[1];
546 TCGArg bl = p2[0], bh = p2[1];
547
Richard Henderson63490392017-06-20 13:43:15 -0700548 if (arg_is_const(bl) && arg_is_const(bh)) {
549 tcg_target_ulong blv = arg_info(bl)->val;
550 tcg_target_ulong bhv = arg_info(bh)->val;
551 uint64_t b = deposit64(blv, 32, 32, bhv);
Richard Henderson6c4382f2012-10-02 11:32:27 -0700552
Richard Henderson63490392017-06-20 13:43:15 -0700553 if (arg_is_const(al) && arg_is_const(ah)) {
554 tcg_target_ulong alv = arg_info(al)->val;
555 tcg_target_ulong ahv = arg_info(ah)->val;
556 uint64_t a = deposit64(alv, 32, 32, ahv);
Richard Henderson6c4382f2012-10-02 11:32:27 -0700557 return do_constant_folding_cond_64(a, b, c);
558 }
559 if (b == 0) {
560 switch (c) {
561 case TCG_COND_LTU:
562 return 0;
563 case TCG_COND_GEU:
564 return 1;
565 default:
566 break;
567 }
568 }
569 }
Richard Henderson63490392017-06-20 13:43:15 -0700570 if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
Richard Henderson6c4382f2012-10-02 11:32:27 -0700571 return do_constant_folding_cond_eq(c);
572 }
573 return 2;
574}
575
Richard Henderson24c9ae42012-10-02 11:32:21 -0700576static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
577{
578 TCGArg a1 = *p1, a2 = *p2;
579 int sum = 0;
Richard Henderson63490392017-06-20 13:43:15 -0700580 sum += arg_is_const(a1);
581 sum -= arg_is_const(a2);
Richard Henderson24c9ae42012-10-02 11:32:21 -0700582
583 /* Prefer the constant in second argument, and then the form
584 op a, a, b, which is better handled on non-RISC hosts. */
585 if (sum > 0 || (sum == 0 && dest == a2)) {
586 *p1 = a2;
587 *p2 = a1;
588 return true;
589 }
590 return false;
591}
592
Richard Henderson0bfcb862012-10-02 11:32:23 -0700593static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
594{
595 int sum = 0;
Richard Henderson63490392017-06-20 13:43:15 -0700596 sum += arg_is_const(p1[0]);
597 sum += arg_is_const(p1[1]);
598 sum -= arg_is_const(p2[0]);
599 sum -= arg_is_const(p2[1]);
Richard Henderson0bfcb862012-10-02 11:32:23 -0700600 if (sum > 0) {
601 TCGArg t;
602 t = p1[0], p1[0] = p2[0], p2[0] = t;
603 t = p1[1], p1[1] = p2[1], p2[1] = t;
604 return true;
605 }
606 return false;
607}
608
Kirill Batuzov22613af2011-07-07 16:37:13 +0400609/* Propagate constants and copies, fold constant expressions. */
Aurelien Jarno36e60ef2015-06-04 21:53:27 +0200610void tcg_optimize(TCGContext *s)
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400611{
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700612 int oi, oi_next, nb_temps, nb_globals;
Richard Hendersonacd93702016-12-08 12:28:42 -0800613 TCGOp *prev_mb = NULL;
Richard Henderson5d8f5362012-09-21 10:13:38 -0700614
Kirill Batuzov22613af2011-07-07 16:37:13 +0400615 /* Array VALS has an element for each temp.
616 If this temp holds a constant then its value is kept in VALS' element.
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200617 If this temp is a copy of other ones then the other copies are
618 available through the doubly linked circular list. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400619
620 nb_temps = s->nb_temps;
621 nb_globals = s->nb_globals;
Paolo Bonzinid193a142013-01-11 15:42:51 -0800622 reset_all_temps(nb_temps);
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +0400623
Richard Hendersondcb8e752016-06-22 19:42:31 -0700624 for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
Richard Henderson24666ba2014-05-22 11:14:10 -0700625 tcg_target_ulong mask, partmask, affected;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700626 int nb_oargs, nb_iargs, i;
Richard Hendersoncf066672014-03-22 20:06:52 -0700627 TCGArg tmp;
628
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700629 TCGOp * const op = &s->gen_op_buf[oi];
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700630 TCGOpcode opc = op->opc;
631 const TCGOpDef *def = &tcg_op_defs[opc];
632
633 oi_next = op->next;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200634
635 /* Count the arguments, and initialize the temps that are
636 going to be used */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700637 if (opc == INDEX_op_call) {
638 nb_oargs = op->callo;
639 nb_iargs = op->calli;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200640 for (i = 0; i < nb_oargs + nb_iargs; i++) {
Richard Henderson63490392017-06-20 13:43:15 -0700641 TCGTemp *ts = arg_temp(op->args[i]);
642 if (ts) {
643 init_ts_info(ts);
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200644 }
645 }
Aurelien Jarno1ff8c542012-09-11 16:18:49 +0200646 } else {
Richard Hendersoncf066672014-03-22 20:06:52 -0700647 nb_oargs = def->nb_oargs;
648 nb_iargs = def->nb_iargs;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200649 for (i = 0; i < nb_oargs + nb_iargs; i++) {
Richard Henderson63490392017-06-20 13:43:15 -0700650 init_arg_info(op->args[i]);
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200651 }
Richard Hendersoncf066672014-03-22 20:06:52 -0700652 }
653
654 /* Do copy propagation */
655 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
Richard Henderson63490392017-06-20 13:43:15 -0700656 TCGTemp *ts = arg_temp(op->args[i]);
657 if (ts && ts_is_copy(ts)) {
658 op->args[i] = temp_arg(find_better_copy(s, ts));
Kirill Batuzov22613af2011-07-07 16:37:13 +0400659 }
660 }
661
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400662 /* For commutative operations make constant second argument */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700663 switch (opc) {
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400664 CASE_OP_32_64(add):
665 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +0400666 CASE_OP_32_64(and):
667 CASE_OP_32_64(or):
668 CASE_OP_32_64(xor):
Richard Hendersoncb25c802011-08-17 14:11:47 -0700669 CASE_OP_32_64(eqv):
670 CASE_OP_32_64(nand):
671 CASE_OP_32_64(nor):
Richard Henderson03271522013-08-14 14:35:56 -0700672 CASE_OP_32_64(muluh):
673 CASE_OP_32_64(mulsh):
Richard Hendersonacd93702016-12-08 12:28:42 -0800674 swap_commutative(op->args[0], &op->args[1], &op->args[2]);
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400675 break;
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200676 CASE_OP_32_64(brcond):
Richard Hendersonacd93702016-12-08 12:28:42 -0800677 if (swap_commutative(-1, &op->args[0], &op->args[1])) {
678 op->args[2] = tcg_swap_cond(op->args[2]);
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200679 }
680 break;
681 CASE_OP_32_64(setcond):
Richard Hendersonacd93702016-12-08 12:28:42 -0800682 if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
683 op->args[3] = tcg_swap_cond(op->args[3]);
Aurelien Jarno65a7cce2012-09-06 16:47:14 +0200684 }
685 break;
Richard Hendersonfa01a202012-09-21 10:13:37 -0700686 CASE_OP_32_64(movcond):
Richard Hendersonacd93702016-12-08 12:28:42 -0800687 if (swap_commutative(-1, &op->args[1], &op->args[2])) {
688 op->args[5] = tcg_swap_cond(op->args[5]);
Richard Hendersonfa01a202012-09-21 10:13:37 -0700689 }
Richard Henderson5d8f5362012-09-21 10:13:38 -0700690 /* For movcond, we canonicalize the "false" input reg to match
691 the destination reg so that the tcg backend can implement
692 a "move if true" operation. */
Richard Hendersonacd93702016-12-08 12:28:42 -0800693 if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
694 op->args[5] = tcg_invert_cond(op->args[5]);
Richard Henderson5d8f5362012-09-21 10:13:38 -0700695 }
Richard Henderson1e484e62012-10-02 11:32:22 -0700696 break;
Richard Hendersond7156f72013-02-19 23:51:52 -0800697 CASE_OP_32_64(add2):
Richard Hendersonacd93702016-12-08 12:28:42 -0800698 swap_commutative(op->args[0], &op->args[2], &op->args[4]);
699 swap_commutative(op->args[1], &op->args[3], &op->args[5]);
Richard Henderson1e484e62012-10-02 11:32:22 -0700700 break;
Richard Hendersond7156f72013-02-19 23:51:52 -0800701 CASE_OP_32_64(mulu2):
Richard Henderson4d3203f2013-02-19 23:51:53 -0800702 CASE_OP_32_64(muls2):
Richard Hendersonacd93702016-12-08 12:28:42 -0800703 swap_commutative(op->args[0], &op->args[2], &op->args[3]);
Richard Henderson14149682012-10-02 11:32:30 -0700704 break;
Richard Henderson0bfcb862012-10-02 11:32:23 -0700705 case INDEX_op_brcond2_i32:
Richard Hendersonacd93702016-12-08 12:28:42 -0800706 if (swap_commutative2(&op->args[0], &op->args[2])) {
707 op->args[4] = tcg_swap_cond(op->args[4]);
Richard Henderson0bfcb862012-10-02 11:32:23 -0700708 }
709 break;
710 case INDEX_op_setcond2_i32:
Richard Hendersonacd93702016-12-08 12:28:42 -0800711 if (swap_commutative2(&op->args[1], &op->args[3])) {
712 op->args[5] = tcg_swap_cond(op->args[5]);
Richard Henderson0bfcb862012-10-02 11:32:23 -0700713 }
714 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400715 default:
716 break;
717 }
718
Richard Henderson2d497542013-03-21 09:13:33 -0700719 /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
720 and "sub r, 0, a => neg r, a" case. */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700721 switch (opc) {
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200722 CASE_OP_32_64(shl):
723 CASE_OP_32_64(shr):
724 CASE_OP_32_64(sar):
725 CASE_OP_32_64(rotl):
726 CASE_OP_32_64(rotr):
Richard Henderson63490392017-06-20 13:43:15 -0700727 if (arg_is_const(op->args[1])
728 && arg_info(op->args[1])->val == 0) {
Richard Hendersonacd93702016-12-08 12:28:42 -0800729 tcg_opt_gen_movi(s, op, op->args[0], 0);
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200730 continue;
731 }
732 break;
Richard Henderson2d497542013-03-21 09:13:33 -0700733 CASE_OP_32_64(sub):
734 {
735 TCGOpcode neg_op;
736 bool have_neg;
737
Richard Henderson63490392017-06-20 13:43:15 -0700738 if (arg_is_const(op->args[2])) {
Richard Henderson2d497542013-03-21 09:13:33 -0700739 /* Proceed with possible constant folding. */
740 break;
741 }
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700742 if (opc == INDEX_op_sub_i32) {
Richard Henderson2d497542013-03-21 09:13:33 -0700743 neg_op = INDEX_op_neg_i32;
744 have_neg = TCG_TARGET_HAS_neg_i32;
745 } else {
746 neg_op = INDEX_op_neg_i64;
747 have_neg = TCG_TARGET_HAS_neg_i64;
748 }
749 if (!have_neg) {
750 break;
751 }
Richard Henderson63490392017-06-20 13:43:15 -0700752 if (arg_is_const(op->args[1])
753 && arg_info(op->args[1])->val == 0) {
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700754 op->opc = neg_op;
Richard Hendersonacd93702016-12-08 12:28:42 -0800755 reset_temp(op->args[0]);
756 op->args[1] = op->args[2];
Richard Henderson2d497542013-03-21 09:13:33 -0700757 continue;
758 }
759 }
760 break;
Richard Hendersone201b562014-01-28 13:15:38 -0800761 CASE_OP_32_64(xor):
762 CASE_OP_32_64(nand):
Richard Henderson63490392017-06-20 13:43:15 -0700763 if (!arg_is_const(op->args[1])
764 && arg_is_const(op->args[2])
765 && arg_info(op->args[2])->val == -1) {
Richard Hendersone201b562014-01-28 13:15:38 -0800766 i = 1;
767 goto try_not;
768 }
769 break;
770 CASE_OP_32_64(nor):
Richard Henderson63490392017-06-20 13:43:15 -0700771 if (!arg_is_const(op->args[1])
772 && arg_is_const(op->args[2])
773 && arg_info(op->args[2])->val == 0) {
Richard Hendersone201b562014-01-28 13:15:38 -0800774 i = 1;
775 goto try_not;
776 }
777 break;
778 CASE_OP_32_64(andc):
Richard Henderson63490392017-06-20 13:43:15 -0700779 if (!arg_is_const(op->args[2])
780 && arg_is_const(op->args[1])
781 && arg_info(op->args[1])->val == -1) {
Richard Hendersone201b562014-01-28 13:15:38 -0800782 i = 2;
783 goto try_not;
784 }
785 break;
786 CASE_OP_32_64(orc):
787 CASE_OP_32_64(eqv):
Richard Henderson63490392017-06-20 13:43:15 -0700788 if (!arg_is_const(op->args[2])
789 && arg_is_const(op->args[1])
790 && arg_info(op->args[1])->val == 0) {
Richard Hendersone201b562014-01-28 13:15:38 -0800791 i = 2;
792 goto try_not;
793 }
794 break;
795 try_not:
796 {
797 TCGOpcode not_op;
798 bool have_not;
799
800 if (def->flags & TCG_OPF_64BIT) {
801 not_op = INDEX_op_not_i64;
802 have_not = TCG_TARGET_HAS_not_i64;
803 } else {
804 not_op = INDEX_op_not_i32;
805 have_not = TCG_TARGET_HAS_not_i32;
806 }
807 if (!have_not) {
808 break;
809 }
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700810 op->opc = not_op;
Richard Hendersonacd93702016-12-08 12:28:42 -0800811 reset_temp(op->args[0]);
812 op->args[1] = op->args[i];
Richard Hendersone201b562014-01-28 13:15:38 -0800813 continue;
814 }
Aurelien Jarno01ee5282012-09-06 16:47:14 +0200815 default:
816 break;
817 }
818
Richard Henderson464a1442014-01-31 07:42:11 -0600819 /* Simplify expression for "op r, a, const => mov r, a" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700820 switch (opc) {
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400821 CASE_OP_32_64(add):
822 CASE_OP_32_64(sub):
Kirill Batuzov55c09752011-07-07 16:37:16 +0400823 CASE_OP_32_64(shl):
824 CASE_OP_32_64(shr):
825 CASE_OP_32_64(sar):
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700826 CASE_OP_32_64(rotl):
827 CASE_OP_32_64(rotr):
Aurelien Jarno38ee1882012-09-06 16:47:14 +0200828 CASE_OP_32_64(or):
829 CASE_OP_32_64(xor):
Richard Henderson464a1442014-01-31 07:42:11 -0600830 CASE_OP_32_64(andc):
Richard Henderson63490392017-06-20 13:43:15 -0700831 if (!arg_is_const(op->args[1])
832 && arg_is_const(op->args[2])
833 && arg_info(op->args[2])->val == 0) {
Richard Hendersonacd93702016-12-08 12:28:42 -0800834 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200835 continue;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400836 }
837 break;
Richard Henderson464a1442014-01-31 07:42:11 -0600838 CASE_OP_32_64(and):
839 CASE_OP_32_64(orc):
840 CASE_OP_32_64(eqv):
Richard Henderson63490392017-06-20 13:43:15 -0700841 if (!arg_is_const(op->args[1])
842 && arg_is_const(op->args[2])
843 && arg_info(op->args[2])->val == -1) {
Richard Hendersonacd93702016-12-08 12:28:42 -0800844 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
Aurelien Jarno97a79eb2015-06-05 11:19:18 +0200845 continue;
Richard Henderson464a1442014-01-31 07:42:11 -0600846 }
847 break;
Aurelien Jarno56e49432012-09-06 16:47:13 +0200848 default:
849 break;
850 }
851
Aurelien Jarno30312442013-09-03 08:27:38 +0200852 /* Simplify using known-zero bits. Currently only ops with a single
853 output argument is supported. */
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800854 mask = -1;
Paolo Bonzini633f6502013-01-11 15:42:53 -0800855 affected = -1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700856 switch (opc) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800857 CASE_OP_32_64(ext8s):
Richard Henderson63490392017-06-20 13:43:15 -0700858 if ((arg_info(op->args[1])->mask & 0x80) != 0) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800859 break;
860 }
861 CASE_OP_32_64(ext8u):
862 mask = 0xff;
863 goto and_const;
864 CASE_OP_32_64(ext16s):
Richard Henderson63490392017-06-20 13:43:15 -0700865 if ((arg_info(op->args[1])->mask & 0x8000) != 0) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800866 break;
867 }
868 CASE_OP_32_64(ext16u):
869 mask = 0xffff;
870 goto and_const;
871 case INDEX_op_ext32s_i64:
Richard Henderson63490392017-06-20 13:43:15 -0700872 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800873 break;
874 }
875 case INDEX_op_ext32u_i64:
876 mask = 0xffffffffU;
877 goto and_const;
878
879 CASE_OP_32_64(and):
Richard Henderson63490392017-06-20 13:43:15 -0700880 mask = arg_info(op->args[2])->mask;
881 if (arg_is_const(op->args[2])) {
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800882 and_const:
Richard Henderson63490392017-06-20 13:43:15 -0700883 affected = arg_info(op->args[1])->mask & ~mask;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800884 }
Richard Henderson63490392017-06-20 13:43:15 -0700885 mask = arg_info(op->args[1])->mask & mask;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800886 break;
887
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200888 case INDEX_op_ext_i32_i64:
Richard Henderson63490392017-06-20 13:43:15 -0700889 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200890 break;
891 }
892 case INDEX_op_extu_i32_i64:
893 /* We do not compute affected as it is a size changing op. */
Richard Henderson63490392017-06-20 13:43:15 -0700894 mask = (uint32_t)arg_info(op->args[1])->mask;
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200895 break;
896
Richard Henderson23ec69ed2014-01-28 12:03:24 -0800897 CASE_OP_32_64(andc):
898 /* Known-zeros does not imply known-ones. Therefore unless
Richard Hendersonacd93702016-12-08 12:28:42 -0800899 op->args[2] is constant, we can't infer anything from it. */
Richard Henderson63490392017-06-20 13:43:15 -0700900 if (arg_is_const(op->args[2])) {
901 mask = ~arg_info(op->args[2])->mask;
Richard Henderson23ec69ed2014-01-28 12:03:24 -0800902 goto and_const;
903 }
Richard Henderson63490392017-06-20 13:43:15 -0700904 /* But we certainly know nothing outside args[1] may be set. */
905 mask = arg_info(op->args[1])->mask;
Richard Henderson23ec69ed2014-01-28 12:03:24 -0800906 break;
907
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200908 case INDEX_op_sar_i32:
Richard Henderson63490392017-06-20 13:43:15 -0700909 if (arg_is_const(op->args[2])) {
910 tmp = arg_info(op->args[2])->val & 31;
911 mask = (int32_t)arg_info(op->args[1])->mask >> tmp;
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200912 }
913 break;
914 case INDEX_op_sar_i64:
Richard Henderson63490392017-06-20 13:43:15 -0700915 if (arg_is_const(op->args[2])) {
916 tmp = arg_info(op->args[2])->val & 63;
917 mask = (int64_t)arg_info(op->args[1])->mask >> tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800918 }
919 break;
920
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200921 case INDEX_op_shr_i32:
Richard Henderson63490392017-06-20 13:43:15 -0700922 if (arg_is_const(op->args[2])) {
923 tmp = arg_info(op->args[2])->val & 31;
924 mask = (uint32_t)arg_info(op->args[1])->mask >> tmp;
Aurelien Jarnoe46b2252013-09-03 08:27:38 +0200925 }
926 break;
927 case INDEX_op_shr_i64:
Richard Henderson63490392017-06-20 13:43:15 -0700928 if (arg_is_const(op->args[2])) {
929 tmp = arg_info(op->args[2])->val & 63;
930 mask = (uint64_t)arg_info(op->args[1])->mask >> tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800931 }
932 break;
933
Richard Henderson609ad702015-07-24 07:16:00 -0700934 case INDEX_op_extrl_i64_i32:
Richard Henderson63490392017-06-20 13:43:15 -0700935 mask = (uint32_t)arg_info(op->args[1])->mask;
Richard Henderson609ad702015-07-24 07:16:00 -0700936 break;
937 case INDEX_op_extrh_i64_i32:
Richard Henderson63490392017-06-20 13:43:15 -0700938 mask = (uint64_t)arg_info(op->args[1])->mask >> 32;
Richard Henderson4bb7a412013-09-09 17:03:24 -0700939 break;
940
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800941 CASE_OP_32_64(shl):
Richard Henderson63490392017-06-20 13:43:15 -0700942 if (arg_is_const(op->args[2])) {
943 tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1);
944 mask = arg_info(op->args[1])->mask << tmp;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800945 }
946 break;
947
948 CASE_OP_32_64(neg):
949 /* Set to 1 all bits to the left of the rightmost. */
Richard Henderson63490392017-06-20 13:43:15 -0700950 mask = -(arg_info(op->args[1])->mask
951 & -arg_info(op->args[1])->mask);
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800952 break;
953
954 CASE_OP_32_64(deposit):
Richard Henderson63490392017-06-20 13:43:15 -0700955 mask = deposit64(arg_info(op->args[1])->mask,
956 op->args[3], op->args[4],
957 arg_info(op->args[2])->mask);
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800958 break;
959
Richard Henderson7ec8bab2016-10-14 12:04:32 -0500960 CASE_OP_32_64(extract):
Richard Henderson63490392017-06-20 13:43:15 -0700961 mask = extract64(arg_info(op->args[1])->mask,
962 op->args[2], op->args[3]);
Richard Hendersonacd93702016-12-08 12:28:42 -0800963 if (op->args[2] == 0) {
Richard Henderson63490392017-06-20 13:43:15 -0700964 affected = arg_info(op->args[1])->mask & ~mask;
Richard Henderson7ec8bab2016-10-14 12:04:32 -0500965 }
966 break;
967 CASE_OP_32_64(sextract):
Richard Henderson63490392017-06-20 13:43:15 -0700968 mask = sextract64(arg_info(op->args[1])->mask,
Richard Hendersonacd93702016-12-08 12:28:42 -0800969 op->args[2], op->args[3]);
970 if (op->args[2] == 0 && (tcg_target_long)mask >= 0) {
Richard Henderson63490392017-06-20 13:43:15 -0700971 affected = arg_info(op->args[1])->mask & ~mask;
Richard Henderson7ec8bab2016-10-14 12:04:32 -0500972 }
973 break;
974
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800975 CASE_OP_32_64(or):
976 CASE_OP_32_64(xor):
Richard Henderson63490392017-06-20 13:43:15 -0700977 mask = arg_info(op->args[1])->mask | arg_info(op->args[2])->mask;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800978 break;
979
Richard Henderson0e28d002016-11-16 09:23:28 +0100980 case INDEX_op_clz_i32:
981 case INDEX_op_ctz_i32:
Richard Henderson63490392017-06-20 13:43:15 -0700982 mask = arg_info(op->args[2])->mask | 31;
Richard Henderson0e28d002016-11-16 09:23:28 +0100983 break;
984
985 case INDEX_op_clz_i64:
986 case INDEX_op_ctz_i64:
Richard Henderson63490392017-06-20 13:43:15 -0700987 mask = arg_info(op->args[2])->mask | 63;
Richard Henderson0e28d002016-11-16 09:23:28 +0100988 break;
989
Richard Hendersona768e4e2016-11-21 11:13:39 +0100990 case INDEX_op_ctpop_i32:
991 mask = 32 | 31;
992 break;
993 case INDEX_op_ctpop_i64:
994 mask = 64 | 63;
995 break;
996
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800997 CASE_OP_32_64(setcond):
Richard Hendersona7635512014-04-23 22:18:30 -0700998 case INDEX_op_setcond2_i32:
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800999 mask = 1;
1000 break;
1001
1002 CASE_OP_32_64(movcond):
Richard Henderson63490392017-06-20 13:43:15 -07001003 mask = arg_info(op->args[3])->mask | arg_info(op->args[4])->mask;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -08001004 break;
1005
Aurelien Jarnoc8d70272013-09-03 08:27:39 +02001006 CASE_OP_32_64(ld8u):
Aurelien Jarnoc8d70272013-09-03 08:27:39 +02001007 mask = 0xff;
1008 break;
1009 CASE_OP_32_64(ld16u):
Aurelien Jarnoc8d70272013-09-03 08:27:39 +02001010 mask = 0xffff;
1011 break;
1012 case INDEX_op_ld32u_i64:
Aurelien Jarnoc8d70272013-09-03 08:27:39 +02001013 mask = 0xffffffffu;
1014 break;
1015
1016 CASE_OP_32_64(qemu_ld):
1017 {
Richard Hendersonacd93702016-12-08 12:28:42 -08001018 TCGMemOpIdx oi = op->args[nb_oargs + nb_iargs];
Richard Henderson59227d52015-05-12 11:51:44 -07001019 TCGMemOp mop = get_memop(oi);
Aurelien Jarnoc8d70272013-09-03 08:27:39 +02001020 if (!(mop & MO_SIGN)) {
1021 mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
1022 }
1023 }
1024 break;
1025
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -08001026 default:
1027 break;
1028 }
1029
Richard Hendersonbc8d6882014-06-08 18:24:14 -07001030 /* 32-bit ops generate 32-bit results. For the result is zero test
1031 below, we can ignore high bits, but for further optimizations we
1032 need to record that the high bits contain garbage. */
Richard Henderson24666ba2014-05-22 11:14:10 -07001033 partmask = mask;
Richard Hendersonbc8d6882014-06-08 18:24:14 -07001034 if (!(def->flags & TCG_OPF_64BIT)) {
Richard Henderson24666ba2014-05-22 11:14:10 -07001035 mask |= ~(tcg_target_ulong)0xffffffffu;
1036 partmask &= 0xffffffffu;
1037 affected &= 0xffffffffu;
Aurelien Jarnof096dc92013-09-03 08:27:38 +02001038 }
1039
Richard Henderson24666ba2014-05-22 11:14:10 -07001040 if (partmask == 0) {
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +02001041 tcg_debug_assert(nb_oargs == 1);
Richard Hendersonacd93702016-12-08 12:28:42 -08001042 tcg_opt_gen_movi(s, op, op->args[0], 0);
Paolo Bonzini633f6502013-01-11 15:42:53 -08001043 continue;
1044 }
1045 if (affected == 0) {
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +02001046 tcg_debug_assert(nb_oargs == 1);
Richard Hendersonacd93702016-12-08 12:28:42 -08001047 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
Paolo Bonzini633f6502013-01-11 15:42:53 -08001048 continue;
1049 }
1050
Aurelien Jarno56e49432012-09-06 16:47:13 +02001051 /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001052 switch (opc) {
Aurelien Jarno61251c02012-09-06 16:47:14 +02001053 CASE_OP_32_64(and):
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001054 CASE_OP_32_64(mul):
Richard Henderson03271522013-08-14 14:35:56 -07001055 CASE_OP_32_64(muluh):
1056 CASE_OP_32_64(mulsh):
Richard Henderson63490392017-06-20 13:43:15 -07001057 if (arg_is_const(op->args[2])
1058 && arg_info(op->args[2])->val == 0) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001059 tcg_opt_gen_movi(s, op, op->args[0], 0);
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001060 continue;
1061 }
1062 break;
Aurelien Jarno56e49432012-09-06 16:47:13 +02001063 default:
1064 break;
1065 }
1066
1067 /* Simplify expression for "op r, a, a => mov r, a" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001068 switch (opc) {
Kirill Batuzov9a810902011-07-07 16:37:15 +04001069 CASE_OP_32_64(or):
1070 CASE_OP_32_64(and):
Richard Henderson63490392017-06-20 13:43:15 -07001071 if (args_are_copies(op->args[1], op->args[2])) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001072 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
Kirill Batuzov9a810902011-07-07 16:37:15 +04001073 continue;
1074 }
1075 break;
Blue Swirlfe0de7a2011-07-30 19:18:32 +00001076 default:
1077 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001078 }
1079
Aurelien Jarno3c941932012-09-18 19:12:36 +02001080 /* Simplify expression for "op r, a, a => movi r, 0" cases */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001081 switch (opc) {
Richard Hendersone64e9582014-01-28 13:26:17 -08001082 CASE_OP_32_64(andc):
Aurelien Jarno3c941932012-09-18 19:12:36 +02001083 CASE_OP_32_64(sub):
1084 CASE_OP_32_64(xor):
Richard Henderson63490392017-06-20 13:43:15 -07001085 if (args_are_copies(op->args[1], op->args[2])) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001086 tcg_opt_gen_movi(s, op, op->args[0], 0);
Aurelien Jarno3c941932012-09-18 19:12:36 +02001087 continue;
1088 }
1089 break;
1090 default:
1091 break;
1092 }
1093
Kirill Batuzov22613af2011-07-07 16:37:13 +04001094 /* Propagate constants through copy operations and do constant
1095 folding. Constants will be substituted to arguments by register
1096 allocator where needed and possible. Also detect copies. */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001097 switch (opc) {
Kirill Batuzov22613af2011-07-07 16:37:13 +04001098 CASE_OP_32_64(mov):
Richard Hendersonacd93702016-12-08 12:28:42 -08001099 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
Aurelien Jarno97a79eb2015-06-05 11:19:18 +02001100 break;
Kirill Batuzov22613af2011-07-07 16:37:13 +04001101 CASE_OP_32_64(movi):
Richard Hendersonacd93702016-12-08 12:28:42 -08001102 tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
Kirill Batuzov22613af2011-07-07 16:37:13 +04001103 break;
Richard Henderson6e14e912012-10-02 11:32:24 -07001104
Kirill Batuzova640f032011-07-07 16:37:17 +04001105 CASE_OP_32_64(not):
Richard Hendersoncb25c802011-08-17 14:11:47 -07001106 CASE_OP_32_64(neg):
Richard Henderson25c4d9c2011-08-17 14:11:46 -07001107 CASE_OP_32_64(ext8s):
1108 CASE_OP_32_64(ext8u):
1109 CASE_OP_32_64(ext16s):
1110 CASE_OP_32_64(ext16u):
Richard Hendersona768e4e2016-11-21 11:13:39 +01001111 CASE_OP_32_64(ctpop):
Kirill Batuzova640f032011-07-07 16:37:17 +04001112 case INDEX_op_ext32s_i64:
1113 case INDEX_op_ext32u_i64:
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +02001114 case INDEX_op_ext_i32_i64:
1115 case INDEX_op_extu_i32_i64:
Richard Henderson609ad702015-07-24 07:16:00 -07001116 case INDEX_op_extrl_i64_i32:
1117 case INDEX_op_extrh_i64_i32:
Richard Henderson63490392017-06-20 13:43:15 -07001118 if (arg_is_const(op->args[1])) {
1119 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 0);
Richard Hendersonacd93702016-12-08 12:28:42 -08001120 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001121 break;
Kirill Batuzova640f032011-07-07 16:37:17 +04001122 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001123 goto do_default;
1124
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001125 CASE_OP_32_64(add):
1126 CASE_OP_32_64(sub):
1127 CASE_OP_32_64(mul):
Kirill Batuzov9a810902011-07-07 16:37:15 +04001128 CASE_OP_32_64(or):
1129 CASE_OP_32_64(and):
1130 CASE_OP_32_64(xor):
Kirill Batuzov55c09752011-07-07 16:37:16 +04001131 CASE_OP_32_64(shl):
1132 CASE_OP_32_64(shr):
1133 CASE_OP_32_64(sar):
Richard Henderson25c4d9c2011-08-17 14:11:46 -07001134 CASE_OP_32_64(rotl):
1135 CASE_OP_32_64(rotr):
Richard Hendersoncb25c802011-08-17 14:11:47 -07001136 CASE_OP_32_64(andc):
1137 CASE_OP_32_64(orc):
1138 CASE_OP_32_64(eqv):
1139 CASE_OP_32_64(nand):
1140 CASE_OP_32_64(nor):
Richard Henderson03271522013-08-14 14:35:56 -07001141 CASE_OP_32_64(muluh):
1142 CASE_OP_32_64(mulsh):
Richard Henderson01547f72013-08-14 15:22:46 -07001143 CASE_OP_32_64(div):
1144 CASE_OP_32_64(divu):
1145 CASE_OP_32_64(rem):
1146 CASE_OP_32_64(remu):
Richard Henderson63490392017-06-20 13:43:15 -07001147 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1148 tmp = do_constant_folding(opc, arg_info(op->args[1])->val,
1149 arg_info(op->args[2])->val);
Richard Hendersonacd93702016-12-08 12:28:42 -08001150 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001151 break;
Kirill Batuzov53108fb2011-07-07 16:37:14 +04001152 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001153 goto do_default;
1154
Richard Henderson0e28d002016-11-16 09:23:28 +01001155 CASE_OP_32_64(clz):
1156 CASE_OP_32_64(ctz):
Richard Henderson63490392017-06-20 13:43:15 -07001157 if (arg_is_const(op->args[1])) {
1158 TCGArg v = arg_info(op->args[1])->val;
Richard Henderson0e28d002016-11-16 09:23:28 +01001159 if (v != 0) {
1160 tmp = do_constant_folding(opc, v, 0);
Richard Hendersonacd93702016-12-08 12:28:42 -08001161 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson0e28d002016-11-16 09:23:28 +01001162 } else {
Richard Hendersonacd93702016-12-08 12:28:42 -08001163 tcg_opt_gen_mov(s, op, op->args[0], op->args[2]);
Richard Henderson0e28d002016-11-16 09:23:28 +01001164 }
1165 break;
1166 }
1167 goto do_default;
1168
Aurelien Jarno7ef55fc2012-09-21 11:07:29 +02001169 CASE_OP_32_64(deposit):
Richard Henderson63490392017-06-20 13:43:15 -07001170 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1171 tmp = deposit64(arg_info(op->args[1])->val,
1172 op->args[3], op->args[4],
1173 arg_info(op->args[2])->val);
Richard Hendersonacd93702016-12-08 12:28:42 -08001174 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001175 break;
Aurelien Jarno7ef55fc2012-09-21 11:07:29 +02001176 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001177 goto do_default;
1178
Richard Henderson7ec8bab2016-10-14 12:04:32 -05001179 CASE_OP_32_64(extract):
Richard Henderson63490392017-06-20 13:43:15 -07001180 if (arg_is_const(op->args[1])) {
1181 tmp = extract64(arg_info(op->args[1])->val,
Richard Hendersonacd93702016-12-08 12:28:42 -08001182 op->args[2], op->args[3]);
1183 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson7ec8bab2016-10-14 12:04:32 -05001184 break;
1185 }
1186 goto do_default;
1187
1188 CASE_OP_32_64(sextract):
Richard Henderson63490392017-06-20 13:43:15 -07001189 if (arg_is_const(op->args[1])) {
1190 tmp = sextract64(arg_info(op->args[1])->val,
Richard Hendersonacd93702016-12-08 12:28:42 -08001191 op->args[2], op->args[3]);
1192 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson7ec8bab2016-10-14 12:04:32 -05001193 break;
1194 }
1195 goto do_default;
1196
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +02001197 CASE_OP_32_64(setcond):
Richard Hendersonacd93702016-12-08 12:28:42 -08001198 tmp = do_constant_folding_cond(opc, op->args[1],
1199 op->args[2], op->args[3]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001200 if (tmp != 2) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001201 tcg_opt_gen_movi(s, op, op->args[0], tmp);
Richard Henderson6e14e912012-10-02 11:32:24 -07001202 break;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +02001203 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001204 goto do_default;
1205
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001206 CASE_OP_32_64(brcond):
Richard Hendersonacd93702016-12-08 12:28:42 -08001207 tmp = do_constant_folding_cond(opc, op->args[0],
1208 op->args[1], op->args[2]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001209 if (tmp != 2) {
1210 if (tmp) {
Paolo Bonzinid193a142013-01-11 15:42:51 -08001211 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001212 op->opc = INDEX_op_br;
Richard Hendersonacd93702016-12-08 12:28:42 -08001213 op->args[0] = op->args[3];
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001214 } else {
Richard Henderson0c627cd2014-03-30 16:51:54 -07001215 tcg_op_remove(s, op);
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001216 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001217 break;
Aurelien Jarnofbeaa262012-09-06 16:47:14 +02001218 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001219 goto do_default;
1220
Richard Hendersonfa01a202012-09-21 10:13:37 -07001221 CASE_OP_32_64(movcond):
Richard Hendersonacd93702016-12-08 12:28:42 -08001222 tmp = do_constant_folding_cond(opc, op->args[1],
1223 op->args[2], op->args[5]);
Aurelien Jarnob336ceb2012-09-18 19:37:00 +02001224 if (tmp != 2) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001225 tcg_opt_gen_mov(s, op, op->args[0], op->args[4-tmp]);
Richard Henderson6e14e912012-10-02 11:32:24 -07001226 break;
Richard Hendersonfa01a202012-09-21 10:13:37 -07001227 }
Richard Henderson63490392017-06-20 13:43:15 -07001228 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
1229 tcg_target_ulong tv = arg_info(op->args[3])->val;
1230 tcg_target_ulong fv = arg_info(op->args[4])->val;
Richard Hendersonacd93702016-12-08 12:28:42 -08001231 TCGCond cond = op->args[5];
Richard Henderson333b21b2016-10-23 20:44:32 -07001232 if (fv == 1 && tv == 0) {
1233 cond = tcg_invert_cond(cond);
1234 } else if (!(tv == 1 && fv == 0)) {
1235 goto do_default;
1236 }
Richard Hendersonacd93702016-12-08 12:28:42 -08001237 op->args[3] = cond;
Richard Henderson333b21b2016-10-23 20:44:32 -07001238 op->opc = opc = (opc == INDEX_op_movcond_i32
1239 ? INDEX_op_setcond_i32
1240 : INDEX_op_setcond_i64);
1241 nb_iargs = 2;
1242 }
Richard Henderson6e14e912012-10-02 11:32:24 -07001243 goto do_default;
1244
Richard Henderson212c3282012-10-02 11:32:28 -07001245 case INDEX_op_add2_i32:
1246 case INDEX_op_sub2_i32:
Richard Henderson63490392017-06-20 13:43:15 -07001247 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])
1248 && arg_is_const(op->args[4]) && arg_is_const(op->args[5])) {
1249 uint32_t al = arg_info(op->args[2])->val;
1250 uint32_t ah = arg_info(op->args[3])->val;
1251 uint32_t bl = arg_info(op->args[4])->val;
1252 uint32_t bh = arg_info(op->args[5])->val;
Richard Henderson212c3282012-10-02 11:32:28 -07001253 uint64_t a = ((uint64_t)ah << 32) | al;
1254 uint64_t b = ((uint64_t)bh << 32) | bl;
1255 TCGArg rl, rh;
Richard Henderson5a184072016-06-23 20:34:33 -07001256 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
Richard Henderson212c3282012-10-02 11:32:28 -07001257
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001258 if (opc == INDEX_op_add2_i32) {
Richard Henderson212c3282012-10-02 11:32:28 -07001259 a += b;
1260 } else {
1261 a -= b;
1262 }
1263
Richard Hendersonacd93702016-12-08 12:28:42 -08001264 rl = op->args[0];
1265 rh = op->args[1];
1266 tcg_opt_gen_movi(s, op, rl, (int32_t)a);
1267 tcg_opt_gen_movi(s, op2, rh, (int32_t)(a >> 32));
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001268
1269 /* We've done all we need to do with the movi. Skip it. */
1270 oi_next = op2->next;
Richard Henderson212c3282012-10-02 11:32:28 -07001271 break;
1272 }
1273 goto do_default;
1274
Richard Henderson14149682012-10-02 11:32:30 -07001275 case INDEX_op_mulu2_i32:
Richard Henderson63490392017-06-20 13:43:15 -07001276 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) {
1277 uint32_t a = arg_info(op->args[2])->val;
1278 uint32_t b = arg_info(op->args[3])->val;
Richard Henderson14149682012-10-02 11:32:30 -07001279 uint64_t r = (uint64_t)a * b;
1280 TCGArg rl, rh;
Richard Henderson5a184072016-06-23 20:34:33 -07001281 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
Richard Henderson14149682012-10-02 11:32:30 -07001282
Richard Hendersonacd93702016-12-08 12:28:42 -08001283 rl = op->args[0];
1284 rh = op->args[1];
1285 tcg_opt_gen_movi(s, op, rl, (int32_t)r);
1286 tcg_opt_gen_movi(s, op2, rh, (int32_t)(r >> 32));
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001287
1288 /* We've done all we need to do with the movi. Skip it. */
1289 oi_next = op2->next;
Richard Henderson14149682012-10-02 11:32:30 -07001290 break;
1291 }
1292 goto do_default;
1293
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001294 case INDEX_op_brcond2_i32:
Richard Hendersonacd93702016-12-08 12:28:42 -08001295 tmp = do_constant_folding_cond2(&op->args[0], &op->args[2],
1296 op->args[4]);
Richard Henderson6c4382f2012-10-02 11:32:27 -07001297 if (tmp != 2) {
1298 if (tmp) {
Richard Hendersona7635512014-04-23 22:18:30 -07001299 do_brcond_true:
Paolo Bonzinid193a142013-01-11 15:42:51 -08001300 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001301 op->opc = INDEX_op_br;
Richard Hendersonacd93702016-12-08 12:28:42 -08001302 op->args[0] = op->args[5];
Richard Henderson6c4382f2012-10-02 11:32:27 -07001303 } else {
Richard Hendersona7635512014-04-23 22:18:30 -07001304 do_brcond_false:
Richard Henderson0c627cd2014-03-30 16:51:54 -07001305 tcg_op_remove(s, op);
Richard Henderson6c4382f2012-10-02 11:32:27 -07001306 }
Richard Hendersonacd93702016-12-08 12:28:42 -08001307 } else if ((op->args[4] == TCG_COND_LT
1308 || op->args[4] == TCG_COND_GE)
Richard Henderson63490392017-06-20 13:43:15 -07001309 && arg_is_const(op->args[2])
1310 && arg_info(op->args[2])->val == 0
1311 && arg_is_const(op->args[3])
1312 && arg_info(op->args[3])->val == 0) {
Richard Henderson6c4382f2012-10-02 11:32:27 -07001313 /* Simplify LT/GE comparisons vs zero to a single compare
1314 vs the high word of the input. */
Richard Hendersona7635512014-04-23 22:18:30 -07001315 do_brcond_high:
Paolo Bonzinid193a142013-01-11 15:42:51 -08001316 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001317 op->opc = INDEX_op_brcond_i32;
Richard Hendersonacd93702016-12-08 12:28:42 -08001318 op->args[0] = op->args[1];
1319 op->args[1] = op->args[3];
1320 op->args[2] = op->args[4];
1321 op->args[3] = op->args[5];
1322 } else if (op->args[4] == TCG_COND_EQ) {
Richard Hendersona7635512014-04-23 22:18:30 -07001323 /* Simplify EQ comparisons where one of the pairs
1324 can be simplified. */
1325 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001326 op->args[0], op->args[2],
1327 TCG_COND_EQ);
Richard Hendersona7635512014-04-23 22:18:30 -07001328 if (tmp == 0) {
1329 goto do_brcond_false;
1330 } else if (tmp == 1) {
1331 goto do_brcond_high;
1332 }
1333 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001334 op->args[1], op->args[3],
1335 TCG_COND_EQ);
Richard Hendersona7635512014-04-23 22:18:30 -07001336 if (tmp == 0) {
1337 goto do_brcond_false;
1338 } else if (tmp != 1) {
1339 goto do_default;
1340 }
1341 do_brcond_low:
1342 reset_all_temps(nb_temps);
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001343 op->opc = INDEX_op_brcond_i32;
Richard Hendersonacd93702016-12-08 12:28:42 -08001344 op->args[1] = op->args[2];
1345 op->args[2] = op->args[4];
1346 op->args[3] = op->args[5];
1347 } else if (op->args[4] == TCG_COND_NE) {
Richard Hendersona7635512014-04-23 22:18:30 -07001348 /* Simplify NE comparisons where one of the pairs
1349 can be simplified. */
1350 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001351 op->args[0], op->args[2],
1352 TCG_COND_NE);
Richard Hendersona7635512014-04-23 22:18:30 -07001353 if (tmp == 0) {
1354 goto do_brcond_high;
1355 } else if (tmp == 1) {
1356 goto do_brcond_true;
1357 }
1358 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001359 op->args[1], op->args[3],
1360 TCG_COND_NE);
Richard Hendersona7635512014-04-23 22:18:30 -07001361 if (tmp == 0) {
1362 goto do_brcond_low;
1363 } else if (tmp == 1) {
1364 goto do_brcond_true;
1365 }
1366 goto do_default;
Richard Henderson6c4382f2012-10-02 11:32:27 -07001367 } else {
1368 goto do_default;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001369 }
Richard Henderson6c4382f2012-10-02 11:32:27 -07001370 break;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001371
1372 case INDEX_op_setcond2_i32:
Richard Hendersonacd93702016-12-08 12:28:42 -08001373 tmp = do_constant_folding_cond2(&op->args[1], &op->args[3],
1374 op->args[5]);
Richard Henderson6c4382f2012-10-02 11:32:27 -07001375 if (tmp != 2) {
Richard Hendersona7635512014-04-23 22:18:30 -07001376 do_setcond_const:
Richard Hendersonacd93702016-12-08 12:28:42 -08001377 tcg_opt_gen_movi(s, op, op->args[0], tmp);
1378 } else if ((op->args[5] == TCG_COND_LT
1379 || op->args[5] == TCG_COND_GE)
Richard Henderson63490392017-06-20 13:43:15 -07001380 && arg_is_const(op->args[3])
1381 && arg_info(op->args[3])->val == 0
1382 && arg_is_const(op->args[4])
1383 && arg_info(op->args[4])->val == 0) {
Richard Henderson6c4382f2012-10-02 11:32:27 -07001384 /* Simplify LT/GE comparisons vs zero to a single compare
1385 vs the high word of the input. */
Richard Hendersona7635512014-04-23 22:18:30 -07001386 do_setcond_high:
Richard Hendersonacd93702016-12-08 12:28:42 -08001387 reset_temp(op->args[0]);
Richard Henderson63490392017-06-20 13:43:15 -07001388 arg_info(op->args[0])->mask = 1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001389 op->opc = INDEX_op_setcond_i32;
Richard Hendersonacd93702016-12-08 12:28:42 -08001390 op->args[1] = op->args[2];
1391 op->args[2] = op->args[4];
1392 op->args[3] = op->args[5];
1393 } else if (op->args[5] == TCG_COND_EQ) {
Richard Hendersona7635512014-04-23 22:18:30 -07001394 /* Simplify EQ comparisons where one of the pairs
1395 can be simplified. */
1396 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001397 op->args[1], op->args[3],
1398 TCG_COND_EQ);
Richard Hendersona7635512014-04-23 22:18:30 -07001399 if (tmp == 0) {
1400 goto do_setcond_const;
1401 } else if (tmp == 1) {
1402 goto do_setcond_high;
1403 }
1404 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001405 op->args[2], op->args[4],
1406 TCG_COND_EQ);
Richard Hendersona7635512014-04-23 22:18:30 -07001407 if (tmp == 0) {
1408 goto do_setcond_high;
1409 } else if (tmp != 1) {
1410 goto do_default;
1411 }
1412 do_setcond_low:
Richard Hendersonacd93702016-12-08 12:28:42 -08001413 reset_temp(op->args[0]);
Richard Henderson63490392017-06-20 13:43:15 -07001414 arg_info(op->args[0])->mask = 1;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001415 op->opc = INDEX_op_setcond_i32;
Richard Hendersonacd93702016-12-08 12:28:42 -08001416 op->args[2] = op->args[3];
1417 op->args[3] = op->args[5];
1418 } else if (op->args[5] == TCG_COND_NE) {
Richard Hendersona7635512014-04-23 22:18:30 -07001419 /* Simplify NE comparisons where one of the pairs
1420 can be simplified. */
1421 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001422 op->args[1], op->args[3],
1423 TCG_COND_NE);
Richard Hendersona7635512014-04-23 22:18:30 -07001424 if (tmp == 0) {
1425 goto do_setcond_high;
1426 } else if (tmp == 1) {
1427 goto do_setcond_const;
1428 }
1429 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
Richard Hendersonacd93702016-12-08 12:28:42 -08001430 op->args[2], op->args[4],
1431 TCG_COND_NE);
Richard Hendersona7635512014-04-23 22:18:30 -07001432 if (tmp == 0) {
1433 goto do_setcond_low;
1434 } else if (tmp == 1) {
1435 goto do_setcond_const;
1436 }
1437 goto do_default;
Richard Henderson6c4382f2012-10-02 11:32:27 -07001438 } else {
1439 goto do_default;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001440 }
Richard Henderson6c4382f2012-10-02 11:32:27 -07001441 break;
Richard Hendersonbc1473e2012-10-02 11:32:25 -07001442
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001443 case INDEX_op_call:
Richard Hendersonacd93702016-12-08 12:28:42 -08001444 if (!(op->args[nb_oargs + nb_iargs + 1]
Richard Hendersoncf066672014-03-22 20:06:52 -07001445 & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
Kirill Batuzov22613af2011-07-07 16:37:13 +04001446 for (i = 0; i < nb_globals; i++) {
Aurelien Jarno1208d7d2015-07-27 12:41:44 +02001447 if (test_bit(i, temps_used.l)) {
Richard Henderson63490392017-06-20 13:43:15 -07001448 reset_ts(&s->temps[i]);
Aurelien Jarno1208d7d2015-07-27 12:41:44 +02001449 }
Kirill Batuzov22613af2011-07-07 16:37:13 +04001450 }
1451 }
Richard Hendersoncf066672014-03-22 20:06:52 -07001452 goto do_reset_output;
Richard Henderson6e14e912012-10-02 11:32:24 -07001453
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001454 default:
Richard Henderson6e14e912012-10-02 11:32:24 -07001455 do_default:
1456 /* Default case: we know nothing about operation (or were unable
1457 to compute the operation result) so no propagation is done.
1458 We trash everything if the operation is the end of a basic
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -08001459 block, otherwise we only trash the output args. "mask" is
1460 the non-zero bits mask for the first output arg. */
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001461 if (def->flags & TCG_OPF_BB_END) {
Paolo Bonzinid193a142013-01-11 15:42:51 -08001462 reset_all_temps(nb_temps);
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001463 } else {
Richard Hendersoncf066672014-03-22 20:06:52 -07001464 do_reset_output:
1465 for (i = 0; i < nb_oargs; i++) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001466 reset_temp(op->args[i]);
Aurelien Jarno30312442013-09-03 08:27:38 +02001467 /* Save the corresponding known-zero bits mask for the
1468 first output argument (only one supported so far). */
1469 if (i == 0) {
Richard Henderson63490392017-06-20 13:43:15 -07001470 arg_info(op->args[i])->mask = mask;
Aurelien Jarno30312442013-09-03 08:27:38 +02001471 }
Aurelien Jarnoa2550662012-09-19 21:40:30 +02001472 }
Kirill Batuzov22613af2011-07-07 16:37:13 +04001473 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001474 break;
1475 }
Pranith Kumar34f93922016-08-23 09:48:25 -04001476
1477 /* Eliminate duplicate and redundant fence instructions. */
Richard Hendersonacd93702016-12-08 12:28:42 -08001478 if (prev_mb) {
Pranith Kumar34f93922016-08-23 09:48:25 -04001479 switch (opc) {
1480 case INDEX_op_mb:
1481 /* Merge two barriers of the same type into one,
1482 * or a weaker barrier into a stronger one,
1483 * or two weaker barriers into a stronger one.
1484 * mb X; mb Y => mb X|Y
1485 * mb; strl => mb; st
1486 * ldaq; mb => ld; mb
1487 * ldaq; strl => ld; mb; st
1488 * Other combinations are also merged into a strong
1489 * barrier. This is stricter than specified but for
1490 * the purposes of TCG is better than not optimizing.
1491 */
Richard Hendersonacd93702016-12-08 12:28:42 -08001492 prev_mb->args[0] |= op->args[0];
Pranith Kumar34f93922016-08-23 09:48:25 -04001493 tcg_op_remove(s, op);
1494 break;
1495
1496 default:
1497 /* Opcodes that end the block stop the optimization. */
1498 if ((def->flags & TCG_OPF_BB_END) == 0) {
1499 break;
1500 }
1501 /* fallthru */
1502 case INDEX_op_qemu_ld_i32:
1503 case INDEX_op_qemu_ld_i64:
1504 case INDEX_op_qemu_st_i32:
1505 case INDEX_op_qemu_st_i64:
1506 case INDEX_op_call:
1507 /* Opcodes that touch guest memory stop the optimization. */
Richard Hendersonacd93702016-12-08 12:28:42 -08001508 prev_mb = NULL;
Pranith Kumar34f93922016-08-23 09:48:25 -04001509 break;
1510 }
1511 } else if (opc == INDEX_op_mb) {
Richard Hendersonacd93702016-12-08 12:28:42 -08001512 prev_mb = op;
Pranith Kumar34f93922016-08-23 09:48:25 -04001513 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001514 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001515}