blob: ef202abbcb4efd571b24e53b7a83f867d032d7ac [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"
Richard Henderson9531c072021-08-26 06:51:39 -070027#include "qemu/int128.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +010028#include "tcg/tcg-op.h"
Richard Henderson90163902021-03-18 10:21:45 -060029#include "tcg-internal.h"
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +040030
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
Richard Henderson170ba882017-11-22 09:07:11 +010035#define CASE_OP_32_64_VEC(x) \
36 glue(glue(case INDEX_op_, x), _i32): \
37 glue(glue(case INDEX_op_, x), _i64): \
38 glue(glue(case INDEX_op_, x), _vec)
39
Richard Henderson6fcb98e2020-03-30 17:44:30 -070040typedef struct TempOptInfo {
Aurelien Jarnob41059d2015-07-27 12:41:44 +020041 bool is_const;
Richard Henderson63490392017-06-20 13:43:15 -070042 TCGTemp *prev_copy;
43 TCGTemp *next_copy;
Richard Henderson54795542020-09-06 16:21:32 -070044 uint64_t val;
Richard Hendersonb1fde412021-08-23 13:07:49 -070045 uint64_t z_mask; /* mask bit is 0 if and only if value bit is 0 */
Richard Henderson57fe5c62021-08-26 12:04:46 -070046 uint64_t s_mask; /* a left-aligned mask of clrsb(value) bits. */
Richard Henderson6fcb98e2020-03-30 17:44:30 -070047} TempOptInfo;
Kirill Batuzov22613af2011-07-07 16:37:13 +040048
Richard Henderson3b3f8472021-08-23 22:06:31 -070049typedef struct OptContext {
Richard Hendersondc849882021-08-24 07:13:45 -070050 TCGContext *tcg;
Richard Hendersond0ed5152021-08-24 07:38:39 -070051 TCGOp *prev_mb;
Richard Henderson3b3f8472021-08-23 22:06:31 -070052 TCGTempSet temps_used;
Richard Henderson137f1f42021-08-24 08:49:25 -070053
54 /* In flight values from optimization. */
Richard Hendersonfae450b2021-08-25 22:42:19 -070055 uint64_t a_mask; /* mask bit is 0 iff value identical to first input */
56 uint64_t z_mask; /* mask bit is 0 iff value bit is 0 */
Richard Henderson57fe5c62021-08-26 12:04:46 -070057 uint64_t s_mask; /* mask of clrsb(value) bits */
Richard Henderson67f84c92021-08-25 08:00:20 -070058 TCGType type;
Richard Henderson3b3f8472021-08-23 22:06:31 -070059} OptContext;
60
Richard Henderson57fe5c62021-08-26 12:04:46 -070061/* Calculate the smask for a specific value. */
62static uint64_t smask_from_value(uint64_t value)
63{
64 int rep = clrsb64(value);
65 return ~(~0ull >> rep);
66}
67
68/*
69 * Calculate the smask for a given set of known-zeros.
70 * If there are lots of zeros on the left, we can consider the remainder
71 * an unsigned field, and thus the corresponding signed field is one bit
72 * larger.
73 */
74static uint64_t smask_from_zmask(uint64_t zmask)
75{
76 /*
77 * Only the 0 bits are significant for zmask, thus the msb itself
78 * must be zero, else we have no sign information.
79 */
80 int rep = clz64(zmask);
81 if (rep == 0) {
82 return 0;
83 }
84 rep -= 1;
85 return ~(~0ull >> rep);
86}
87
Richard Henderson6fcb98e2020-03-30 17:44:30 -070088static inline TempOptInfo *ts_info(TCGTemp *ts)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020089{
Richard Henderson63490392017-06-20 13:43:15 -070090 return ts->state_ptr;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020091}
92
Richard Henderson6fcb98e2020-03-30 17:44:30 -070093static inline TempOptInfo *arg_info(TCGArg arg)
Aurelien Jarnod9c769c2015-07-27 12:41:44 +020094{
Richard Henderson63490392017-06-20 13:43:15 -070095 return ts_info(arg_temp(arg));
96}
97
98static inline bool ts_is_const(TCGTemp *ts)
99{
100 return ts_info(ts)->is_const;
101}
102
103static inline bool arg_is_const(TCGArg arg)
104{
105 return ts_is_const(arg_temp(arg));
106}
107
108static inline bool ts_is_copy(TCGTemp *ts)
109{
110 return ts_info(ts)->next_copy != ts;
Aurelien Jarnod9c769c2015-07-27 12:41:44 +0200111}
112
Aurelien Jarnob41059d2015-07-27 12:41:44 +0200113/* Reset TEMP's state, possibly removing the temp for the list of copies. */
Richard Henderson63490392017-06-20 13:43:15 -0700114static void reset_ts(TCGTemp *ts)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400115{
Richard Henderson6fcb98e2020-03-30 17:44:30 -0700116 TempOptInfo *ti = ts_info(ts);
117 TempOptInfo *pi = ts_info(ti->prev_copy);
118 TempOptInfo *ni = ts_info(ti->next_copy);
Richard Henderson63490392017-06-20 13:43:15 -0700119
120 ni->prev_copy = ti->prev_copy;
121 pi->next_copy = ti->next_copy;
122 ti->next_copy = ts;
123 ti->prev_copy = ts;
124 ti->is_const = false;
Richard Hendersonb1fde412021-08-23 13:07:49 -0700125 ti->z_mask = -1;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700126 ti->s_mask = 0;
Richard Henderson63490392017-06-20 13:43:15 -0700127}
128
129static void reset_temp(TCGArg arg)
130{
131 reset_ts(arg_temp(arg));
Kirill Batuzov22613af2011-07-07 16:37:13 +0400132}
133
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200134/* Initialize and activate a temporary. */
Richard Henderson3b3f8472021-08-23 22:06:31 -0700135static void init_ts_info(OptContext *ctx, TCGTemp *ts)
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200136{
Richard Henderson63490392017-06-20 13:43:15 -0700137 size_t idx = temp_idx(ts);
Richard Henderson8f17a972020-03-30 19:52:02 -0700138 TempOptInfo *ti;
Richard Henderson63490392017-06-20 13:43:15 -0700139
Richard Henderson3b3f8472021-08-23 22:06:31 -0700140 if (test_bit(idx, ctx->temps_used.l)) {
Richard Henderson8f17a972020-03-30 19:52:02 -0700141 return;
142 }
Richard Henderson3b3f8472021-08-23 22:06:31 -0700143 set_bit(idx, ctx->temps_used.l);
Richard Henderson8f17a972020-03-30 19:52:02 -0700144
145 ti = ts->state_ptr;
146 if (ti == NULL) {
147 ti = tcg_malloc(sizeof(TempOptInfo));
Richard Henderson63490392017-06-20 13:43:15 -0700148 ts->state_ptr = ti;
Richard Henderson8f17a972020-03-30 19:52:02 -0700149 }
150
151 ti->next_copy = ts;
152 ti->prev_copy = ts;
153 if (ts->kind == TEMP_CONST) {
154 ti->is_const = true;
155 ti->val = ts->val;
Richard Hendersonb1fde412021-08-23 13:07:49 -0700156 ti->z_mask = ts->val;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700157 ti->s_mask = smask_from_value(ts->val);
Richard Henderson8f17a972020-03-30 19:52:02 -0700158 } else {
159 ti->is_const = false;
Richard Hendersonb1fde412021-08-23 13:07:49 -0700160 ti->z_mask = -1;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700161 ti->s_mask = 0;
Aurelien Jarno1208d7d2015-07-27 12:41:44 +0200162 }
163}
164
Richard Henderson63490392017-06-20 13:43:15 -0700165static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200166{
Richard Henderson4c868ce2020-04-23 09:02:23 -0700167 TCGTemp *i, *g, *l;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200168
Richard Henderson4c868ce2020-04-23 09:02:23 -0700169 /* If this is already readonly, we can't do better. */
170 if (temp_readonly(ts)) {
Richard Henderson63490392017-06-20 13:43:15 -0700171 return ts;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200172 }
173
Richard Henderson4c868ce2020-04-23 09:02:23 -0700174 g = l = NULL;
Richard Henderson63490392017-06-20 13:43:15 -0700175 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
Richard Henderson4c868ce2020-04-23 09:02:23 -0700176 if (temp_readonly(i)) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200177 return i;
Richard Henderson4c868ce2020-04-23 09:02:23 -0700178 } else if (i->kind > ts->kind) {
179 if (i->kind == TEMP_GLOBAL) {
180 g = i;
181 } else if (i->kind == TEMP_LOCAL) {
182 l = i;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200183 }
184 }
185 }
186
Richard Henderson4c868ce2020-04-23 09:02:23 -0700187 /* If we didn't find a better representation, return the same temp. */
188 return g ? g : l ? l : ts;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200189}
190
Richard Henderson63490392017-06-20 13:43:15 -0700191static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200192{
Richard Henderson63490392017-06-20 13:43:15 -0700193 TCGTemp *i;
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200194
Richard Henderson63490392017-06-20 13:43:15 -0700195 if (ts1 == ts2) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200196 return true;
197 }
198
Richard Henderson63490392017-06-20 13:43:15 -0700199 if (!ts_is_copy(ts1) || !ts_is_copy(ts2)) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200200 return false;
201 }
202
Richard Henderson63490392017-06-20 13:43:15 -0700203 for (i = ts_info(ts1)->next_copy; i != ts1; i = ts_info(i)->next_copy) {
204 if (i == ts2) {
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +0200205 return true;
206 }
207 }
208
209 return false;
210}
211
Richard Henderson63490392017-06-20 13:43:15 -0700212static bool args_are_copies(TCGArg arg1, TCGArg arg2)
213{
214 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
215}
216
Richard Henderson6b99d5b2021-08-24 10:57:56 -0700217static bool tcg_opt_gen_mov(OptContext *ctx, TCGOp *op, TCGArg dst, TCGArg src)
Kirill Batuzov22613af2011-07-07 16:37:13 +0400218{
Richard Henderson63490392017-06-20 13:43:15 -0700219 TCGTemp *dst_ts = arg_temp(dst);
220 TCGTemp *src_ts = arg_temp(src);
Richard Henderson6fcb98e2020-03-30 17:44:30 -0700221 TempOptInfo *di;
222 TempOptInfo *si;
Richard Henderson63490392017-06-20 13:43:15 -0700223 TCGOpcode new_op;
224
225 if (ts_are_copies(dst_ts, src_ts)) {
Richard Hendersondc849882021-08-24 07:13:45 -0700226 tcg_op_remove(ctx->tcg, op);
Richard Henderson6b99d5b2021-08-24 10:57:56 -0700227 return true;
Aurelien Jarno53657182015-06-04 21:53:25 +0200228 }
229
Richard Henderson63490392017-06-20 13:43:15 -0700230 reset_ts(dst_ts);
231 di = ts_info(dst_ts);
232 si = ts_info(src_ts);
Richard Henderson67f84c92021-08-25 08:00:20 -0700233
234 switch (ctx->type) {
235 case TCG_TYPE_I32:
Richard Henderson170ba882017-11-22 09:07:11 +0100236 new_op = INDEX_op_mov_i32;
Richard Henderson67f84c92021-08-25 08:00:20 -0700237 break;
238 case TCG_TYPE_I64:
239 new_op = INDEX_op_mov_i64;
240 break;
241 case TCG_TYPE_V64:
242 case TCG_TYPE_V128:
243 case TCG_TYPE_V256:
244 /* TCGOP_VECL and TCGOP_VECE remain unchanged. */
245 new_op = INDEX_op_mov_vec;
246 break;
247 default:
248 g_assert_not_reached();
Richard Henderson170ba882017-11-22 09:07:11 +0100249 }
Richard Hendersonc45cb8b2014-09-19 13:49:15 -0700250 op->opc = new_op;
Richard Henderson63490392017-06-20 13:43:15 -0700251 op->args[0] = dst;
252 op->args[1] = src;
Richard Hendersona62f6f52014-05-22 10:59:12 -0700253
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700254 di->z_mask = si->z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700255 di->s_mask = si->s_mask;
Richard Henderson24666ba2014-05-22 11:14:10 -0700256
Richard Henderson63490392017-06-20 13:43:15 -0700257 if (src_ts->type == dst_ts->type) {
Richard Henderson6fcb98e2020-03-30 17:44:30 -0700258 TempOptInfo *ni = ts_info(si->next_copy);
Richard Henderson63490392017-06-20 13:43:15 -0700259
260 di->next_copy = si->next_copy;
261 di->prev_copy = src_ts;
262 ni->prev_copy = dst_ts;
263 si->next_copy = dst_ts;
264 di->is_const = si->is_const;
265 di->val = si->val;
Paolo Bonzini3a9d8b12013-01-11 15:42:52 -0800266 }
Richard Henderson6b99d5b2021-08-24 10:57:56 -0700267 return true;
Kirill Batuzov22613af2011-07-07 16:37:13 +0400268}
269
Richard Henderson6b99d5b2021-08-24 10:57:56 -0700270static bool tcg_opt_gen_movi(OptContext *ctx, TCGOp *op,
Richard Hendersondc849882021-08-24 07:13:45 -0700271 TCGArg dst, uint64_t val)
Richard Henderson8fe35e02020-03-30 20:42:43 -0700272{
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700273 TCGTemp *tv;
Richard Henderson67f84c92021-08-25 08:00:20 -0700274
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700275 if (ctx->type == TCG_TYPE_I32) {
276 val = (int32_t)val;
277 }
278
279 /* Convert movi to mov with constant temp. */
280 tv = tcg_constant_internal(ctx->type, val);
Richard Henderson3b3f8472021-08-23 22:06:31 -0700281 init_ts_info(ctx, tv);
Richard Henderson6b99d5b2021-08-24 10:57:56 -0700282 return tcg_opt_gen_mov(ctx, op, dst, temp_arg(tv));
Richard Henderson8fe35e02020-03-30 20:42:43 -0700283}
284
Richard Henderson54795542020-09-06 16:21:32 -0700285static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400286{
Richard Henderson03271522013-08-14 14:35:56 -0700287 uint64_t l64, h64;
288
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400289 switch (op) {
290 CASE_OP_32_64(add):
291 return x + y;
292
293 CASE_OP_32_64(sub):
294 return x - y;
295
296 CASE_OP_32_64(mul):
297 return x * y;
298
Kirill Batuzov9a810902011-07-07 16:37:15 +0400299 CASE_OP_32_64(and):
300 return x & y;
301
302 CASE_OP_32_64(or):
303 return x | y;
304
305 CASE_OP_32_64(xor):
306 return x ^ y;
307
Kirill Batuzov55c09752011-07-07 16:37:16 +0400308 case INDEX_op_shl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700309 return (uint32_t)x << (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400310
Kirill Batuzov55c09752011-07-07 16:37:16 +0400311 case INDEX_op_shl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700312 return (uint64_t)x << (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400313
314 case INDEX_op_shr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700315 return (uint32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400316
Kirill Batuzov55c09752011-07-07 16:37:16 +0400317 case INDEX_op_shr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700318 return (uint64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400319
320 case INDEX_op_sar_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700321 return (int32_t)x >> (y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400322
Kirill Batuzov55c09752011-07-07 16:37:16 +0400323 case INDEX_op_sar_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700324 return (int64_t)x >> (y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400325
326 case INDEX_op_rotr_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700327 return ror32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400328
Kirill Batuzov55c09752011-07-07 16:37:16 +0400329 case INDEX_op_rotr_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700330 return ror64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400331
332 case INDEX_op_rotl_i32:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700333 return rol32(x, y & 31);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400334
Kirill Batuzov55c09752011-07-07 16:37:16 +0400335 case INDEX_op_rotl_i64:
Richard Henderson50c5c4d2014-03-18 07:45:39 -0700336 return rol64(x, y & 63);
Kirill Batuzov55c09752011-07-07 16:37:16 +0400337
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700338 CASE_OP_32_64(not):
Kirill Batuzova640f032011-07-07 16:37:17 +0400339 return ~x;
340
Richard Hendersoncb25c802011-08-17 14:11:47 -0700341 CASE_OP_32_64(neg):
342 return -x;
343
344 CASE_OP_32_64(andc):
345 return x & ~y;
346
347 CASE_OP_32_64(orc):
348 return x | ~y;
349
350 CASE_OP_32_64(eqv):
351 return ~(x ^ y);
352
353 CASE_OP_32_64(nand):
354 return ~(x & y);
355
356 CASE_OP_32_64(nor):
357 return ~(x | y);
358
Richard Henderson0e28d002016-11-16 09:23:28 +0100359 case INDEX_op_clz_i32:
360 return (uint32_t)x ? clz32(x) : y;
361
362 case INDEX_op_clz_i64:
363 return x ? clz64(x) : y;
364
365 case INDEX_op_ctz_i32:
366 return (uint32_t)x ? ctz32(x) : y;
367
368 case INDEX_op_ctz_i64:
369 return x ? ctz64(x) : y;
370
Richard Hendersona768e4e2016-11-21 11:13:39 +0100371 case INDEX_op_ctpop_i32:
372 return ctpop32(x);
373
374 case INDEX_op_ctpop_i64:
375 return ctpop64(x);
376
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700377 CASE_OP_32_64(ext8s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400378 return (int8_t)x;
379
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700380 CASE_OP_32_64(ext16s):
Kirill Batuzova640f032011-07-07 16:37:17 +0400381 return (int16_t)x;
382
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700383 CASE_OP_32_64(ext8u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400384 return (uint8_t)x;
385
Richard Henderson25c4d9c2011-08-17 14:11:46 -0700386 CASE_OP_32_64(ext16u):
Kirill Batuzova640f032011-07-07 16:37:17 +0400387 return (uint16_t)x;
388
Richard Henderson64985942018-11-20 08:53:34 +0100389 CASE_OP_32_64(bswap16):
Richard Henderson0b76ff82021-06-13 13:04:00 -0700390 x = bswap16(x);
391 return y & TCG_BSWAP_OS ? (int16_t)x : x;
Richard Henderson64985942018-11-20 08:53:34 +0100392
393 CASE_OP_32_64(bswap32):
Richard Henderson0b76ff82021-06-13 13:04:00 -0700394 x = bswap32(x);
395 return y & TCG_BSWAP_OS ? (int32_t)x : x;
Richard Henderson64985942018-11-20 08:53:34 +0100396
397 case INDEX_op_bswap64_i64:
398 return bswap64(x);
399
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200400 case INDEX_op_ext_i32_i64:
Kirill Batuzova640f032011-07-07 16:37:17 +0400401 case INDEX_op_ext32s_i64:
402 return (int32_t)x;
403
Aurelien Jarno8bcb5c82015-07-27 12:41:45 +0200404 case INDEX_op_extu_i32_i64:
Richard Henderson609ad702015-07-24 07:16:00 -0700405 case INDEX_op_extrl_i64_i32:
Kirill Batuzova640f032011-07-07 16:37:17 +0400406 case INDEX_op_ext32u_i64:
407 return (uint32_t)x;
Kirill Batuzova640f032011-07-07 16:37:17 +0400408
Richard Henderson609ad702015-07-24 07:16:00 -0700409 case INDEX_op_extrh_i64_i32:
410 return (uint64_t)x >> 32;
411
Richard Henderson03271522013-08-14 14:35:56 -0700412 case INDEX_op_muluh_i32:
413 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
414 case INDEX_op_mulsh_i32:
415 return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
416
417 case INDEX_op_muluh_i64:
418 mulu64(&l64, &h64, x, y);
419 return h64;
420 case INDEX_op_mulsh_i64:
421 muls64(&l64, &h64, x, y);
422 return h64;
423
Richard Henderson01547f72013-08-14 15:22:46 -0700424 case INDEX_op_div_i32:
425 /* Avoid crashing on divide by zero, otherwise undefined. */
426 return (int32_t)x / ((int32_t)y ? : 1);
427 case INDEX_op_divu_i32:
428 return (uint32_t)x / ((uint32_t)y ? : 1);
429 case INDEX_op_div_i64:
430 return (int64_t)x / ((int64_t)y ? : 1);
431 case INDEX_op_divu_i64:
432 return (uint64_t)x / ((uint64_t)y ? : 1);
433
434 case INDEX_op_rem_i32:
435 return (int32_t)x % ((int32_t)y ? : 1);
436 case INDEX_op_remu_i32:
437 return (uint32_t)x % ((uint32_t)y ? : 1);
438 case INDEX_op_rem_i64:
439 return (int64_t)x % ((int64_t)y ? : 1);
440 case INDEX_op_remu_i64:
441 return (uint64_t)x % ((uint64_t)y ? : 1);
442
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400443 default:
444 fprintf(stderr,
445 "Unrecognized operation %d in do_constant_folding.\n", op);
446 tcg_abort();
447 }
448}
449
Richard Henderson67f84c92021-08-25 08:00:20 -0700450static uint64_t do_constant_folding(TCGOpcode op, TCGType type,
451 uint64_t x, uint64_t y)
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400452{
Richard Henderson54795542020-09-06 16:21:32 -0700453 uint64_t res = do_constant_folding_2(op, x, y);
Richard Henderson67f84c92021-08-25 08:00:20 -0700454 if (type == TCG_TYPE_I32) {
Aurelien Jarno29f3ff82015-07-10 18:03:31 +0200455 res = (int32_t)res;
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400456 }
Kirill Batuzov53108fb2011-07-07 16:37:14 +0400457 return res;
458}
459
Richard Henderson9519da72012-10-02 11:32:26 -0700460static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
461{
462 switch (c) {
463 case TCG_COND_EQ:
464 return x == y;
465 case TCG_COND_NE:
466 return x != y;
467 case TCG_COND_LT:
468 return (int32_t)x < (int32_t)y;
469 case TCG_COND_GE:
470 return (int32_t)x >= (int32_t)y;
471 case TCG_COND_LE:
472 return (int32_t)x <= (int32_t)y;
473 case TCG_COND_GT:
474 return (int32_t)x > (int32_t)y;
475 case TCG_COND_LTU:
476 return x < y;
477 case TCG_COND_GEU:
478 return x >= y;
479 case TCG_COND_LEU:
480 return x <= y;
481 case TCG_COND_GTU:
482 return x > y;
483 default:
484 tcg_abort();
485 }
486}
487
488static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
489{
490 switch (c) {
491 case TCG_COND_EQ:
492 return x == y;
493 case TCG_COND_NE:
494 return x != y;
495 case TCG_COND_LT:
496 return (int64_t)x < (int64_t)y;
497 case TCG_COND_GE:
498 return (int64_t)x >= (int64_t)y;
499 case TCG_COND_LE:
500 return (int64_t)x <= (int64_t)y;
501 case TCG_COND_GT:
502 return (int64_t)x > (int64_t)y;
503 case TCG_COND_LTU:
504 return x < y;
505 case TCG_COND_GEU:
506 return x >= y;
507 case TCG_COND_LEU:
508 return x <= y;
509 case TCG_COND_GTU:
510 return x > y;
511 default:
512 tcg_abort();
513 }
514}
515
516static bool do_constant_folding_cond_eq(TCGCond c)
517{
518 switch (c) {
519 case TCG_COND_GT:
520 case TCG_COND_LTU:
521 case TCG_COND_LT:
522 case TCG_COND_GTU:
523 case TCG_COND_NE:
524 return 0;
525 case TCG_COND_GE:
526 case TCG_COND_GEU:
527 case TCG_COND_LE:
528 case TCG_COND_LEU:
529 case TCG_COND_EQ:
530 return 1;
531 default:
532 tcg_abort();
533 }
534}
535
Richard Henderson8d57bf12021-08-24 08:34:27 -0700536/*
537 * Return -1 if the condition can't be simplified,
538 * and the result of the condition (0 or 1) if it can.
539 */
Richard Henderson67f84c92021-08-25 08:00:20 -0700540static int do_constant_folding_cond(TCGType type, TCGArg x,
Richard Henderson8d57bf12021-08-24 08:34:27 -0700541 TCGArg y, TCGCond c)
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200542{
Richard Henderson54795542020-09-06 16:21:32 -0700543 uint64_t xv = arg_info(x)->val;
544 uint64_t yv = arg_info(y)->val;
545
Richard Henderson63490392017-06-20 13:43:15 -0700546 if (arg_is_const(x) && arg_is_const(y)) {
Richard Henderson67f84c92021-08-25 08:00:20 -0700547 switch (type) {
548 case TCG_TYPE_I32:
Richard Henderson170ba882017-11-22 09:07:11 +0100549 return do_constant_folding_cond_32(xv, yv, c);
Richard Henderson67f84c92021-08-25 08:00:20 -0700550 case TCG_TYPE_I64:
551 return do_constant_folding_cond_64(xv, yv, c);
552 default:
553 /* Only scalar comparisons are optimizable */
554 return -1;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200555 }
Richard Henderson63490392017-06-20 13:43:15 -0700556 } else if (args_are_copies(x, y)) {
Richard Henderson9519da72012-10-02 11:32:26 -0700557 return do_constant_folding_cond_eq(c);
Richard Henderson63490392017-06-20 13:43:15 -0700558 } else if (arg_is_const(y) && yv == 0) {
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200559 switch (c) {
560 case TCG_COND_LTU:
561 return 0;
562 case TCG_COND_GEU:
563 return 1;
564 default:
Richard Henderson8d57bf12021-08-24 08:34:27 -0700565 return -1;
Aurelien Jarnob336ceb2012-09-18 19:37:00 +0200566 }
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200567 }
Richard Henderson8d57bf12021-08-24 08:34:27 -0700568 return -1;
Aurelien Jarnof8dd19e2012-09-06 16:47:14 +0200569}
570
Richard Henderson8d57bf12021-08-24 08:34:27 -0700571/*
572 * Return -1 if the condition can't be simplified,
573 * and the result of the condition (0 or 1) if it can.
574 */
575static int do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
Richard Henderson6c4382f2012-10-02 11:32:27 -0700576{
577 TCGArg al = p1[0], ah = p1[1];
578 TCGArg bl = p2[0], bh = p2[1];
579
Richard Henderson63490392017-06-20 13:43:15 -0700580 if (arg_is_const(bl) && arg_is_const(bh)) {
581 tcg_target_ulong blv = arg_info(bl)->val;
582 tcg_target_ulong bhv = arg_info(bh)->val;
583 uint64_t b = deposit64(blv, 32, 32, bhv);
Richard Henderson6c4382f2012-10-02 11:32:27 -0700584
Richard Henderson63490392017-06-20 13:43:15 -0700585 if (arg_is_const(al) && arg_is_const(ah)) {
586 tcg_target_ulong alv = arg_info(al)->val;
587 tcg_target_ulong ahv = arg_info(ah)->val;
588 uint64_t a = deposit64(alv, 32, 32, ahv);
Richard Henderson6c4382f2012-10-02 11:32:27 -0700589 return do_constant_folding_cond_64(a, b, c);
590 }
591 if (b == 0) {
592 switch (c) {
593 case TCG_COND_LTU:
594 return 0;
595 case TCG_COND_GEU:
596 return 1;
597 default:
598 break;
599 }
600 }
601 }
Richard Henderson63490392017-06-20 13:43:15 -0700602 if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
Richard Henderson6c4382f2012-10-02 11:32:27 -0700603 return do_constant_folding_cond_eq(c);
604 }
Richard Henderson8d57bf12021-08-24 08:34:27 -0700605 return -1;
Richard Henderson6c4382f2012-10-02 11:32:27 -0700606}
607
Richard Henderson7a2f7082021-08-26 07:06:39 -0700608/**
609 * swap_commutative:
610 * @dest: TCGArg of the destination argument, or NO_DEST.
611 * @p1: first paired argument
612 * @p2: second paired argument
613 *
614 * If *@p1 is a constant and *@p2 is not, swap.
615 * If *@p2 matches @dest, swap.
616 * Return true if a swap was performed.
617 */
618
619#define NO_DEST temp_arg(NULL)
620
Richard Henderson24c9ae42012-10-02 11:32:21 -0700621static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
622{
623 TCGArg a1 = *p1, a2 = *p2;
624 int sum = 0;
Richard Henderson63490392017-06-20 13:43:15 -0700625 sum += arg_is_const(a1);
626 sum -= arg_is_const(a2);
Richard Henderson24c9ae42012-10-02 11:32:21 -0700627
628 /* Prefer the constant in second argument, and then the form
629 op a, a, b, which is better handled on non-RISC hosts. */
630 if (sum > 0 || (sum == 0 && dest == a2)) {
631 *p1 = a2;
632 *p2 = a1;
633 return true;
634 }
635 return false;
636}
637
Richard Henderson0bfcb862012-10-02 11:32:23 -0700638static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
639{
640 int sum = 0;
Richard Henderson63490392017-06-20 13:43:15 -0700641 sum += arg_is_const(p1[0]);
642 sum += arg_is_const(p1[1]);
643 sum -= arg_is_const(p2[0]);
644 sum -= arg_is_const(p2[1]);
Richard Henderson0bfcb862012-10-02 11:32:23 -0700645 if (sum > 0) {
646 TCGArg t;
647 t = p1[0], p1[0] = p2[0], p2[0] = t;
648 t = p1[1], p1[1] = p2[1], p2[1] = t;
649 return true;
650 }
651 return false;
652}
653
Richard Hendersone2577ea2021-08-24 08:00:48 -0700654static void init_arguments(OptContext *ctx, TCGOp *op, int nb_args)
655{
656 for (int i = 0; i < nb_args; i++) {
657 TCGTemp *ts = arg_temp(op->args[i]);
658 if (ts) {
659 init_ts_info(ctx, ts);
660 }
661 }
662}
663
Richard Henderson8774dde2021-08-24 08:04:47 -0700664static void copy_propagate(OptContext *ctx, TCGOp *op,
665 int nb_oargs, int nb_iargs)
666{
667 TCGContext *s = ctx->tcg;
668
669 for (int i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
670 TCGTemp *ts = arg_temp(op->args[i]);
671 if (ts && ts_is_copy(ts)) {
672 op->args[i] = temp_arg(find_better_copy(s, ts));
673 }
674 }
675}
676
Richard Henderson137f1f42021-08-24 08:49:25 -0700677static void finish_folding(OptContext *ctx, TCGOp *op)
678{
679 const TCGOpDef *def = &tcg_op_defs[op->opc];
680 int i, nb_oargs;
681
682 /*
683 * For an opcode that ends a BB, reset all temp data.
684 * We do no cross-BB optimization.
685 */
686 if (def->flags & TCG_OPF_BB_END) {
687 memset(&ctx->temps_used, 0, sizeof(ctx->temps_used));
688 ctx->prev_mb = NULL;
689 return;
690 }
691
692 nb_oargs = def->nb_oargs;
693 for (i = 0; i < nb_oargs; i++) {
Richard Henderson57fe5c62021-08-26 12:04:46 -0700694 TCGTemp *ts = arg_temp(op->args[i]);
695 reset_ts(ts);
Richard Henderson137f1f42021-08-24 08:49:25 -0700696 /*
Richard Henderson57fe5c62021-08-26 12:04:46 -0700697 * Save the corresponding known-zero/sign bits mask for the
Richard Henderson137f1f42021-08-24 08:49:25 -0700698 * first output argument (only one supported so far).
699 */
700 if (i == 0) {
Richard Henderson57fe5c62021-08-26 12:04:46 -0700701 ts_info(ts)->z_mask = ctx->z_mask;
702 ts_info(ts)->s_mask = ctx->s_mask;
Richard Henderson137f1f42021-08-24 08:49:25 -0700703 }
704 }
705}
706
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700707/*
708 * The fold_* functions return true when processing is complete,
709 * usually by folding the operation to a constant or to a copy,
710 * and calling tcg_opt_gen_{mov,movi}. They may do other things,
711 * like collect information about the value produced, for use in
712 * optimizing a subsequent operation.
713 *
714 * These first fold_* functions are all helpers, used by other
715 * folders for more specific operations.
716 */
717
718static bool fold_const1(OptContext *ctx, TCGOp *op)
719{
720 if (arg_is_const(op->args[1])) {
721 uint64_t t;
722
723 t = arg_info(op->args[1])->val;
Richard Henderson67f84c92021-08-25 08:00:20 -0700724 t = do_constant_folding(op->opc, ctx->type, t, 0);
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700725 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
726 }
727 return false;
728}
729
730static bool fold_const2(OptContext *ctx, TCGOp *op)
731{
732 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
733 uint64_t t1 = arg_info(op->args[1])->val;
734 uint64_t t2 = arg_info(op->args[2])->val;
735
Richard Henderson67f84c92021-08-25 08:00:20 -0700736 t1 = do_constant_folding(op->opc, ctx->type, t1, t2);
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700737 return tcg_opt_gen_movi(ctx, op, op->args[0], t1);
738 }
739 return false;
740}
741
Richard Henderson7a2f7082021-08-26 07:06:39 -0700742static bool fold_const2_commutative(OptContext *ctx, TCGOp *op)
743{
744 swap_commutative(op->args[0], &op->args[1], &op->args[2]);
745 return fold_const2(ctx, op);
746}
747
Richard Hendersonfae450b2021-08-25 22:42:19 -0700748static bool fold_masks(OptContext *ctx, TCGOp *op)
749{
750 uint64_t a_mask = ctx->a_mask;
751 uint64_t z_mask = ctx->z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700752 uint64_t s_mask = ctx->s_mask;
Richard Hendersonfae450b2021-08-25 22:42:19 -0700753
754 /*
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700755 * 32-bit ops generate 32-bit results, which for the purpose of
756 * simplifying tcg are sign-extended. Certainly that's how we
757 * represent our constants elsewhere. Note that the bits will
758 * be reset properly for a 64-bit value when encountering the
759 * type changing opcodes.
Richard Hendersonfae450b2021-08-25 22:42:19 -0700760 */
761 if (ctx->type == TCG_TYPE_I32) {
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700762 a_mask = (int32_t)a_mask;
763 z_mask = (int32_t)z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700764 s_mask |= MAKE_64BIT_MASK(32, 32);
Richard Hendersonfaa2e102021-08-26 09:03:59 -0700765 ctx->z_mask = z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -0700766 ctx->s_mask = s_mask;
Richard Hendersonfae450b2021-08-25 22:42:19 -0700767 }
768
769 if (z_mask == 0) {
770 return tcg_opt_gen_movi(ctx, op, op->args[0], 0);
771 }
772 if (a_mask == 0) {
773 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
774 }
775 return false;
776}
777
Richard Henderson0e0a32b2021-08-24 13:18:01 -0700778/*
779 * Convert @op to NOT, if NOT is supported by the host.
780 * Return true f the conversion is successful, which will still
781 * indicate that the processing is complete.
782 */
783static bool fold_not(OptContext *ctx, TCGOp *op);
784static bool fold_to_not(OptContext *ctx, TCGOp *op, int idx)
785{
786 TCGOpcode not_op;
787 bool have_not;
788
789 switch (ctx->type) {
790 case TCG_TYPE_I32:
791 not_op = INDEX_op_not_i32;
792 have_not = TCG_TARGET_HAS_not_i32;
793 break;
794 case TCG_TYPE_I64:
795 not_op = INDEX_op_not_i64;
796 have_not = TCG_TARGET_HAS_not_i64;
797 break;
798 case TCG_TYPE_V64:
799 case TCG_TYPE_V128:
800 case TCG_TYPE_V256:
801 not_op = INDEX_op_not_vec;
802 have_not = TCG_TARGET_HAS_not_vec;
803 break;
804 default:
805 g_assert_not_reached();
806 }
807 if (have_not) {
808 op->opc = not_op;
809 op->args[1] = op->args[idx];
810 return fold_not(ctx, op);
811 }
812 return false;
813}
814
Richard Hendersonda48e272021-08-25 20:42:04 -0700815/* If the binary operation has first argument @i, fold to @i. */
816static bool fold_ix_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
817{
818 if (arg_is_const(op->args[1]) && arg_info(op->args[1])->val == i) {
819 return tcg_opt_gen_movi(ctx, op, op->args[0], i);
820 }
821 return false;
822}
823
Richard Henderson0e0a32b2021-08-24 13:18:01 -0700824/* If the binary operation has first argument @i, fold to NOT. */
825static bool fold_ix_to_not(OptContext *ctx, TCGOp *op, uint64_t i)
826{
827 if (arg_is_const(op->args[1]) && arg_info(op->args[1])->val == i) {
828 return fold_to_not(ctx, op, 2);
829 }
830 return false;
831}
832
Richard Hendersone8679952021-08-25 13:19:52 -0700833/* If the binary operation has second argument @i, fold to @i. */
834static bool fold_xi_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
835{
836 if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
837 return tcg_opt_gen_movi(ctx, op, op->args[0], i);
838 }
839 return false;
840}
841
Richard Hendersona63ce0e2021-08-25 20:28:53 -0700842/* If the binary operation has second argument @i, fold to identity. */
843static bool fold_xi_to_x(OptContext *ctx, TCGOp *op, uint64_t i)
844{
845 if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
846 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
847 }
848 return false;
849}
850
Richard Henderson0e0a32b2021-08-24 13:18:01 -0700851/* If the binary operation has second argument @i, fold to NOT. */
852static bool fold_xi_to_not(OptContext *ctx, TCGOp *op, uint64_t i)
853{
854 if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
855 return fold_to_not(ctx, op, 1);
856 }
857 return false;
858}
859
Richard Hendersoncbe42fb2021-08-25 13:02:00 -0700860/* If the binary operation has both arguments equal, fold to @i. */
861static bool fold_xx_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
862{
863 if (args_are_copies(op->args[1], op->args[2])) {
864 return tcg_opt_gen_movi(ctx, op, op->args[0], i);
865 }
866 return false;
867}
868
Richard Hendersonca7bb042021-08-25 13:14:21 -0700869/* If the binary operation has both arguments equal, fold to identity. */
870static bool fold_xx_to_x(OptContext *ctx, TCGOp *op)
871{
872 if (args_are_copies(op->args[1], op->args[2])) {
873 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
874 }
875 return false;
876}
877
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700878/*
879 * These outermost fold_<op> functions are sorted alphabetically.
Richard Hendersonca7bb042021-08-25 13:14:21 -0700880 *
881 * The ordering of the transformations should be:
882 * 1) those that produce a constant
883 * 2) those that produce a copy
884 * 3) those that produce information about the result value.
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700885 */
886
887static bool fold_add(OptContext *ctx, TCGOp *op)
888{
Richard Henderson7a2f7082021-08-26 07:06:39 -0700889 if (fold_const2_commutative(ctx, op) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -0700890 fold_xi_to_x(ctx, op, 0)) {
891 return true;
892 }
893 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700894}
895
Richard Henderson9531c072021-08-26 06:51:39 -0700896static bool fold_addsub2(OptContext *ctx, TCGOp *op, bool add)
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700897{
898 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3]) &&
899 arg_is_const(op->args[4]) && arg_is_const(op->args[5])) {
Richard Henderson9531c072021-08-26 06:51:39 -0700900 uint64_t al = arg_info(op->args[2])->val;
901 uint64_t ah = arg_info(op->args[3])->val;
902 uint64_t bl = arg_info(op->args[4])->val;
903 uint64_t bh = arg_info(op->args[5])->val;
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700904 TCGArg rl, rh;
Richard Henderson9531c072021-08-26 06:51:39 -0700905 TCGOp *op2;
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700906
Richard Henderson9531c072021-08-26 06:51:39 -0700907 if (ctx->type == TCG_TYPE_I32) {
908 uint64_t a = deposit64(al, 32, 32, ah);
909 uint64_t b = deposit64(bl, 32, 32, bh);
910
911 if (add) {
912 a += b;
913 } else {
914 a -= b;
915 }
916
917 al = sextract64(a, 0, 32);
918 ah = sextract64(a, 32, 32);
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700919 } else {
Richard Henderson9531c072021-08-26 06:51:39 -0700920 Int128 a = int128_make128(al, ah);
921 Int128 b = int128_make128(bl, bh);
922
923 if (add) {
924 a = int128_add(a, b);
925 } else {
926 a = int128_sub(a, b);
927 }
928
929 al = int128_getlo(a);
930 ah = int128_gethi(a);
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700931 }
932
933 rl = op->args[0];
934 rh = op->args[1];
Richard Henderson9531c072021-08-26 06:51:39 -0700935
936 /* The proper opcode is supplied by tcg_opt_gen_mov. */
937 op2 = tcg_op_insert_before(ctx->tcg, op, 0);
938
939 tcg_opt_gen_movi(ctx, op, rl, al);
940 tcg_opt_gen_movi(ctx, op2, rh, ah);
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700941 return true;
942 }
943 return false;
944}
945
Richard Henderson9531c072021-08-26 06:51:39 -0700946static bool fold_add2(OptContext *ctx, TCGOp *op)
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700947{
Richard Henderson7a2f7082021-08-26 07:06:39 -0700948 /* Note that the high and low parts may be independently swapped. */
949 swap_commutative(op->args[0], &op->args[2], &op->args[4]);
950 swap_commutative(op->args[1], &op->args[3], &op->args[5]);
951
Richard Henderson9531c072021-08-26 06:51:39 -0700952 return fold_addsub2(ctx, op, true);
Richard Hendersone3f7dc22021-08-24 10:30:38 -0700953}
954
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700955static bool fold_and(OptContext *ctx, TCGOp *op)
956{
Richard Hendersonfae450b2021-08-25 22:42:19 -0700957 uint64_t z1, z2;
958
Richard Henderson7a2f7082021-08-26 07:06:39 -0700959 if (fold_const2_commutative(ctx, op) ||
Richard Hendersone8679952021-08-25 13:19:52 -0700960 fold_xi_to_i(ctx, op, 0) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -0700961 fold_xi_to_x(ctx, op, -1) ||
Richard Hendersonca7bb042021-08-25 13:14:21 -0700962 fold_xx_to_x(ctx, op)) {
963 return true;
964 }
Richard Hendersonfae450b2021-08-25 22:42:19 -0700965
966 z1 = arg_info(op->args[1])->z_mask;
967 z2 = arg_info(op->args[2])->z_mask;
968 ctx->z_mask = z1 & z2;
969
970 /*
971 * Known-zeros does not imply known-ones. Therefore unless
972 * arg2 is constant, we can't infer affected bits from it.
973 */
974 if (arg_is_const(op->args[2])) {
975 ctx->a_mask = z1 & ~z2;
976 }
977
978 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -0700979}
980
981static bool fold_andc(OptContext *ctx, TCGOp *op)
982{
Richard Hendersonfae450b2021-08-25 22:42:19 -0700983 uint64_t z1;
984
Richard Hendersoncbe42fb2021-08-25 13:02:00 -0700985 if (fold_const2(ctx, op) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -0700986 fold_xx_to_i(ctx, op, 0) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -0700987 fold_xi_to_x(ctx, op, 0) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -0700988 fold_ix_to_not(ctx, op, -1)) {
Richard Hendersoncbe42fb2021-08-25 13:02:00 -0700989 return true;
990 }
Richard Hendersonfae450b2021-08-25 22:42:19 -0700991
992 z1 = arg_info(op->args[1])->z_mask;
993
994 /*
995 * Known-zeros does not imply known-ones. Therefore unless
996 * arg2 is constant, we can't infer anything from it.
997 */
998 if (arg_is_const(op->args[2])) {
999 uint64_t z2 = ~arg_info(op->args[2])->z_mask;
1000 ctx->a_mask = z1 & ~z2;
1001 z1 &= z2;
1002 }
1003 ctx->z_mask = z1;
1004
1005 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001006}
1007
Richard Henderson079b0802021-08-24 09:30:59 -07001008static bool fold_brcond(OptContext *ctx, TCGOp *op)
1009{
1010 TCGCond cond = op->args[2];
Richard Henderson7a2f7082021-08-26 07:06:39 -07001011 int i;
Richard Henderson079b0802021-08-24 09:30:59 -07001012
Richard Henderson7a2f7082021-08-26 07:06:39 -07001013 if (swap_commutative(NO_DEST, &op->args[0], &op->args[1])) {
1014 op->args[2] = cond = tcg_swap_cond(cond);
1015 }
1016
1017 i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond);
Richard Henderson079b0802021-08-24 09:30:59 -07001018 if (i == 0) {
1019 tcg_op_remove(ctx->tcg, op);
1020 return true;
1021 }
1022 if (i > 0) {
1023 op->opc = INDEX_op_br;
1024 op->args[0] = op->args[3];
1025 }
1026 return false;
1027}
1028
Richard Henderson764d2ab2021-08-24 09:22:11 -07001029static bool fold_brcond2(OptContext *ctx, TCGOp *op)
1030{
1031 TCGCond cond = op->args[4];
Richard Henderson764d2ab2021-08-24 09:22:11 -07001032 TCGArg label = op->args[5];
Richard Henderson7a2f7082021-08-26 07:06:39 -07001033 int i, inv = 0;
Richard Henderson764d2ab2021-08-24 09:22:11 -07001034
Richard Henderson7a2f7082021-08-26 07:06:39 -07001035 if (swap_commutative2(&op->args[0], &op->args[2])) {
1036 op->args[4] = cond = tcg_swap_cond(cond);
1037 }
1038
1039 i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond);
Richard Henderson764d2ab2021-08-24 09:22:11 -07001040 if (i >= 0) {
1041 goto do_brcond_const;
1042 }
1043
1044 switch (cond) {
1045 case TCG_COND_LT:
1046 case TCG_COND_GE:
1047 /*
1048 * Simplify LT/GE comparisons vs zero to a single compare
1049 * vs the high word of the input.
1050 */
1051 if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == 0 &&
1052 arg_is_const(op->args[3]) && arg_info(op->args[3])->val == 0) {
1053 goto do_brcond_high;
1054 }
1055 break;
1056
1057 case TCG_COND_NE:
1058 inv = 1;
1059 QEMU_FALLTHROUGH;
1060 case TCG_COND_EQ:
1061 /*
1062 * Simplify EQ/NE comparisons where one of the pairs
1063 * can be simplified.
1064 */
Richard Henderson67f84c92021-08-25 08:00:20 -07001065 i = do_constant_folding_cond(TCG_TYPE_I32, op->args[0],
Richard Henderson764d2ab2021-08-24 09:22:11 -07001066 op->args[2], cond);
1067 switch (i ^ inv) {
1068 case 0:
1069 goto do_brcond_const;
1070 case 1:
1071 goto do_brcond_high;
1072 }
1073
Richard Henderson67f84c92021-08-25 08:00:20 -07001074 i = do_constant_folding_cond(TCG_TYPE_I32, op->args[1],
Richard Henderson764d2ab2021-08-24 09:22:11 -07001075 op->args[3], cond);
1076 switch (i ^ inv) {
1077 case 0:
1078 goto do_brcond_const;
1079 case 1:
1080 op->opc = INDEX_op_brcond_i32;
1081 op->args[1] = op->args[2];
1082 op->args[2] = cond;
1083 op->args[3] = label;
1084 break;
1085 }
1086 break;
1087
1088 default:
1089 break;
1090
1091 do_brcond_high:
1092 op->opc = INDEX_op_brcond_i32;
1093 op->args[0] = op->args[1];
1094 op->args[1] = op->args[3];
1095 op->args[2] = cond;
1096 op->args[3] = label;
1097 break;
1098
1099 do_brcond_const:
1100 if (i == 0) {
1101 tcg_op_remove(ctx->tcg, op);
1102 return true;
1103 }
1104 op->opc = INDEX_op_br;
1105 op->args[0] = label;
1106 break;
1107 }
1108 return false;
1109}
1110
Richard Henderson09bacdc2021-08-24 11:58:12 -07001111static bool fold_bswap(OptContext *ctx, TCGOp *op)
1112{
Richard Henderson57fe5c62021-08-26 12:04:46 -07001113 uint64_t z_mask, s_mask, sign;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001114
Richard Henderson09bacdc2021-08-24 11:58:12 -07001115 if (arg_is_const(op->args[1])) {
1116 uint64_t t = arg_info(op->args[1])->val;
1117
Richard Henderson67f84c92021-08-25 08:00:20 -07001118 t = do_constant_folding(op->opc, ctx->type, t, op->args[2]);
Richard Henderson09bacdc2021-08-24 11:58:12 -07001119 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1120 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001121
1122 z_mask = arg_info(op->args[1])->z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001123
Richard Hendersonfae450b2021-08-25 22:42:19 -07001124 switch (op->opc) {
1125 case INDEX_op_bswap16_i32:
1126 case INDEX_op_bswap16_i64:
1127 z_mask = bswap16(z_mask);
1128 sign = INT16_MIN;
1129 break;
1130 case INDEX_op_bswap32_i32:
1131 case INDEX_op_bswap32_i64:
1132 z_mask = bswap32(z_mask);
1133 sign = INT32_MIN;
1134 break;
1135 case INDEX_op_bswap64_i64:
1136 z_mask = bswap64(z_mask);
1137 sign = INT64_MIN;
1138 break;
1139 default:
1140 g_assert_not_reached();
1141 }
Richard Henderson57fe5c62021-08-26 12:04:46 -07001142 s_mask = smask_from_zmask(z_mask);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001143
1144 switch (op->args[2] & (TCG_BSWAP_OZ | TCG_BSWAP_OS)) {
1145 case TCG_BSWAP_OZ:
1146 break;
1147 case TCG_BSWAP_OS:
1148 /* If the sign bit may be 1, force all the bits above to 1. */
1149 if (z_mask & sign) {
1150 z_mask |= sign;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001151 s_mask = sign << 1;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001152 }
1153 break;
1154 default:
1155 /* The high bits are undefined: force all bits above the sign to 1. */
1156 z_mask |= sign << 1;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001157 s_mask = 0;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001158 break;
1159 }
1160 ctx->z_mask = z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001161 ctx->s_mask = s_mask;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001162
1163 return fold_masks(ctx, op);
Richard Henderson09bacdc2021-08-24 11:58:12 -07001164}
1165
Richard Henderson5cf32be2021-08-24 08:17:08 -07001166static bool fold_call(OptContext *ctx, TCGOp *op)
1167{
1168 TCGContext *s = ctx->tcg;
1169 int nb_oargs = TCGOP_CALLO(op);
1170 int nb_iargs = TCGOP_CALLI(op);
1171 int flags, i;
1172
1173 init_arguments(ctx, op, nb_oargs + nb_iargs);
1174 copy_propagate(ctx, op, nb_oargs, nb_iargs);
1175
1176 /* If the function reads or writes globals, reset temp data. */
1177 flags = tcg_call_flags(op);
1178 if (!(flags & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
1179 int nb_globals = s->nb_globals;
1180
1181 for (i = 0; i < nb_globals; i++) {
1182 if (test_bit(i, ctx->temps_used.l)) {
1183 reset_ts(&ctx->tcg->temps[i]);
1184 }
1185 }
1186 }
1187
1188 /* Reset temp data for outputs. */
1189 for (i = 0; i < nb_oargs; i++) {
1190 reset_temp(op->args[i]);
1191 }
1192
1193 /* Stop optimizing MB across calls. */
1194 ctx->prev_mb = NULL;
1195 return true;
1196}
1197
Richard Henderson30dd0bf2021-08-24 10:51:34 -07001198static bool fold_count_zeros(OptContext *ctx, TCGOp *op)
1199{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001200 uint64_t z_mask;
1201
Richard Henderson30dd0bf2021-08-24 10:51:34 -07001202 if (arg_is_const(op->args[1])) {
1203 uint64_t t = arg_info(op->args[1])->val;
1204
1205 if (t != 0) {
Richard Henderson67f84c92021-08-25 08:00:20 -07001206 t = do_constant_folding(op->opc, ctx->type, t, 0);
Richard Henderson30dd0bf2021-08-24 10:51:34 -07001207 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1208 }
1209 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[2]);
1210 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001211
1212 switch (ctx->type) {
1213 case TCG_TYPE_I32:
1214 z_mask = 31;
1215 break;
1216 case TCG_TYPE_I64:
1217 z_mask = 63;
1218 break;
1219 default:
1220 g_assert_not_reached();
1221 }
1222 ctx->z_mask = arg_info(op->args[2])->z_mask | z_mask;
1223
Richard Henderson30dd0bf2021-08-24 10:51:34 -07001224 return false;
1225}
1226
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001227static bool fold_ctpop(OptContext *ctx, TCGOp *op)
1228{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001229 if (fold_const1(ctx, op)) {
1230 return true;
1231 }
1232
1233 switch (ctx->type) {
1234 case TCG_TYPE_I32:
1235 ctx->z_mask = 32 | 31;
1236 break;
1237 case TCG_TYPE_I64:
1238 ctx->z_mask = 64 | 63;
1239 break;
1240 default:
1241 g_assert_not_reached();
1242 }
1243 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001244}
1245
Richard Henderson1b1907b2021-08-24 10:47:04 -07001246static bool fold_deposit(OptContext *ctx, TCGOp *op)
1247{
1248 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1249 uint64_t t1 = arg_info(op->args[1])->val;
1250 uint64_t t2 = arg_info(op->args[2])->val;
1251
1252 t1 = deposit64(t1, op->args[3], op->args[4], t2);
1253 return tcg_opt_gen_movi(ctx, op, op->args[0], t1);
1254 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001255
1256 ctx->z_mask = deposit64(arg_info(op->args[1])->z_mask,
1257 op->args[3], op->args[4],
1258 arg_info(op->args[2])->z_mask);
Richard Henderson1b1907b2021-08-24 10:47:04 -07001259 return false;
1260}
1261
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001262static bool fold_divide(OptContext *ctx, TCGOp *op)
1263{
Richard Henderson2f9d9a32021-10-25 11:30:14 -07001264 if (fold_const2(ctx, op) ||
1265 fold_xi_to_x(ctx, op, 1)) {
1266 return true;
1267 }
1268 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001269}
1270
Richard Henderson8cdb3fc2021-08-24 12:06:33 -07001271static bool fold_dup(OptContext *ctx, TCGOp *op)
1272{
1273 if (arg_is_const(op->args[1])) {
1274 uint64_t t = arg_info(op->args[1])->val;
1275 t = dup_const(TCGOP_VECE(op), t);
1276 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1277 }
1278 return false;
1279}
1280
1281static bool fold_dup2(OptContext *ctx, TCGOp *op)
1282{
1283 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1284 uint64_t t = deposit64(arg_info(op->args[1])->val, 32, 32,
1285 arg_info(op->args[2])->val);
1286 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1287 }
1288
1289 if (args_are_copies(op->args[1], op->args[2])) {
1290 op->opc = INDEX_op_dup_vec;
1291 TCGOP_VECE(op) = MO_32;
1292 }
1293 return false;
1294}
1295
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001296static bool fold_eqv(OptContext *ctx, TCGOp *op)
1297{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001298 if (fold_const2_commutative(ctx, op) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001299 fold_xi_to_x(ctx, op, -1) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001300 fold_xi_to_not(ctx, op, 0)) {
1301 return true;
1302 }
1303 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001304}
1305
Richard Hendersonb6617c82021-08-24 10:44:53 -07001306static bool fold_extract(OptContext *ctx, TCGOp *op)
1307{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001308 uint64_t z_mask_old, z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001309 int pos = op->args[2];
1310 int len = op->args[3];
Richard Hendersonfae450b2021-08-25 22:42:19 -07001311
Richard Hendersonb6617c82021-08-24 10:44:53 -07001312 if (arg_is_const(op->args[1])) {
1313 uint64_t t;
1314
1315 t = arg_info(op->args[1])->val;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001316 t = extract64(t, pos, len);
Richard Hendersonb6617c82021-08-24 10:44:53 -07001317 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1318 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001319
1320 z_mask_old = arg_info(op->args[1])->z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001321 z_mask = extract64(z_mask_old, pos, len);
1322 if (pos == 0) {
Richard Hendersonfae450b2021-08-25 22:42:19 -07001323 ctx->a_mask = z_mask_old ^ z_mask;
1324 }
1325 ctx->z_mask = z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001326 ctx->s_mask = smask_from_zmask(z_mask);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001327
1328 return fold_masks(ctx, op);
Richard Hendersonb6617c82021-08-24 10:44:53 -07001329}
1330
Richard Hendersondcd08992021-08-24 10:41:39 -07001331static bool fold_extract2(OptContext *ctx, TCGOp *op)
1332{
1333 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1334 uint64_t v1 = arg_info(op->args[1])->val;
1335 uint64_t v2 = arg_info(op->args[2])->val;
1336 int shr = op->args[3];
1337
1338 if (op->opc == INDEX_op_extract2_i64) {
1339 v1 >>= shr;
1340 v2 <<= 64 - shr;
1341 } else {
1342 v1 = (uint32_t)v1 >> shr;
1343 v2 = (int32_t)v2 << (32 - shr);
1344 }
1345 return tcg_opt_gen_movi(ctx, op, op->args[0], v1 | v2);
1346 }
1347 return false;
1348}
1349
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001350static bool fold_exts(OptContext *ctx, TCGOp *op)
1351{
Richard Henderson57fe5c62021-08-26 12:04:46 -07001352 uint64_t s_mask_old, s_mask, z_mask, sign;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001353 bool type_change = false;
1354
1355 if (fold_const1(ctx, op)) {
1356 return true;
1357 }
1358
Richard Henderson57fe5c62021-08-26 12:04:46 -07001359 z_mask = arg_info(op->args[1])->z_mask;
1360 s_mask = arg_info(op->args[1])->s_mask;
1361 s_mask_old = s_mask;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001362
1363 switch (op->opc) {
1364 CASE_OP_32_64(ext8s):
1365 sign = INT8_MIN;
1366 z_mask = (uint8_t)z_mask;
1367 break;
1368 CASE_OP_32_64(ext16s):
1369 sign = INT16_MIN;
1370 z_mask = (uint16_t)z_mask;
1371 break;
1372 case INDEX_op_ext_i32_i64:
1373 type_change = true;
1374 QEMU_FALLTHROUGH;
1375 case INDEX_op_ext32s_i64:
1376 sign = INT32_MIN;
1377 z_mask = (uint32_t)z_mask;
1378 break;
1379 default:
1380 g_assert_not_reached();
1381 }
1382
1383 if (z_mask & sign) {
1384 z_mask |= sign;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001385 }
Richard Henderson57fe5c62021-08-26 12:04:46 -07001386 s_mask |= sign << 1;
1387
Richard Hendersonfae450b2021-08-25 22:42:19 -07001388 ctx->z_mask = z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001389 ctx->s_mask = s_mask;
1390 if (!type_change) {
1391 ctx->a_mask = s_mask & ~s_mask_old;
1392 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001393
1394 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001395}
1396
1397static bool fold_extu(OptContext *ctx, TCGOp *op)
1398{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001399 uint64_t z_mask_old, z_mask;
1400 bool type_change = false;
1401
1402 if (fold_const1(ctx, op)) {
1403 return true;
1404 }
1405
1406 z_mask_old = z_mask = arg_info(op->args[1])->z_mask;
1407
1408 switch (op->opc) {
1409 CASE_OP_32_64(ext8u):
1410 z_mask = (uint8_t)z_mask;
1411 break;
1412 CASE_OP_32_64(ext16u):
1413 z_mask = (uint16_t)z_mask;
1414 break;
1415 case INDEX_op_extrl_i64_i32:
1416 case INDEX_op_extu_i32_i64:
1417 type_change = true;
1418 QEMU_FALLTHROUGH;
1419 case INDEX_op_ext32u_i64:
1420 z_mask = (uint32_t)z_mask;
1421 break;
1422 case INDEX_op_extrh_i64_i32:
1423 type_change = true;
1424 z_mask >>= 32;
1425 break;
1426 default:
1427 g_assert_not_reached();
1428 }
1429
1430 ctx->z_mask = z_mask;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001431 ctx->s_mask = smask_from_zmask(z_mask);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001432 if (!type_change) {
1433 ctx->a_mask = z_mask_old ^ z_mask;
1434 }
1435 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001436}
1437
Richard Henderson3eefdf22021-08-25 11:06:43 -07001438static bool fold_mb(OptContext *ctx, TCGOp *op)
1439{
1440 /* Eliminate duplicate and redundant fence instructions. */
1441 if (ctx->prev_mb) {
1442 /*
1443 * Merge two barriers of the same type into one,
1444 * or a weaker barrier into a stronger one,
1445 * or two weaker barriers into a stronger one.
1446 * mb X; mb Y => mb X|Y
1447 * mb; strl => mb; st
1448 * ldaq; mb => ld; mb
1449 * ldaq; strl => ld; mb; st
1450 * Other combinations are also merged into a strong
1451 * barrier. This is stricter than specified but for
1452 * the purposes of TCG is better than not optimizing.
1453 */
1454 ctx->prev_mb->args[0] |= op->args[0];
1455 tcg_op_remove(ctx->tcg, op);
1456 } else {
1457 ctx->prev_mb = op;
1458 }
1459 return true;
1460}
1461
Richard Henderson2cfac7f2021-08-25 13:05:43 -07001462static bool fold_mov(OptContext *ctx, TCGOp *op)
1463{
1464 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
1465}
1466
Richard Henderson0c310a32021-08-24 10:37:24 -07001467static bool fold_movcond(OptContext *ctx, TCGOp *op)
1468{
Richard Henderson0c310a32021-08-24 10:37:24 -07001469 TCGCond cond = op->args[5];
Richard Henderson7a2f7082021-08-26 07:06:39 -07001470 int i;
Richard Henderson0c310a32021-08-24 10:37:24 -07001471
Richard Henderson7a2f7082021-08-26 07:06:39 -07001472 if (swap_commutative(NO_DEST, &op->args[1], &op->args[2])) {
1473 op->args[5] = cond = tcg_swap_cond(cond);
1474 }
1475 /*
1476 * Canonicalize the "false" input reg to match the destination reg so
1477 * that the tcg backend can implement a "move if true" operation.
1478 */
1479 if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
1480 op->args[5] = cond = tcg_invert_cond(cond);
1481 }
1482
1483 i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
Richard Henderson0c310a32021-08-24 10:37:24 -07001484 if (i >= 0) {
1485 return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[4 - i]);
1486 }
1487
Richard Hendersonfae450b2021-08-25 22:42:19 -07001488 ctx->z_mask = arg_info(op->args[3])->z_mask
1489 | arg_info(op->args[4])->z_mask;
1490
Richard Henderson0c310a32021-08-24 10:37:24 -07001491 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
1492 uint64_t tv = arg_info(op->args[3])->val;
1493 uint64_t fv = arg_info(op->args[4])->val;
Richard Henderson67f84c92021-08-25 08:00:20 -07001494 TCGOpcode opc;
Richard Henderson0c310a32021-08-24 10:37:24 -07001495
Richard Henderson67f84c92021-08-25 08:00:20 -07001496 switch (ctx->type) {
1497 case TCG_TYPE_I32:
1498 opc = INDEX_op_setcond_i32;
1499 break;
1500 case TCG_TYPE_I64:
1501 opc = INDEX_op_setcond_i64;
1502 break;
1503 default:
1504 g_assert_not_reached();
1505 }
Richard Henderson0c310a32021-08-24 10:37:24 -07001506
1507 if (tv == 1 && fv == 0) {
1508 op->opc = opc;
1509 op->args[3] = cond;
1510 } else if (fv == 1 && tv == 0) {
1511 op->opc = opc;
1512 op->args[3] = tcg_invert_cond(cond);
1513 }
1514 }
1515 return false;
1516}
1517
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001518static bool fold_mul(OptContext *ctx, TCGOp *op)
1519{
Richard Hendersone8679952021-08-25 13:19:52 -07001520 if (fold_const2(ctx, op) ||
Richard Henderson5b5cf472021-10-25 11:19:14 -07001521 fold_xi_to_i(ctx, op, 0) ||
1522 fold_xi_to_x(ctx, op, 1)) {
Richard Hendersone8679952021-08-25 13:19:52 -07001523 return true;
1524 }
1525 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001526}
1527
1528static bool fold_mul_highpart(OptContext *ctx, TCGOp *op)
1529{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001530 if (fold_const2_commutative(ctx, op) ||
Richard Hendersone8679952021-08-25 13:19:52 -07001531 fold_xi_to_i(ctx, op, 0)) {
1532 return true;
1533 }
1534 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001535}
1536
Richard Henderson407112b2021-08-26 06:33:04 -07001537static bool fold_multiply2(OptContext *ctx, TCGOp *op)
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07001538{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001539 swap_commutative(op->args[0], &op->args[2], &op->args[3]);
1540
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07001541 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) {
Richard Henderson407112b2021-08-26 06:33:04 -07001542 uint64_t a = arg_info(op->args[2])->val;
1543 uint64_t b = arg_info(op->args[3])->val;
1544 uint64_t h, l;
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07001545 TCGArg rl, rh;
Richard Henderson407112b2021-08-26 06:33:04 -07001546 TCGOp *op2;
1547
1548 switch (op->opc) {
1549 case INDEX_op_mulu2_i32:
1550 l = (uint64_t)(uint32_t)a * (uint32_t)b;
1551 h = (int32_t)(l >> 32);
1552 l = (int32_t)l;
1553 break;
1554 case INDEX_op_muls2_i32:
1555 l = (int64_t)(int32_t)a * (int32_t)b;
1556 h = l >> 32;
1557 l = (int32_t)l;
1558 break;
1559 case INDEX_op_mulu2_i64:
1560 mulu64(&l, &h, a, b);
1561 break;
1562 case INDEX_op_muls2_i64:
1563 muls64(&l, &h, a, b);
1564 break;
1565 default:
1566 g_assert_not_reached();
1567 }
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07001568
1569 rl = op->args[0];
1570 rh = op->args[1];
Richard Henderson407112b2021-08-26 06:33:04 -07001571
1572 /* The proper opcode is supplied by tcg_opt_gen_mov. */
1573 op2 = tcg_op_insert_before(ctx->tcg, op, 0);
1574
1575 tcg_opt_gen_movi(ctx, op, rl, l);
1576 tcg_opt_gen_movi(ctx, op2, rh, h);
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07001577 return true;
1578 }
1579 return false;
1580}
1581
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001582static bool fold_nand(OptContext *ctx, TCGOp *op)
1583{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001584 if (fold_const2_commutative(ctx, op) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001585 fold_xi_to_not(ctx, op, -1)) {
1586 return true;
1587 }
1588 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001589}
1590
1591static bool fold_neg(OptContext *ctx, TCGOp *op)
1592{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001593 uint64_t z_mask;
1594
Richard Henderson9caca882021-08-24 13:30:32 -07001595 if (fold_const1(ctx, op)) {
1596 return true;
1597 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001598
1599 /* Set to 1 all bits to the left of the rightmost. */
1600 z_mask = arg_info(op->args[1])->z_mask;
1601 ctx->z_mask = -(z_mask & -z_mask);
1602
Richard Henderson9caca882021-08-24 13:30:32 -07001603 /*
1604 * Because of fold_sub_to_neg, we want to always return true,
1605 * via finish_folding.
1606 */
1607 finish_folding(ctx, op);
1608 return true;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001609}
1610
1611static bool fold_nor(OptContext *ctx, TCGOp *op)
1612{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001613 if (fold_const2_commutative(ctx, op) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001614 fold_xi_to_not(ctx, op, 0)) {
1615 return true;
1616 }
1617 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001618}
1619
1620static bool fold_not(OptContext *ctx, TCGOp *op)
1621{
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001622 if (fold_const1(ctx, op)) {
1623 return true;
1624 }
1625
1626 /* Because of fold_to_not, we want to always return true, via finish. */
1627 finish_folding(ctx, op);
1628 return true;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001629}
1630
1631static bool fold_or(OptContext *ctx, TCGOp *op)
1632{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001633 if (fold_const2_commutative(ctx, op) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001634 fold_xi_to_x(ctx, op, 0) ||
Richard Hendersonca7bb042021-08-25 13:14:21 -07001635 fold_xx_to_x(ctx, op)) {
1636 return true;
1637 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001638
1639 ctx->z_mask = arg_info(op->args[1])->z_mask
1640 | arg_info(op->args[2])->z_mask;
1641 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001642}
1643
1644static bool fold_orc(OptContext *ctx, TCGOp *op)
1645{
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001646 if (fold_const2(ctx, op) ||
Richard Henderson4e858d92021-08-26 07:31:13 -07001647 fold_xx_to_i(ctx, op, -1) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001648 fold_xi_to_x(ctx, op, -1) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001649 fold_ix_to_not(ctx, op, 0)) {
1650 return true;
1651 }
1652 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001653}
1654
Richard Henderson3eefdf22021-08-25 11:06:43 -07001655static bool fold_qemu_ld(OptContext *ctx, TCGOp *op)
1656{
Richard Hendersonfae450b2021-08-25 22:42:19 -07001657 const TCGOpDef *def = &tcg_op_defs[op->opc];
1658 MemOpIdx oi = op->args[def->nb_oargs + def->nb_iargs];
1659 MemOp mop = get_memop(oi);
1660 int width = 8 * memop_size(mop);
1661
Richard Henderson57fe5c62021-08-26 12:04:46 -07001662 if (width < 64) {
1663 ctx->s_mask = MAKE_64BIT_MASK(width, 64 - width);
1664 if (!(mop & MO_SIGN)) {
1665 ctx->z_mask = MAKE_64BIT_MASK(0, width);
1666 ctx->s_mask <<= 1;
1667 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001668 }
1669
Richard Henderson3eefdf22021-08-25 11:06:43 -07001670 /* Opcodes that touch guest memory stop the mb optimization. */
1671 ctx->prev_mb = NULL;
1672 return false;
1673}
1674
1675static bool fold_qemu_st(OptContext *ctx, TCGOp *op)
1676{
1677 /* Opcodes that touch guest memory stop the mb optimization. */
1678 ctx->prev_mb = NULL;
1679 return false;
1680}
1681
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001682static bool fold_remainder(OptContext *ctx, TCGOp *op)
1683{
Richard Henderson267c17e2021-10-25 11:30:33 -07001684 if (fold_const2(ctx, op) ||
1685 fold_xx_to_i(ctx, op, 0)) {
1686 return true;
1687 }
1688 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001689}
1690
Richard Hendersonc63ff552021-08-24 09:35:30 -07001691static bool fold_setcond(OptContext *ctx, TCGOp *op)
1692{
1693 TCGCond cond = op->args[3];
Richard Henderson7a2f7082021-08-26 07:06:39 -07001694 int i;
Richard Hendersonc63ff552021-08-24 09:35:30 -07001695
Richard Henderson7a2f7082021-08-26 07:06:39 -07001696 if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
1697 op->args[3] = cond = tcg_swap_cond(cond);
1698 }
1699
1700 i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
Richard Hendersonc63ff552021-08-24 09:35:30 -07001701 if (i >= 0) {
1702 return tcg_opt_gen_movi(ctx, op, op->args[0], i);
1703 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001704
1705 ctx->z_mask = 1;
Richard Hendersonc63ff552021-08-24 09:35:30 -07001706 return false;
1707}
1708
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001709static bool fold_setcond2(OptContext *ctx, TCGOp *op)
1710{
1711 TCGCond cond = op->args[5];
Richard Henderson7a2f7082021-08-26 07:06:39 -07001712 int i, inv = 0;
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001713
Richard Henderson7a2f7082021-08-26 07:06:39 -07001714 if (swap_commutative2(&op->args[1], &op->args[3])) {
1715 op->args[5] = cond = tcg_swap_cond(cond);
1716 }
1717
1718 i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond);
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001719 if (i >= 0) {
1720 goto do_setcond_const;
1721 }
1722
1723 switch (cond) {
1724 case TCG_COND_LT:
1725 case TCG_COND_GE:
1726 /*
1727 * Simplify LT/GE comparisons vs zero to a single compare
1728 * vs the high word of the input.
1729 */
1730 if (arg_is_const(op->args[3]) && arg_info(op->args[3])->val == 0 &&
1731 arg_is_const(op->args[4]) && arg_info(op->args[4])->val == 0) {
1732 goto do_setcond_high;
1733 }
1734 break;
1735
1736 case TCG_COND_NE:
1737 inv = 1;
1738 QEMU_FALLTHROUGH;
1739 case TCG_COND_EQ:
1740 /*
1741 * Simplify EQ/NE comparisons where one of the pairs
1742 * can be simplified.
1743 */
Richard Henderson67f84c92021-08-25 08:00:20 -07001744 i = do_constant_folding_cond(TCG_TYPE_I32, op->args[1],
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001745 op->args[3], cond);
1746 switch (i ^ inv) {
1747 case 0:
1748 goto do_setcond_const;
1749 case 1:
1750 goto do_setcond_high;
1751 }
1752
Richard Henderson67f84c92021-08-25 08:00:20 -07001753 i = do_constant_folding_cond(TCG_TYPE_I32, op->args[2],
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001754 op->args[4], cond);
1755 switch (i ^ inv) {
1756 case 0:
1757 goto do_setcond_const;
1758 case 1:
1759 op->args[2] = op->args[3];
1760 op->args[3] = cond;
1761 op->opc = INDEX_op_setcond_i32;
1762 break;
1763 }
1764 break;
1765
1766 default:
1767 break;
1768
1769 do_setcond_high:
1770 op->args[1] = op->args[2];
1771 op->args[2] = op->args[4];
1772 op->args[3] = cond;
1773 op->opc = INDEX_op_setcond_i32;
1774 break;
1775 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001776
1777 ctx->z_mask = 1;
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07001778 return false;
1779
1780 do_setcond_const:
1781 return tcg_opt_gen_movi(ctx, op, op->args[0], i);
1782}
1783
Richard Hendersonb6617c82021-08-24 10:44:53 -07001784static bool fold_sextract(OptContext *ctx, TCGOp *op)
1785{
Richard Henderson57fe5c62021-08-26 12:04:46 -07001786 uint64_t z_mask, s_mask, s_mask_old;
1787 int pos = op->args[2];
1788 int len = op->args[3];
Richard Hendersonfae450b2021-08-25 22:42:19 -07001789
Richard Hendersonb6617c82021-08-24 10:44:53 -07001790 if (arg_is_const(op->args[1])) {
1791 uint64_t t;
1792
1793 t = arg_info(op->args[1])->val;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001794 t = sextract64(t, pos, len);
Richard Hendersonb6617c82021-08-24 10:44:53 -07001795 return tcg_opt_gen_movi(ctx, op, op->args[0], t);
1796 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001797
Richard Henderson57fe5c62021-08-26 12:04:46 -07001798 z_mask = arg_info(op->args[1])->z_mask;
1799 z_mask = sextract64(z_mask, pos, len);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001800 ctx->z_mask = z_mask;
1801
Richard Henderson57fe5c62021-08-26 12:04:46 -07001802 s_mask_old = arg_info(op->args[1])->s_mask;
1803 s_mask = sextract64(s_mask_old, pos, len);
1804 s_mask |= MAKE_64BIT_MASK(len, 64 - len);
1805 ctx->s_mask = s_mask;
1806
1807 if (pos == 0) {
1808 ctx->a_mask = s_mask & ~s_mask_old;
1809 }
1810
Richard Hendersonfae450b2021-08-25 22:42:19 -07001811 return fold_masks(ctx, op);
Richard Hendersonb6617c82021-08-24 10:44:53 -07001812}
1813
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001814static bool fold_shift(OptContext *ctx, TCGOp *op)
1815{
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001816 if (fold_const2(ctx, op) ||
Richard Hendersonda48e272021-08-25 20:42:04 -07001817 fold_ix_to_i(ctx, op, 0) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001818 fold_xi_to_x(ctx, op, 0)) {
1819 return true;
1820 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001821
1822 if (arg_is_const(op->args[2])) {
1823 ctx->z_mask = do_constant_folding(op->opc, ctx->type,
1824 arg_info(op->args[1])->z_mask,
1825 arg_info(op->args[2])->val);
1826 return fold_masks(ctx, op);
1827 }
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001828 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001829}
1830
Richard Henderson9caca882021-08-24 13:30:32 -07001831static bool fold_sub_to_neg(OptContext *ctx, TCGOp *op)
1832{
1833 TCGOpcode neg_op;
1834 bool have_neg;
1835
1836 if (!arg_is_const(op->args[1]) || arg_info(op->args[1])->val != 0) {
1837 return false;
1838 }
1839
1840 switch (ctx->type) {
1841 case TCG_TYPE_I32:
1842 neg_op = INDEX_op_neg_i32;
1843 have_neg = TCG_TARGET_HAS_neg_i32;
1844 break;
1845 case TCG_TYPE_I64:
1846 neg_op = INDEX_op_neg_i64;
1847 have_neg = TCG_TARGET_HAS_neg_i64;
1848 break;
1849 case TCG_TYPE_V64:
1850 case TCG_TYPE_V128:
1851 case TCG_TYPE_V256:
1852 neg_op = INDEX_op_neg_vec;
1853 have_neg = (TCG_TARGET_HAS_neg_vec &&
1854 tcg_can_emit_vec_op(neg_op, ctx->type, TCGOP_VECE(op)) > 0);
1855 break;
1856 default:
1857 g_assert_not_reached();
1858 }
1859 if (have_neg) {
1860 op->opc = neg_op;
1861 op->args[1] = op->args[2];
1862 return fold_neg(ctx, op);
1863 }
1864 return false;
1865}
1866
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001867static bool fold_sub(OptContext *ctx, TCGOp *op)
1868{
Richard Hendersoncbe42fb2021-08-25 13:02:00 -07001869 if (fold_const2(ctx, op) ||
Richard Henderson9caca882021-08-24 13:30:32 -07001870 fold_xx_to_i(ctx, op, 0) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001871 fold_xi_to_x(ctx, op, 0) ||
Richard Henderson9caca882021-08-24 13:30:32 -07001872 fold_sub_to_neg(ctx, op)) {
Richard Hendersoncbe42fb2021-08-25 13:02:00 -07001873 return true;
1874 }
1875 return false;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001876}
1877
Richard Henderson9531c072021-08-26 06:51:39 -07001878static bool fold_sub2(OptContext *ctx, TCGOp *op)
Richard Hendersone3f7dc22021-08-24 10:30:38 -07001879{
Richard Henderson9531c072021-08-26 06:51:39 -07001880 return fold_addsub2(ctx, op, false);
Richard Hendersone3f7dc22021-08-24 10:30:38 -07001881}
1882
Richard Hendersonfae450b2021-08-25 22:42:19 -07001883static bool fold_tcg_ld(OptContext *ctx, TCGOp *op)
1884{
1885 /* We can't do any folding with a load, but we can record bits. */
1886 switch (op->opc) {
Richard Henderson57fe5c62021-08-26 12:04:46 -07001887 CASE_OP_32_64(ld8s):
1888 ctx->s_mask = MAKE_64BIT_MASK(8, 56);
1889 break;
Richard Hendersonfae450b2021-08-25 22:42:19 -07001890 CASE_OP_32_64(ld8u):
1891 ctx->z_mask = MAKE_64BIT_MASK(0, 8);
Richard Henderson57fe5c62021-08-26 12:04:46 -07001892 ctx->s_mask = MAKE_64BIT_MASK(9, 55);
1893 break;
1894 CASE_OP_32_64(ld16s):
1895 ctx->s_mask = MAKE_64BIT_MASK(16, 48);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001896 break;
1897 CASE_OP_32_64(ld16u):
1898 ctx->z_mask = MAKE_64BIT_MASK(0, 16);
Richard Henderson57fe5c62021-08-26 12:04:46 -07001899 ctx->s_mask = MAKE_64BIT_MASK(17, 47);
1900 break;
1901 case INDEX_op_ld32s_i64:
1902 ctx->s_mask = MAKE_64BIT_MASK(32, 32);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001903 break;
1904 case INDEX_op_ld32u_i64:
1905 ctx->z_mask = MAKE_64BIT_MASK(0, 32);
Richard Henderson57fe5c62021-08-26 12:04:46 -07001906 ctx->s_mask = MAKE_64BIT_MASK(33, 31);
Richard Hendersonfae450b2021-08-25 22:42:19 -07001907 break;
1908 default:
1909 g_assert_not_reached();
1910 }
1911 return false;
1912}
1913
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001914static bool fold_xor(OptContext *ctx, TCGOp *op)
1915{
Richard Henderson7a2f7082021-08-26 07:06:39 -07001916 if (fold_const2_commutative(ctx, op) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001917 fold_xx_to_i(ctx, op, 0) ||
Richard Hendersona63ce0e2021-08-25 20:28:53 -07001918 fold_xi_to_x(ctx, op, 0) ||
Richard Henderson0e0a32b2021-08-24 13:18:01 -07001919 fold_xi_to_not(ctx, op, -1)) {
Richard Hendersoncbe42fb2021-08-25 13:02:00 -07001920 return true;
1921 }
Richard Hendersonfae450b2021-08-25 22:42:19 -07001922
1923 ctx->z_mask = arg_info(op->args[1])->z_mask
1924 | arg_info(op->args[2])->z_mask;
1925 return fold_masks(ctx, op);
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001926}
1927
Kirill Batuzov22613af2011-07-07 16:37:13 +04001928/* Propagate constants and copies, fold constant expressions. */
Aurelien Jarno36e60ef2015-06-04 21:53:27 +02001929void tcg_optimize(TCGContext *s)
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001930{
Richard Henderson5cf32be2021-08-24 08:17:08 -07001931 int nb_temps, i;
Richard Hendersond0ed5152021-08-24 07:38:39 -07001932 TCGOp *op, *op_next;
Richard Hendersondc849882021-08-24 07:13:45 -07001933 OptContext ctx = { .tcg = s };
Richard Henderson5d8f5362012-09-21 10:13:38 -07001934
Kirill Batuzov22613af2011-07-07 16:37:13 +04001935 /* Array VALS has an element for each temp.
1936 If this temp holds a constant then its value is kept in VALS' element.
Aurelien Jarnoe590d4e2012-09-11 12:31:21 +02001937 If this temp is a copy of other ones then the other copies are
1938 available through the doubly linked circular list. */
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001939
1940 nb_temps = s->nb_temps;
Richard Henderson8f17a972020-03-30 19:52:02 -07001941 for (i = 0; i < nb_temps; ++i) {
1942 s->temps[i].state_ptr = NULL;
1943 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04001944
Richard Henderson15fa08f2017-11-02 15:19:14 +01001945 QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001946 TCGOpcode opc = op->opc;
Richard Henderson5cf32be2021-08-24 08:17:08 -07001947 const TCGOpDef *def;
Richard Henderson404a1482021-08-24 11:08:21 -07001948 bool done = false;
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001949
Richard Henderson5cf32be2021-08-24 08:17:08 -07001950 /* Calls are special. */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001951 if (opc == INDEX_op_call) {
Richard Henderson5cf32be2021-08-24 08:17:08 -07001952 fold_call(&ctx, op);
1953 continue;
Richard Hendersoncf066672014-03-22 20:06:52 -07001954 }
Richard Henderson5cf32be2021-08-24 08:17:08 -07001955
1956 def = &tcg_op_defs[opc];
Richard Hendersonec5d4cb2021-08-24 08:20:27 -07001957 init_arguments(&ctx, op, def->nb_oargs + def->nb_iargs);
1958 copy_propagate(&ctx, op, def->nb_oargs, def->nb_iargs);
Kirill Batuzov22613af2011-07-07 16:37:13 +04001959
Richard Henderson67f84c92021-08-25 08:00:20 -07001960 /* Pre-compute the type of the operation. */
1961 if (def->flags & TCG_OPF_VECTOR) {
1962 ctx.type = TCG_TYPE_V64 + TCGOP_VECL(op);
1963 } else if (def->flags & TCG_OPF_64BIT) {
1964 ctx.type = TCG_TYPE_I64;
1965 } else {
1966 ctx.type = TCG_TYPE_I32;
1967 }
1968
Richard Henderson57fe5c62021-08-26 12:04:46 -07001969 /* Assume all bits affected, no bits known zero, no sign reps. */
Richard Hendersonfae450b2021-08-25 22:42:19 -07001970 ctx.a_mask = -1;
1971 ctx.z_mask = -1;
Richard Henderson57fe5c62021-08-26 12:04:46 -07001972 ctx.s_mask = 0;
Paolo Bonzini633f6502013-01-11 15:42:53 -08001973
Richard Henderson2cfac7f2021-08-25 13:05:43 -07001974 /*
1975 * Process each opcode.
1976 * Sorted alphabetically by opcode as much as possible.
1977 */
Richard Hendersonc45cb8b2014-09-19 13:49:15 -07001978 switch (opc) {
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001979 CASE_OP_32_64_VEC(add):
1980 done = fold_add(&ctx, op);
1981 break;
Richard Henderson9531c072021-08-26 06:51:39 -07001982 CASE_OP_32_64(add2):
1983 done = fold_add2(&ctx, op);
Richard Hendersone3f7dc22021-08-24 10:30:38 -07001984 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07001985 CASE_OP_32_64_VEC(and):
1986 done = fold_and(&ctx, op);
1987 break;
1988 CASE_OP_32_64_VEC(andc):
1989 done = fold_andc(&ctx, op);
1990 break;
Richard Henderson079b0802021-08-24 09:30:59 -07001991 CASE_OP_32_64(brcond):
1992 done = fold_brcond(&ctx, op);
1993 break;
Richard Henderson764d2ab2021-08-24 09:22:11 -07001994 case INDEX_op_brcond2_i32:
1995 done = fold_brcond2(&ctx, op);
1996 break;
Richard Henderson09bacdc2021-08-24 11:58:12 -07001997 CASE_OP_32_64(bswap16):
1998 CASE_OP_32_64(bswap32):
1999 case INDEX_op_bswap64_i64:
2000 done = fold_bswap(&ctx, op);
2001 break;
Richard Henderson30dd0bf2021-08-24 10:51:34 -07002002 CASE_OP_32_64(clz):
2003 CASE_OP_32_64(ctz):
2004 done = fold_count_zeros(&ctx, op);
2005 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002006 CASE_OP_32_64(ctpop):
2007 done = fold_ctpop(&ctx, op);
2008 break;
Richard Henderson1b1907b2021-08-24 10:47:04 -07002009 CASE_OP_32_64(deposit):
2010 done = fold_deposit(&ctx, op);
2011 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002012 CASE_OP_32_64(div):
2013 CASE_OP_32_64(divu):
2014 done = fold_divide(&ctx, op);
2015 break;
Richard Henderson8cdb3fc2021-08-24 12:06:33 -07002016 case INDEX_op_dup_vec:
2017 done = fold_dup(&ctx, op);
2018 break;
2019 case INDEX_op_dup2_vec:
2020 done = fold_dup2(&ctx, op);
2021 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002022 CASE_OP_32_64(eqv):
2023 done = fold_eqv(&ctx, op);
2024 break;
Richard Hendersonb6617c82021-08-24 10:44:53 -07002025 CASE_OP_32_64(extract):
2026 done = fold_extract(&ctx, op);
2027 break;
Richard Hendersondcd08992021-08-24 10:41:39 -07002028 CASE_OP_32_64(extract2):
2029 done = fold_extract2(&ctx, op);
2030 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002031 CASE_OP_32_64(ext8s):
2032 CASE_OP_32_64(ext16s):
2033 case INDEX_op_ext32s_i64:
2034 case INDEX_op_ext_i32_i64:
2035 done = fold_exts(&ctx, op);
2036 break;
2037 CASE_OP_32_64(ext8u):
2038 CASE_OP_32_64(ext16u):
2039 case INDEX_op_ext32u_i64:
2040 case INDEX_op_extu_i32_i64:
2041 case INDEX_op_extrl_i64_i32:
2042 case INDEX_op_extrh_i64_i32:
2043 done = fold_extu(&ctx, op);
2044 break;
Richard Henderson57fe5c62021-08-26 12:04:46 -07002045 CASE_OP_32_64(ld8s):
Richard Hendersonfae450b2021-08-25 22:42:19 -07002046 CASE_OP_32_64(ld8u):
Richard Henderson57fe5c62021-08-26 12:04:46 -07002047 CASE_OP_32_64(ld16s):
Richard Hendersonfae450b2021-08-25 22:42:19 -07002048 CASE_OP_32_64(ld16u):
Richard Henderson57fe5c62021-08-26 12:04:46 -07002049 case INDEX_op_ld32s_i64:
Richard Hendersonfae450b2021-08-25 22:42:19 -07002050 case INDEX_op_ld32u_i64:
2051 done = fold_tcg_ld(&ctx, op);
2052 break;
Richard Henderson3eefdf22021-08-25 11:06:43 -07002053 case INDEX_op_mb:
2054 done = fold_mb(&ctx, op);
2055 break;
Richard Henderson2cfac7f2021-08-25 13:05:43 -07002056 CASE_OP_32_64_VEC(mov):
2057 done = fold_mov(&ctx, op);
2058 break;
Richard Henderson0c310a32021-08-24 10:37:24 -07002059 CASE_OP_32_64(movcond):
2060 done = fold_movcond(&ctx, op);
2061 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002062 CASE_OP_32_64(mul):
2063 done = fold_mul(&ctx, op);
2064 break;
2065 CASE_OP_32_64(mulsh):
2066 CASE_OP_32_64(muluh):
2067 done = fold_mul_highpart(&ctx, op);
2068 break;
Richard Henderson407112b2021-08-26 06:33:04 -07002069 CASE_OP_32_64(muls2):
2070 CASE_OP_32_64(mulu2):
2071 done = fold_multiply2(&ctx, op);
Richard Henderson6b8ac0d2021-08-24 10:24:12 -07002072 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002073 CASE_OP_32_64(nand):
2074 done = fold_nand(&ctx, op);
2075 break;
2076 CASE_OP_32_64(neg):
2077 done = fold_neg(&ctx, op);
2078 break;
2079 CASE_OP_32_64(nor):
2080 done = fold_nor(&ctx, op);
2081 break;
2082 CASE_OP_32_64_VEC(not):
2083 done = fold_not(&ctx, op);
2084 break;
2085 CASE_OP_32_64_VEC(or):
2086 done = fold_or(&ctx, op);
2087 break;
2088 CASE_OP_32_64_VEC(orc):
2089 done = fold_orc(&ctx, op);
2090 break;
Richard Henderson3eefdf22021-08-25 11:06:43 -07002091 case INDEX_op_qemu_ld_i32:
2092 case INDEX_op_qemu_ld_i64:
2093 done = fold_qemu_ld(&ctx, op);
2094 break;
2095 case INDEX_op_qemu_st_i32:
2096 case INDEX_op_qemu_st8_i32:
2097 case INDEX_op_qemu_st_i64:
2098 done = fold_qemu_st(&ctx, op);
2099 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002100 CASE_OP_32_64(rem):
2101 CASE_OP_32_64(remu):
2102 done = fold_remainder(&ctx, op);
2103 break;
2104 CASE_OP_32_64(rotl):
2105 CASE_OP_32_64(rotr):
2106 CASE_OP_32_64(sar):
2107 CASE_OP_32_64(shl):
2108 CASE_OP_32_64(shr):
2109 done = fold_shift(&ctx, op);
2110 break;
Richard Hendersonc63ff552021-08-24 09:35:30 -07002111 CASE_OP_32_64(setcond):
2112 done = fold_setcond(&ctx, op);
2113 break;
Richard Hendersonbc47b1a2021-08-24 09:09:35 -07002114 case INDEX_op_setcond2_i32:
2115 done = fold_setcond2(&ctx, op);
2116 break;
Richard Hendersonb6617c82021-08-24 10:44:53 -07002117 CASE_OP_32_64(sextract):
2118 done = fold_sextract(&ctx, op);
2119 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002120 CASE_OP_32_64_VEC(sub):
2121 done = fold_sub(&ctx, op);
2122 break;
Richard Henderson9531c072021-08-26 06:51:39 -07002123 CASE_OP_32_64(sub2):
2124 done = fold_sub2(&ctx, op);
Richard Hendersone3f7dc22021-08-24 10:30:38 -07002125 break;
Richard Henderson2f9f08b2021-08-25 12:03:48 -07002126 CASE_OP_32_64_VEC(xor):
2127 done = fold_xor(&ctx, op);
Richard Hendersonb10f3832021-08-23 22:30:17 -07002128 break;
Richard Henderson2cfac7f2021-08-25 13:05:43 -07002129 default:
2130 break;
Richard Hendersonb10f3832021-08-23 22:30:17 -07002131 }
2132
Richard Henderson404a1482021-08-24 11:08:21 -07002133 if (!done) {
2134 finish_folding(&ctx, op);
2135 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04002136 }
Kirill Batuzov8f2e8c02011-07-07 16:37:12 +04002137}