]>
Commit | Line | Data |
---|---|---|
ef6c17ed | 1 | /* RTL simplification functions for GNU compiler. |
9daf6266 | 2 | Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
9a1ba33e | 3 | 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
22bcc33d | 4 | 2011, 2012 Free Software Foundation, Inc. |
af21a202 | 5 | |
f12b58b3 | 6 | This file is part of GCC. |
af21a202 | 7 | |
f12b58b3 | 8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
8c4c00c1 | 10 | Software Foundation; either version 3, or (at your option) any later |
f12b58b3 | 11 | version. |
af21a202 | 12 | |
f12b58b3 | 13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
af21a202 | 17 | |
18 | You should have received a copy of the GNU General Public License | |
8c4c00c1 | 19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
af21a202 | 21 | |
22 | ||
23 | #include "config.h" | |
af21a202 | 24 | #include "system.h" |
805e22b2 | 25 | #include "coretypes.h" |
26 | #include "tm.h" | |
af21a202 | 27 | #include "rtl.h" |
aa870c1b | 28 | #include "tree.h" |
af21a202 | 29 | #include "tm_p.h" |
30 | #include "regs.h" | |
31 | #include "hard-reg-set.h" | |
32 | #include "flags.h" | |
af21a202 | 33 | #include "insn-config.h" |
34 | #include "recog.h" | |
35 | #include "function.h" | |
36 | #include "expr.h" | |
0b205f4c | 37 | #include "diagnostic-core.h" |
1617c276 | 38 | #include "ggc.h" |
bfe57ab7 | 39 | #include "target.h" |
af21a202 | 40 | |
41 | /* Simplification and canonicalization of RTL. */ | |
42 | ||
a8fb076f | 43 | /* Much code operates on (low, high) pairs; the low value is an |
44 | unsigned wide int, the high value a signed wide int. We | |
45 | occasionally need to sign extend from low to high as if low were a | |
46 | signed wide int. */ | |
2cae60d1 | 47 | #define HWI_SIGN_EXTEND(low) \ |
a8fb076f | 48 | ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0)) |
af21a202 | 49 | |
dd9b9fc5 | 50 | static rtx neg_const_int (enum machine_mode, const_rtx); |
51 | static bool plus_minus_operand_p (const_rtx); | |
1f3b83af | 52 | static bool simplify_plus_minus_op_data_cmp (rtx, rtx); |
e9480a59 | 53 | static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx, rtx); |
791172c5 | 54 | static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode, |
55 | unsigned int); | |
049cadd6 | 56 | static rtx simplify_associative_operation (enum rtx_code, enum machine_mode, |
57 | rtx, rtx); | |
ac503e50 | 58 | static rtx simplify_relational_operation_1 (enum rtx_code, enum machine_mode, |
59 | enum machine_mode, rtx, rtx); | |
3b723a04 | 60 | static rtx simplify_unary_operation_1 (enum rtx_code, enum machine_mode, rtx); |
61 | static rtx simplify_binary_operation_1 (enum rtx_code, enum machine_mode, | |
62 | rtx, rtx, rtx, rtx); | |
7d6080d6 | 63 | \f |
64 | /* Negate a CONST_INT rtx, truncating (because a conversion from a | |
00e0eb3d | 65 | maximally negative number can overflow). */ |
7d6080d6 | 66 | static rtx |
dd9b9fc5 | 67 | neg_const_int (enum machine_mode mode, const_rtx i) |
7d6080d6 | 68 | { |
2d232d05 | 69 | return gen_int_mode (- INTVAL (i), mode); |
7d6080d6 | 70 | } |
71 | ||
502bc734 | 72 | /* Test whether expression, X, is an immediate constant that represents |
73 | the most significant bit of machine mode MODE. */ | |
74 | ||
0b4b6aaa | 75 | bool |
dd9b9fc5 | 76 | mode_signbit_p (enum machine_mode mode, const_rtx x) |
502bc734 | 77 | { |
78 | unsigned HOST_WIDE_INT val; | |
79 | unsigned int width; | |
80 | ||
81 | if (GET_MODE_CLASS (mode) != MODE_INT) | |
82 | return false; | |
83 | ||
f92430e0 | 84 | width = GET_MODE_PRECISION (mode); |
502bc734 | 85 | if (width == 0) |
86 | return false; | |
48e1416a | 87 | |
502bc734 | 88 | if (width <= HOST_BITS_PER_WIDE_INT |
971ba038 | 89 | && CONST_INT_P (x)) |
502bc734 | 90 | val = INTVAL (x); |
91 | else if (width <= 2 * HOST_BITS_PER_WIDE_INT | |
92 | && GET_CODE (x) == CONST_DOUBLE | |
93 | && CONST_DOUBLE_LOW (x) == 0) | |
94 | { | |
95 | val = CONST_DOUBLE_HIGH (x); | |
96 | width -= HOST_BITS_PER_WIDE_INT; | |
97 | } | |
98 | else | |
db20fb47 | 99 | /* FIXME: We don't yet have a representation for wider modes. */ |
502bc734 | 100 | return false; |
101 | ||
102 | if (width < HOST_BITS_PER_WIDE_INT) | |
103 | val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1; | |
104 | return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1)); | |
105 | } | |
f92430e0 | 106 | |
107 | /* Test whether VAL is equal to the most significant bit of mode MODE | |
108 | (after masking with the mode mask of MODE). Returns false if the | |
109 | precision of MODE is too large to handle. */ | |
110 | ||
111 | bool | |
112 | val_signbit_p (enum machine_mode mode, unsigned HOST_WIDE_INT val) | |
113 | { | |
114 | unsigned int width; | |
115 | ||
116 | if (GET_MODE_CLASS (mode) != MODE_INT) | |
117 | return false; | |
118 | ||
119 | width = GET_MODE_PRECISION (mode); | |
120 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) | |
121 | return false; | |
122 | ||
123 | val &= GET_MODE_MASK (mode); | |
124 | return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1)); | |
125 | } | |
126 | ||
127 | /* Test whether the most significant bit of mode MODE is set in VAL. | |
128 | Returns false if the precision of MODE is too large to handle. */ | |
129 | bool | |
130 | val_signbit_known_set_p (enum machine_mode mode, unsigned HOST_WIDE_INT val) | |
131 | { | |
132 | unsigned int width; | |
133 | ||
134 | if (GET_MODE_CLASS (mode) != MODE_INT) | |
135 | return false; | |
136 | ||
137 | width = GET_MODE_PRECISION (mode); | |
138 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) | |
139 | return false; | |
140 | ||
141 | val &= (unsigned HOST_WIDE_INT) 1 << (width - 1); | |
142 | return val != 0; | |
143 | } | |
144 | ||
145 | /* Test whether the most significant bit of mode MODE is clear in VAL. | |
146 | Returns false if the precision of MODE is too large to handle. */ | |
147 | bool | |
148 | val_signbit_known_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT val) | |
149 | { | |
150 | unsigned int width; | |
151 | ||
152 | if (GET_MODE_CLASS (mode) != MODE_INT) | |
153 | return false; | |
154 | ||
155 | width = GET_MODE_PRECISION (mode); | |
156 | if (width == 0 || width > HOST_BITS_PER_WIDE_INT) | |
157 | return false; | |
158 | ||
159 | val &= (unsigned HOST_WIDE_INT) 1 << (width - 1); | |
160 | return val == 0; | |
161 | } | |
ef6c17ed | 162 | \f |
40734805 | 163 | /* Make a binary operation by properly ordering the operands and |
af21a202 | 164 | seeing if the expression folds. */ |
165 | ||
166 | rtx | |
60b8c5b3 | 167 | simplify_gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0, |
168 | rtx op1) | |
af21a202 | 169 | { |
170 | rtx tem; | |
171 | ||
af21a202 | 172 | /* If this simplifies, do it. */ |
173 | tem = simplify_binary_operation (code, mode, op0, op1); | |
af21a202 | 174 | if (tem) |
175 | return tem; | |
176 | ||
5f768987 | 177 | /* Put complex operands first and constants second if commutative. */ |
178 | if (GET_RTX_CLASS (code) == RTX_COMM_ARITH | |
179 | && swap_commutative_operands_p (op0, op1)) | |
180 | tem = op0, op0 = op1, op1 = tem; | |
181 | ||
907bb1cf | 182 | return gen_rtx_fmt_ee (code, mode, op0, op1); |
af21a202 | 183 | } |
184 | \f | |
6f2c2456 | 185 | /* If X is a MEM referencing the constant pool, return the real value. |
02cd84cd | 186 | Otherwise return X. */ |
c0876b6c | 187 | rtx |
60b8c5b3 | 188 | avoid_constant_pool_reference (rtx x) |
02cd84cd | 189 | { |
bfe57ab7 | 190 | rtx c, tmp, addr; |
6f2c2456 | 191 | enum machine_mode cmode; |
63537b25 | 192 | HOST_WIDE_INT offset = 0; |
6f2c2456 | 193 | |
bfe57ab7 | 194 | switch (GET_CODE (x)) |
195 | { | |
196 | case MEM: | |
197 | break; | |
198 | ||
199 | case FLOAT_EXTEND: | |
200 | /* Handle float extensions of constant pool references. */ | |
201 | tmp = XEXP (x, 0); | |
202 | c = avoid_constant_pool_reference (tmp); | |
203 | if (c != tmp && GET_CODE (c) == CONST_DOUBLE) | |
204 | { | |
205 | REAL_VALUE_TYPE d; | |
206 | ||
207 | REAL_VALUE_FROM_CONST_DOUBLE (d, c); | |
208 | return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x)); | |
209 | } | |
210 | return x; | |
211 | ||
212 | default: | |
213 | return x; | |
214 | } | |
215 | ||
8187c3ba | 216 | if (GET_MODE (x) == BLKmode) |
217 | return x; | |
218 | ||
6f2c2456 | 219 | addr = XEXP (x, 0); |
220 | ||
7981458e | 221 | /* Call target hook to avoid the effects of -fpic etc.... */ |
883b2e73 | 222 | addr = targetm.delegitimize_address (addr); |
bfe57ab7 | 223 | |
63537b25 | 224 | /* Split the address into a base and integer offset. */ |
225 | if (GET_CODE (addr) == CONST | |
226 | && GET_CODE (XEXP (addr, 0)) == PLUS | |
971ba038 | 227 | && CONST_INT_P (XEXP (XEXP (addr, 0), 1))) |
63537b25 | 228 | { |
229 | offset = INTVAL (XEXP (XEXP (addr, 0), 1)); | |
230 | addr = XEXP (XEXP (addr, 0), 0); | |
231 | } | |
232 | ||
7603dbce | 233 | if (GET_CODE (addr) == LO_SUM) |
234 | addr = XEXP (addr, 1); | |
235 | ||
63537b25 | 236 | /* If this is a constant pool reference, we can turn it into its |
237 | constant and hope that simplifications happen. */ | |
238 | if (GET_CODE (addr) == SYMBOL_REF | |
239 | && CONSTANT_POOL_ADDRESS_P (addr)) | |
6f2c2456 | 240 | { |
63537b25 | 241 | c = get_pool_constant (addr); |
242 | cmode = get_pool_mode (addr); | |
243 | ||
244 | /* If we're accessing the constant in a different mode than it was | |
245 | originally stored, attempt to fix that up via subreg simplifications. | |
246 | If that fails we have no choice but to return the original memory. */ | |
247 | if (offset != 0 || cmode != GET_MODE (x)) | |
248 | { | |
249 | rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset); | |
250 | if (tem && CONSTANT_P (tem)) | |
251 | return tem; | |
252 | } | |
253 | else | |
254 | return c; | |
6f2c2456 | 255 | } |
256 | ||
63537b25 | 257 | return x; |
02cd84cd | 258 | } |
259 | \f | |
9845d120 | 260 | /* Simplify a MEM based on its attributes. This is the default |
261 | delegitimize_address target hook, and it's recommended that every | |
262 | overrider call it. */ | |
263 | ||
264 | rtx | |
265 | delegitimize_mem_from_attrs (rtx x) | |
266 | { | |
8e63f6ce | 267 | /* MEMs without MEM_OFFSETs may have been offset, so we can't just |
268 | use their base addresses as equivalent. */ | |
9845d120 | 269 | if (MEM_P (x) |
270 | && MEM_EXPR (x) | |
da443c27 | 271 | && MEM_OFFSET_KNOWN_P (x)) |
9845d120 | 272 | { |
273 | tree decl = MEM_EXPR (x); | |
274 | enum machine_mode mode = GET_MODE (x); | |
275 | HOST_WIDE_INT offset = 0; | |
276 | ||
277 | switch (TREE_CODE (decl)) | |
278 | { | |
279 | default: | |
280 | decl = NULL; | |
281 | break; | |
282 | ||
283 | case VAR_DECL: | |
284 | break; | |
285 | ||
286 | case ARRAY_REF: | |
287 | case ARRAY_RANGE_REF: | |
288 | case COMPONENT_REF: | |
289 | case BIT_FIELD_REF: | |
290 | case REALPART_EXPR: | |
291 | case IMAGPART_EXPR: | |
292 | case VIEW_CONVERT_EXPR: | |
293 | { | |
294 | HOST_WIDE_INT bitsize, bitpos; | |
295 | tree toffset; | |
c165a033 | 296 | int unsignedp, volatilep = 0; |
9845d120 | 297 | |
298 | decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset, | |
299 | &mode, &unsignedp, &volatilep, false); | |
300 | if (bitsize != GET_MODE_BITSIZE (mode) | |
301 | || (bitpos % BITS_PER_UNIT) | |
302 | || (toffset && !host_integerp (toffset, 0))) | |
303 | decl = NULL; | |
304 | else | |
305 | { | |
306 | offset += bitpos / BITS_PER_UNIT; | |
307 | if (toffset) | |
308 | offset += TREE_INT_CST_LOW (toffset); | |
309 | } | |
310 | break; | |
311 | } | |
312 | } | |
313 | ||
314 | if (decl | |
315 | && mode == GET_MODE (x) | |
316 | && TREE_CODE (decl) == VAR_DECL | |
317 | && (TREE_STATIC (decl) | |
318 | || DECL_THREAD_LOCAL_P (decl)) | |
319 | && DECL_RTL_SET_P (decl) | |
320 | && MEM_P (DECL_RTL (decl))) | |
321 | { | |
322 | rtx newx; | |
323 | ||
da443c27 | 324 | offset += MEM_OFFSET (x); |
9845d120 | 325 | |
326 | newx = DECL_RTL (decl); | |
327 | ||
328 | if (MEM_P (newx)) | |
329 | { | |
330 | rtx n = XEXP (newx, 0), o = XEXP (x, 0); | |
331 | ||
332 | /* Avoid creating a new MEM needlessly if we already had | |
333 | the same address. We do if there's no OFFSET and the | |
334 | old address X is identical to NEWX, or if X is of the | |
335 | form (plus NEWX OFFSET), or the NEWX is of the form | |
336 | (plus Y (const_int Z)) and X is that with the offset | |
337 | added: (plus Y (const_int Z+OFFSET)). */ | |
338 | if (!((offset == 0 | |
339 | || (GET_CODE (o) == PLUS | |
340 | && GET_CODE (XEXP (o, 1)) == CONST_INT | |
341 | && (offset == INTVAL (XEXP (o, 1)) | |
342 | || (GET_CODE (n) == PLUS | |
343 | && GET_CODE (XEXP (n, 1)) == CONST_INT | |
344 | && (INTVAL (XEXP (n, 1)) + offset | |
345 | == INTVAL (XEXP (o, 1))) | |
346 | && (n = XEXP (n, 0)))) | |
347 | && (o = XEXP (o, 0)))) | |
348 | && rtx_equal_p (o, n))) | |
349 | x = adjust_address_nv (newx, mode, offset); | |
350 | } | |
351 | else if (GET_MODE (x) == GET_MODE (newx) | |
352 | && offset == 0) | |
353 | x = newx; | |
354 | } | |
355 | } | |
356 | ||
357 | return x; | |
358 | } | |
359 | \f | |
53cb61a7 | 360 | /* Make a unary operation by first seeing if it folds and otherwise making |
361 | the specified operation. */ | |
362 | ||
363 | rtx | |
60b8c5b3 | 364 | simplify_gen_unary (enum rtx_code code, enum machine_mode mode, rtx op, |
365 | enum machine_mode op_mode) | |
53cb61a7 | 366 | { |
367 | rtx tem; | |
368 | ||
369 | /* If this simplifies, use it. */ | |
370 | if ((tem = simplify_unary_operation (code, mode, op, op_mode)) != 0) | |
371 | return tem; | |
372 | ||
373 | return gen_rtx_fmt_e (code, mode, op); | |
374 | } | |
375 | ||
376 | /* Likewise for ternary operations. */ | |
377 | ||
378 | rtx | |
60b8c5b3 | 379 | simplify_gen_ternary (enum rtx_code code, enum machine_mode mode, |
380 | enum machine_mode op0_mode, rtx op0, rtx op1, rtx op2) | |
53cb61a7 | 381 | { |
382 | rtx tem; | |
383 | ||
384 | /* If this simplifies, use it. */ | |
385 | if (0 != (tem = simplify_ternary_operation (code, mode, op0_mode, | |
386 | op0, op1, op2))) | |
387 | return tem; | |
388 | ||
389 | return gen_rtx_fmt_eee (code, mode, op0, op1, op2); | |
390 | } | |
ac503e50 | 391 | |
e78c6706 | 392 | /* Likewise, for relational operations. |
ac503e50 | 393 | CMP_MODE specifies mode comparison is done in. */ |
53cb61a7 | 394 | |
395 | rtx | |
60b8c5b3 | 396 | simplify_gen_relational (enum rtx_code code, enum machine_mode mode, |
397 | enum machine_mode cmp_mode, rtx op0, rtx op1) | |
53cb61a7 | 398 | { |
399 | rtx tem; | |
400 | ||
ac503e50 | 401 | if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode, |
402 | op0, op1))) | |
403 | return tem; | |
6a64811f | 404 | |
53cb61a7 | 405 | return gen_rtx_fmt_ee (code, mode, op0, op1); |
406 | } | |
407 | \f | |
35af0188 | 408 | /* If FN is NULL, replace all occurrences of OLD_RTX in X with copy_rtx (DATA) |
409 | and simplify the result. If FN is non-NULL, call this callback on each | |
410 | X, if it returns non-NULL, replace X with its return value and simplify the | |
411 | result. */ | |
53cb61a7 | 412 | |
413 | rtx | |
bf4652ac | 414 | simplify_replace_fn_rtx (rtx x, const_rtx old_rtx, |
35af0188 | 415 | rtx (*fn) (rtx, const_rtx, void *), void *data) |
53cb61a7 | 416 | { |
417 | enum rtx_code code = GET_CODE (x); | |
418 | enum machine_mode mode = GET_MODE (x); | |
93124003 | 419 | enum machine_mode op_mode; |
f7038c77 | 420 | const char *fmt; |
421 | rtx op0, op1, op2, newx, op; | |
422 | rtvec vec, newvec; | |
423 | int i, j; | |
53cb61a7 | 424 | |
35af0188 | 425 | if (__builtin_expect (fn != NULL, 0)) |
bf4652ac | 426 | { |
35af0188 | 427 | newx = fn (x, old_rtx, data); |
428 | if (newx) | |
429 | return newx; | |
bf4652ac | 430 | } |
35af0188 | 431 | else if (rtx_equal_p (x, old_rtx)) |
432 | return copy_rtx ((rtx) data); | |
53cb61a7 | 433 | |
434 | switch (GET_RTX_CLASS (code)) | |
435 | { | |
6720e96c | 436 | case RTX_UNARY: |
93124003 | 437 | op0 = XEXP (x, 0); |
438 | op_mode = GET_MODE (op0); | |
bf4652ac | 439 | op0 = simplify_replace_fn_rtx (op0, old_rtx, fn, data); |
93124003 | 440 | if (op0 == XEXP (x, 0)) |
441 | return x; | |
442 | return simplify_gen_unary (code, mode, op0, op_mode); | |
53cb61a7 | 443 | |
6720e96c | 444 | case RTX_BIN_ARITH: |
445 | case RTX_COMM_ARITH: | |
bf4652ac | 446 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
447 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); | |
93124003 | 448 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
449 | return x; | |
450 | return simplify_gen_binary (code, mode, op0, op1); | |
451 | ||
6720e96c | 452 | case RTX_COMPARE: |
453 | case RTX_COMM_COMPARE: | |
93124003 | 454 | op0 = XEXP (x, 0); |
455 | op1 = XEXP (x, 1); | |
456 | op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); | |
bf4652ac | 457 | op0 = simplify_replace_fn_rtx (op0, old_rtx, fn, data); |
458 | op1 = simplify_replace_fn_rtx (op1, old_rtx, fn, data); | |
93124003 | 459 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
460 | return x; | |
461 | return simplify_gen_relational (code, mode, op_mode, op0, op1); | |
53cb61a7 | 462 | |
6720e96c | 463 | case RTX_TERNARY: |
464 | case RTX_BITFIELD_OPS: | |
93124003 | 465 | op0 = XEXP (x, 0); |
466 | op_mode = GET_MODE (op0); | |
bf4652ac | 467 | op0 = simplify_replace_fn_rtx (op0, old_rtx, fn, data); |
468 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); | |
469 | op2 = simplify_replace_fn_rtx (XEXP (x, 2), old_rtx, fn, data); | |
93124003 | 470 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2)) |
471 | return x; | |
472 | if (op_mode == VOIDmode) | |
473 | op_mode = GET_MODE (op0); | |
474 | return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2); | |
53cb61a7 | 475 | |
6720e96c | 476 | case RTX_EXTRA: |
f760707b | 477 | if (code == SUBREG) |
478 | { | |
bf4652ac | 479 | op0 = simplify_replace_fn_rtx (SUBREG_REG (x), old_rtx, fn, data); |
93124003 | 480 | if (op0 == SUBREG_REG (x)) |
481 | return x; | |
482 | op0 = simplify_gen_subreg (GET_MODE (x), op0, | |
f760707b | 483 | GET_MODE (SUBREG_REG (x)), |
484 | SUBREG_BYTE (x)); | |
93124003 | 485 | return op0 ? op0 : x; |
f760707b | 486 | } |
93124003 | 487 | break; |
53cb61a7 | 488 | |
6720e96c | 489 | case RTX_OBJ: |
e1ef2dde | 490 | if (code == MEM) |
93124003 | 491 | { |
bf4652ac | 492 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
93124003 | 493 | if (op0 == XEXP (x, 0)) |
494 | return x; | |
495 | return replace_equiv_address_nv (x, op0); | |
496 | } | |
805ae000 | 497 | else if (code == LO_SUM) |
498 | { | |
bf4652ac | 499 | op0 = simplify_replace_fn_rtx (XEXP (x, 0), old_rtx, fn, data); |
500 | op1 = simplify_replace_fn_rtx (XEXP (x, 1), old_rtx, fn, data); | |
805ae000 | 501 | |
502 | /* (lo_sum (high x) x) -> x */ | |
503 | if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1)) | |
504 | return op1; | |
e1ef2dde | 505 | |
93124003 | 506 | if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) |
507 | return x; | |
805ae000 | 508 | return gen_rtx_LO_SUM (mode, op0, op1); |
509 | } | |
93124003 | 510 | break; |
e1ef2dde | 511 | |
512 | default: | |
93124003 | 513 | break; |
53cb61a7 | 514 | } |
f7038c77 | 515 | |
516 | newx = x; | |
517 | fmt = GET_RTX_FORMAT (code); | |
518 | for (i = 0; fmt[i]; i++) | |
519 | switch (fmt[i]) | |
520 | { | |
521 | case 'E': | |
522 | vec = XVEC (x, i); | |
523 | newvec = XVEC (newx, i); | |
524 | for (j = 0; j < GET_NUM_ELEM (vec); j++) | |
525 | { | |
526 | op = simplify_replace_fn_rtx (RTVEC_ELT (vec, j), | |
527 | old_rtx, fn, data); | |
528 | if (op != RTVEC_ELT (vec, j)) | |
529 | { | |
530 | if (newvec == vec) | |
531 | { | |
532 | newvec = shallow_copy_rtvec (vec); | |
533 | if (x == newx) | |
534 | newx = shallow_copy_rtx (x); | |
535 | XVEC (newx, i) = newvec; | |
536 | } | |
537 | RTVEC_ELT (newvec, j) = op; | |
538 | } | |
539 | } | |
540 | break; | |
541 | ||
542 | case 'e': | |
6ad7c2ac | 543 | if (XEXP (x, i)) |
f7038c77 | 544 | { |
6ad7c2ac | 545 | op = simplify_replace_fn_rtx (XEXP (x, i), old_rtx, fn, data); |
546 | if (op != XEXP (x, i)) | |
547 | { | |
548 | if (x == newx) | |
549 | newx = shallow_copy_rtx (x); | |
550 | XEXP (newx, i) = op; | |
551 | } | |
f7038c77 | 552 | } |
553 | break; | |
554 | } | |
555 | return newx; | |
53cb61a7 | 556 | } |
bf4652ac | 557 | |
558 | /* Replace all occurrences of OLD_RTX in X with NEW_RTX and try to simplify the | |
559 | resulting RTX. Return a new RTX which is as simplified as possible. */ | |
560 | ||
561 | rtx | |
562 | simplify_replace_rtx (rtx x, const_rtx old_rtx, rtx new_rtx) | |
563 | { | |
564 | return simplify_replace_fn_rtx (x, old_rtx, 0, new_rtx); | |
565 | } | |
53cb61a7 | 566 | \f |
af21a202 | 567 | /* Try to simplify a unary operation CODE whose output mode is to be |
568 | MODE with input operand OP whose mode was originally OP_MODE. | |
569 | Return zero if no simplification can be made. */ | |
af21a202 | 570 | rtx |
60b8c5b3 | 571 | simplify_unary_operation (enum rtx_code code, enum machine_mode mode, |
572 | rtx op, enum machine_mode op_mode) | |
3b723a04 | 573 | { |
574 | rtx trueop, tem; | |
575 | ||
3b723a04 | 576 | trueop = avoid_constant_pool_reference (op); |
577 | ||
578 | tem = simplify_const_unary_operation (code, mode, trueop, op_mode); | |
579 | if (tem) | |
580 | return tem; | |
581 | ||
582 | return simplify_unary_operation_1 (code, mode, op); | |
583 | } | |
584 | ||
585 | /* Perform some simplifications we can do even if the operands | |
586 | aren't constant. */ | |
587 | static rtx | |
588 | simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) | |
589 | { | |
590 | enum rtx_code reversed; | |
591 | rtx temp; | |
592 | ||
593 | switch (code) | |
594 | { | |
595 | case NOT: | |
596 | /* (not (not X)) == X. */ | |
597 | if (GET_CODE (op) == NOT) | |
598 | return XEXP (op, 0); | |
599 | ||
6516cbaf | 600 | /* (not (eq X Y)) == (ne X Y), etc. if BImode or the result of the |
601 | comparison is all ones. */ | |
3b723a04 | 602 | if (COMPARISON_P (op) |
603 | && (mode == BImode || STORE_FLAG_VALUE == -1) | |
604 | && ((reversed = reversed_comparison_code (op, NULL_RTX)) != UNKNOWN)) | |
605 | return simplify_gen_relational (reversed, mode, VOIDmode, | |
606 | XEXP (op, 0), XEXP (op, 1)); | |
607 | ||
608 | /* (not (plus X -1)) can become (neg X). */ | |
609 | if (GET_CODE (op) == PLUS | |
610 | && XEXP (op, 1) == constm1_rtx) | |
611 | return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); | |
612 | ||
613 | /* Similarly, (not (neg X)) is (plus X -1). */ | |
614 | if (GET_CODE (op) == NEG) | |
29c05e22 | 615 | return plus_constant (mode, XEXP (op, 0), -1); |
3b723a04 | 616 | |
617 | /* (not (xor X C)) for C constant is (xor X D) with D = ~C. */ | |
618 | if (GET_CODE (op) == XOR | |
971ba038 | 619 | && CONST_INT_P (XEXP (op, 1)) |
3b723a04 | 620 | && (temp = simplify_unary_operation (NOT, mode, |
621 | XEXP (op, 1), mode)) != 0) | |
622 | return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp); | |
623 | ||
624 | /* (not (plus X C)) for signbit C is (xor X D) with D = ~C. */ | |
625 | if (GET_CODE (op) == PLUS | |
971ba038 | 626 | && CONST_INT_P (XEXP (op, 1)) |
3b723a04 | 627 | && mode_signbit_p (mode, XEXP (op, 1)) |
628 | && (temp = simplify_unary_operation (NOT, mode, | |
629 | XEXP (op, 1), mode)) != 0) | |
630 | return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp); | |
631 | ||
632 | ||
633 | /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for | |
634 | operands other than 1, but that is not valid. We could do a | |
635 | similar simplification for (not (lshiftrt C X)) where C is | |
636 | just the sign bit, but this doesn't seem common enough to | |
637 | bother with. */ | |
638 | if (GET_CODE (op) == ASHIFT | |
639 | && XEXP (op, 0) == const1_rtx) | |
640 | { | |
641 | temp = simplify_gen_unary (NOT, mode, const1_rtx, mode); | |
642 | return simplify_gen_binary (ROTATE, mode, temp, XEXP (op, 1)); | |
643 | } | |
644 | ||
3b723a04 | 645 | /* (not (ashiftrt foo C)) where C is the number of bits in FOO |
646 | minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, | |
647 | so we can perform the above simplification. */ | |
48e1416a | 648 | |
3b723a04 | 649 | if (STORE_FLAG_VALUE == -1 |
650 | && GET_CODE (op) == ASHIFTRT | |
971ba038 | 651 | && GET_CODE (XEXP (op, 1)) |
ded805e6 | 652 | && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1) |
3b723a04 | 653 | return simplify_gen_relational (GE, mode, VOIDmode, |
654 | XEXP (op, 0), const0_rtx); | |
655 | ||
6516cbaf | 656 | |
657 | if (GET_CODE (op) == SUBREG | |
658 | && subreg_lowpart_p (op) | |
659 | && (GET_MODE_SIZE (GET_MODE (op)) | |
660 | < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) | |
661 | && GET_CODE (SUBREG_REG (op)) == ASHIFT | |
662 | && XEXP (SUBREG_REG (op), 0) == const1_rtx) | |
663 | { | |
664 | enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op)); | |
665 | rtx x; | |
666 | ||
667 | x = gen_rtx_ROTATE (inner_mode, | |
668 | simplify_gen_unary (NOT, inner_mode, const1_rtx, | |
669 | inner_mode), | |
670 | XEXP (SUBREG_REG (op), 1)); | |
671 | return rtl_hooks.gen_lowpart_no_emit (mode, x); | |
672 | } | |
673 | ||
674 | /* Apply De Morgan's laws to reduce number of patterns for machines | |
675 | with negating logical insns (and-not, nand, etc.). If result has | |
676 | only one NOT, put it first, since that is how the patterns are | |
677 | coded. */ | |
678 | ||
679 | if (GET_CODE (op) == IOR || GET_CODE (op) == AND) | |
680 | { | |
681 | rtx in1 = XEXP (op, 0), in2 = XEXP (op, 1); | |
682 | enum machine_mode op_mode; | |
683 | ||
684 | op_mode = GET_MODE (in1); | |
685 | in1 = simplify_gen_unary (NOT, op_mode, in1, op_mode); | |
686 | ||
687 | op_mode = GET_MODE (in2); | |
688 | if (op_mode == VOIDmode) | |
689 | op_mode = mode; | |
690 | in2 = simplify_gen_unary (NOT, op_mode, in2, op_mode); | |
691 | ||
692 | if (GET_CODE (in2) == NOT && GET_CODE (in1) != NOT) | |
693 | { | |
694 | rtx tem = in2; | |
695 | in2 = in1; in1 = tem; | |
696 | } | |
697 | ||
698 | return gen_rtx_fmt_ee (GET_CODE (op) == IOR ? AND : IOR, | |
699 | mode, in1, in2); | |
700 | } | |
3b723a04 | 701 | break; |
702 | ||
703 | case NEG: | |
704 | /* (neg (neg X)) == X. */ | |
705 | if (GET_CODE (op) == NEG) | |
706 | return XEXP (op, 0); | |
707 | ||
708 | /* (neg (plus X 1)) can become (not X). */ | |
709 | if (GET_CODE (op) == PLUS | |
710 | && XEXP (op, 1) == const1_rtx) | |
711 | return simplify_gen_unary (NOT, mode, XEXP (op, 0), mode); | |
48e1416a | 712 | |
3b723a04 | 713 | /* Similarly, (neg (not X)) is (plus X 1). */ |
714 | if (GET_CODE (op) == NOT) | |
29c05e22 | 715 | return plus_constant (mode, XEXP (op, 0), 1); |
48e1416a | 716 | |
3b723a04 | 717 | /* (neg (minus X Y)) can become (minus Y X). This transformation |
718 | isn't safe for modes with signed zeros, since if X and Y are | |
719 | both +0, (minus Y X) is the same as (minus X Y). If the | |
720 | rounding mode is towards +infinity (or -infinity) then the two | |
721 | expressions will be rounded differently. */ | |
722 | if (GET_CODE (op) == MINUS | |
723 | && !HONOR_SIGNED_ZEROS (mode) | |
724 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) | |
725 | return simplify_gen_binary (MINUS, mode, XEXP (op, 1), XEXP (op, 0)); | |
48e1416a | 726 | |
3b723a04 | 727 | if (GET_CODE (op) == PLUS |
728 | && !HONOR_SIGNED_ZEROS (mode) | |
729 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) | |
730 | { | |
731 | /* (neg (plus A C)) is simplified to (minus -C A). */ | |
971ba038 | 732 | if (CONST_INT_P (XEXP (op, 1)) |
3b723a04 | 733 | || GET_CODE (XEXP (op, 1)) == CONST_DOUBLE) |
734 | { | |
735 | temp = simplify_unary_operation (NEG, mode, XEXP (op, 1), mode); | |
736 | if (temp) | |
737 | return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 0)); | |
738 | } | |
739 | ||
740 | /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */ | |
741 | temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); | |
742 | return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1)); | |
743 | } | |
744 | ||
0ed407e4 | 745 | /* (neg (mult A B)) becomes (mult A (neg B)). |
3b723a04 | 746 | This works even for floating-point values. */ |
747 | if (GET_CODE (op) == MULT | |
748 | && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) | |
749 | { | |
0ed407e4 | 750 | temp = simplify_gen_unary (NEG, mode, XEXP (op, 1), mode); |
751 | return simplify_gen_binary (MULT, mode, XEXP (op, 0), temp); | |
3b723a04 | 752 | } |
753 | ||
754 | /* NEG commutes with ASHIFT since it is multiplication. Only do | |
755 | this if we can then eliminate the NEG (e.g., if the operand | |
756 | is a constant). */ | |
757 | if (GET_CODE (op) == ASHIFT) | |
758 | { | |
759 | temp = simplify_unary_operation (NEG, mode, XEXP (op, 0), mode); | |
760 | if (temp) | |
761 | return simplify_gen_binary (ASHIFT, mode, temp, XEXP (op, 1)); | |
762 | } | |
763 | ||
764 | /* (neg (ashiftrt X C)) can be replaced by (lshiftrt X C) when | |
765 | C is equal to the width of MODE minus 1. */ | |
766 | if (GET_CODE (op) == ASHIFTRT | |
971ba038 | 767 | && CONST_INT_P (XEXP (op, 1)) |
ded805e6 | 768 | && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1) |
3b723a04 | 769 | return simplify_gen_binary (LSHIFTRT, mode, |
770 | XEXP (op, 0), XEXP (op, 1)); | |
771 | ||
772 | /* (neg (lshiftrt X C)) can be replaced by (ashiftrt X C) when | |
773 | C is equal to the width of MODE minus 1. */ | |
774 | if (GET_CODE (op) == LSHIFTRT | |
971ba038 | 775 | && CONST_INT_P (XEXP (op, 1)) |
ded805e6 | 776 | && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1) |
3b723a04 | 777 | return simplify_gen_binary (ASHIFTRT, mode, |
778 | XEXP (op, 0), XEXP (op, 1)); | |
48e1416a | 779 | |
6516cbaf | 780 | /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ |
781 | if (GET_CODE (op) == XOR | |
782 | && XEXP (op, 1) == const1_rtx | |
783 | && nonzero_bits (XEXP (op, 0), mode) == 1) | |
29c05e22 | 784 | return plus_constant (mode, XEXP (op, 0), -1); |
819aeb26 | 785 | |
786 | /* (neg (lt x 0)) is (ashiftrt X C) if STORE_FLAG_VALUE is 1. */ | |
787 | /* (neg (lt x 0)) is (lshiftrt X C) if STORE_FLAG_VALUE is -1. */ | |
788 | if (GET_CODE (op) == LT | |
6ca7788b | 789 | && XEXP (op, 1) == const0_rtx |
790 | && SCALAR_INT_MODE_P (GET_MODE (XEXP (op, 0)))) | |
819aeb26 | 791 | { |
4a9a1e2b | 792 | enum machine_mode inner = GET_MODE (XEXP (op, 0)); |
ded805e6 | 793 | int isize = GET_MODE_PRECISION (inner); |
819aeb26 | 794 | if (STORE_FLAG_VALUE == 1) |
4a9a1e2b | 795 | { |
796 | temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0), | |
797 | GEN_INT (isize - 1)); | |
798 | if (mode == inner) | |
799 | return temp; | |
ded805e6 | 800 | if (GET_MODE_PRECISION (mode) > isize) |
4a9a1e2b | 801 | return simplify_gen_unary (SIGN_EXTEND, mode, temp, inner); |
802 | return simplify_gen_unary (TRUNCATE, mode, temp, inner); | |
803 | } | |
819aeb26 | 804 | else if (STORE_FLAG_VALUE == -1) |
4a9a1e2b | 805 | { |
806 | temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0), | |
807 | GEN_INT (isize - 1)); | |
808 | if (mode == inner) | |
809 | return temp; | |
ded805e6 | 810 | if (GET_MODE_PRECISION (mode) > isize) |
4a9a1e2b | 811 | return simplify_gen_unary (ZERO_EXTEND, mode, temp, inner); |
812 | return simplify_gen_unary (TRUNCATE, mode, temp, inner); | |
813 | } | |
819aeb26 | 814 | } |
6516cbaf | 815 | break; |
816 | ||
817 | case TRUNCATE: | |
818 | /* We can't handle truncation to a partial integer mode here | |
819 | because we don't know the real bitsize of the partial | |
820 | integer mode. */ | |
821 | if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) | |
822 | break; | |
823 | ||
824 | /* (truncate:SI ({sign,zero}_extend:DI foo:SI)) == foo:SI. */ | |
825 | if ((GET_CODE (op) == SIGN_EXTEND | |
826 | || GET_CODE (op) == ZERO_EXTEND) | |
827 | && GET_MODE (XEXP (op, 0)) == mode) | |
828 | return XEXP (op, 0); | |
829 | ||
830 | /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is | |
831 | (OP:SI foo:SI) if OP is NEG or ABS. */ | |
832 | if ((GET_CODE (op) == ABS | |
833 | || GET_CODE (op) == NEG) | |
834 | && (GET_CODE (XEXP (op, 0)) == SIGN_EXTEND | |
835 | || GET_CODE (XEXP (op, 0)) == ZERO_EXTEND) | |
836 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) | |
837 | return simplify_gen_unary (GET_CODE (op), mode, | |
838 | XEXP (XEXP (op, 0), 0), mode); | |
839 | ||
c2e0ce21 | 840 | /* (truncate:A (subreg:B (truncate:C X) 0)) is |
841 | (truncate:A X). */ | |
6516cbaf | 842 | if (GET_CODE (op) == SUBREG |
843 | && GET_CODE (SUBREG_REG (op)) == TRUNCATE | |
844 | && subreg_lowpart_p (op)) | |
c2e0ce21 | 845 | return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), |
846 | GET_MODE (XEXP (SUBREG_REG (op), 0))); | |
6516cbaf | 847 | |
848 | /* If we know that the value is already truncated, we can | |
fd95fba4 | 849 | replace the TRUNCATE with a SUBREG. Note that this is also |
850 | valid if TRULY_NOOP_TRUNCATION is false for the corresponding | |
851 | modes we just have to apply a different definition for | |
48e1416a | 852 | truncation. But don't do this for an (LSHIFTRT (MULT ...)) |
fd95fba4 | 853 | since this will cause problems with the umulXi3_highpart |
854 | patterns. */ | |
396f2130 | 855 | if ((TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) |
fd95fba4 | 856 | ? (num_sign_bit_copies (op, GET_MODE (op)) |
ded805e6 | 857 | > (unsigned int) (GET_MODE_PRECISION (GET_MODE (op)) |
858 | - GET_MODE_PRECISION (mode))) | |
fd95fba4 | 859 | : truncated_to_mode (mode, op)) |
6516cbaf | 860 | && ! (GET_CODE (op) == LSHIFTRT |
861 | && GET_CODE (XEXP (op, 0)) == MULT)) | |
862 | return rtl_hooks.gen_lowpart_no_emit (mode, op); | |
863 | ||
864 | /* A truncate of a comparison can be replaced with a subreg if | |
865 | STORE_FLAG_VALUE permits. This is like the previous test, | |
866 | but it works even if the comparison is done in a mode larger | |
867 | than HOST_BITS_PER_WIDE_INT. */ | |
f179ee60 | 868 | if (HWI_COMPUTABLE_MODE_P (mode) |
6516cbaf | 869 | && COMPARISON_P (op) |
23423d0e | 870 | && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0) |
6516cbaf | 871 | return rtl_hooks.gen_lowpart_no_emit (mode, op); |
872 | break; | |
873 | ||
874 | case FLOAT_TRUNCATE: | |
069b07bf | 875 | if (DECIMAL_FLOAT_MODE_P (mode)) |
876 | break; | |
877 | ||
6516cbaf | 878 | /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ |
879 | if (GET_CODE (op) == FLOAT_EXTEND | |
880 | && GET_MODE (XEXP (op, 0)) == mode) | |
881 | return XEXP (op, 0); | |
882 | ||
883 | /* (float_truncate:SF (float_truncate:DF foo:XF)) | |
884 | = (float_truncate:SF foo:XF). | |
885 | This may eliminate double rounding, so it is unsafe. | |
886 | ||
887 | (float_truncate:SF (float_extend:XF foo:DF)) | |
888 | = (float_truncate:SF foo:DF). | |
889 | ||
890 | (float_truncate:DF (float_extend:XF foo:SF)) | |
891 | = (float_extend:SF foo:DF). */ | |
892 | if ((GET_CODE (op) == FLOAT_TRUNCATE | |
893 | && flag_unsafe_math_optimizations) | |
894 | || GET_CODE (op) == FLOAT_EXTEND) | |
895 | return simplify_gen_unary (GET_MODE_SIZE (GET_MODE (XEXP (op, | |
896 | 0))) | |
897 | > GET_MODE_SIZE (mode) | |
898 | ? FLOAT_TRUNCATE : FLOAT_EXTEND, | |
899 | mode, | |
900 | XEXP (op, 0), mode); | |
901 | ||
902 | /* (float_truncate (float x)) is (float x) */ | |
903 | if (GET_CODE (op) == FLOAT | |
904 | && (flag_unsafe_math_optimizations | |
8373dacd | 905 | || (SCALAR_FLOAT_MODE_P (GET_MODE (op)) |
906 | && ((unsigned)significand_size (GET_MODE (op)) | |
ded805e6 | 907 | >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0))) |
8373dacd | 908 | - num_sign_bit_copies (XEXP (op, 0), |
909 | GET_MODE (XEXP (op, 0)))))))) | |
6516cbaf | 910 | return simplify_gen_unary (FLOAT, mode, |
911 | XEXP (op, 0), | |
912 | GET_MODE (XEXP (op, 0))); | |
913 | ||
914 | /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is | |
915 | (OP:SF foo:SF) if OP is NEG or ABS. */ | |
916 | if ((GET_CODE (op) == ABS | |
917 | || GET_CODE (op) == NEG) | |
918 | && GET_CODE (XEXP (op, 0)) == FLOAT_EXTEND | |
919 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) | |
920 | return simplify_gen_unary (GET_CODE (op), mode, | |
921 | XEXP (XEXP (op, 0), 0), mode); | |
922 | ||
923 | /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0)) | |
924 | is (float_truncate:SF x). */ | |
925 | if (GET_CODE (op) == SUBREG | |
926 | && subreg_lowpart_p (op) | |
927 | && GET_CODE (SUBREG_REG (op)) == FLOAT_TRUNCATE) | |
928 | return SUBREG_REG (op); | |
929 | break; | |
930 | ||
931 | case FLOAT_EXTEND: | |
069b07bf | 932 | if (DECIMAL_FLOAT_MODE_P (mode)) |
933 | break; | |
934 | ||
6516cbaf | 935 | /* (float_extend (float_extend x)) is (float_extend x) |
936 | ||
937 | (float_extend (float x)) is (float x) assuming that double | |
938 | rounding can't happen. | |
939 | */ | |
940 | if (GET_CODE (op) == FLOAT_EXTEND | |
941 | || (GET_CODE (op) == FLOAT | |
8373dacd | 942 | && SCALAR_FLOAT_MODE_P (GET_MODE (op)) |
6516cbaf | 943 | && ((unsigned)significand_size (GET_MODE (op)) |
ded805e6 | 944 | >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0))) |
6516cbaf | 945 | - num_sign_bit_copies (XEXP (op, 0), |
946 | GET_MODE (XEXP (op, 0))))))) | |
947 | return simplify_gen_unary (GET_CODE (op), mode, | |
948 | XEXP (op, 0), | |
949 | GET_MODE (XEXP (op, 0))); | |
950 | ||
951 | break; | |
952 | ||
953 | case ABS: | |
954 | /* (abs (neg <foo>)) -> (abs <foo>) */ | |
955 | if (GET_CODE (op) == NEG) | |
956 | return simplify_gen_unary (ABS, mode, XEXP (op, 0), | |
957 | GET_MODE (XEXP (op, 0))); | |
958 | ||
959 | /* If the mode of the operand is VOIDmode (i.e. if it is ASM_OPERANDS), | |
960 | do nothing. */ | |
961 | if (GET_MODE (op) == VOIDmode) | |
962 | break; | |
963 | ||
964 | /* If operand is something known to be positive, ignore the ABS. */ | |
965 | if (GET_CODE (op) == FFS || GET_CODE (op) == ABS | |
f92430e0 | 966 | || val_signbit_known_clear_p (GET_MODE (op), |
967 | nonzero_bits (op, GET_MODE (op)))) | |
6516cbaf | 968 | return op; |
969 | ||
970 | /* If operand is known to be only -1 or 0, convert ABS to NEG. */ | |
ded805e6 | 971 | if (num_sign_bit_copies (op, mode) == GET_MODE_PRECISION (mode)) |
6516cbaf | 972 | return gen_rtx_NEG (mode, op); |
973 | ||
974 | break; | |
975 | ||
976 | case FFS: | |
977 | /* (ffs (*_extend <X>)) = (ffs <X>) */ | |
978 | if (GET_CODE (op) == SIGN_EXTEND | |
979 | || GET_CODE (op) == ZERO_EXTEND) | |
980 | return simplify_gen_unary (FFS, mode, XEXP (op, 0), | |
981 | GET_MODE (XEXP (op, 0))); | |
982 | break; | |
983 | ||
984 | case POPCOUNT: | |
199c981a | 985 | switch (GET_CODE (op)) |
986 | { | |
987 | case BSWAP: | |
988 | case ZERO_EXTEND: | |
989 | /* (popcount (zero_extend <X>)) = (popcount <X>) */ | |
990 | return simplify_gen_unary (POPCOUNT, mode, XEXP (op, 0), | |
991 | GET_MODE (XEXP (op, 0))); | |
992 | ||
993 | case ROTATE: | |
994 | case ROTATERT: | |
995 | /* Rotations don't affect popcount. */ | |
996 | if (!side_effects_p (XEXP (op, 1))) | |
997 | return simplify_gen_unary (POPCOUNT, mode, XEXP (op, 0), | |
998 | GET_MODE (XEXP (op, 0))); | |
999 | break; | |
1000 | ||
1001 | default: | |
1002 | break; | |
1003 | } | |
1004 | break; | |
1005 | ||
6516cbaf | 1006 | case PARITY: |
199c981a | 1007 | switch (GET_CODE (op)) |
1008 | { | |
1009 | case NOT: | |
1010 | case BSWAP: | |
1011 | case ZERO_EXTEND: | |
1012 | case SIGN_EXTEND: | |
1013 | return simplify_gen_unary (PARITY, mode, XEXP (op, 0), | |
1014 | GET_MODE (XEXP (op, 0))); | |
1015 | ||
1016 | case ROTATE: | |
1017 | case ROTATERT: | |
1018 | /* Rotations don't affect parity. */ | |
1019 | if (!side_effects_p (XEXP (op, 1))) | |
1020 | return simplify_gen_unary (PARITY, mode, XEXP (op, 0), | |
1021 | GET_MODE (XEXP (op, 0))); | |
1022 | break; | |
1023 | ||
1024 | default: | |
1025 | break; | |
1026 | } | |
1027 | break; | |
1028 | ||
1029 | case BSWAP: | |
1030 | /* (bswap (bswap x)) -> x. */ | |
1031 | if (GET_CODE (op) == BSWAP) | |
1032 | return XEXP (op, 0); | |
6516cbaf | 1033 | break; |
1034 | ||
1035 | case FLOAT: | |
1036 | /* (float (sign_extend <X>)) = (float <X>). */ | |
1037 | if (GET_CODE (op) == SIGN_EXTEND) | |
1038 | return simplify_gen_unary (FLOAT, mode, XEXP (op, 0), | |
1039 | GET_MODE (XEXP (op, 0))); | |
3b723a04 | 1040 | break; |
1041 | ||
1042 | case SIGN_EXTEND: | |
1043 | /* (sign_extend (truncate (minus (label_ref L1) (label_ref L2)))) | |
1044 | becomes just the MINUS if its mode is MODE. This allows | |
1045 | folding switch statements on machines using casesi (such as | |
1046 | the VAX). */ | |
1047 | if (GET_CODE (op) == TRUNCATE | |
1048 | && GET_MODE (XEXP (op, 0)) == mode | |
1049 | && GET_CODE (XEXP (op, 0)) == MINUS | |
1050 | && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF | |
1051 | && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF) | |
1052 | return XEXP (op, 0); | |
1053 | ||
9f9356e0 | 1054 | /* Extending a widening multiplication should be canonicalized to |
1055 | a wider widening multiplication. */ | |
1056 | if (GET_CODE (op) == MULT) | |
1057 | { | |
1058 | rtx lhs = XEXP (op, 0); | |
1059 | rtx rhs = XEXP (op, 1); | |
1060 | enum rtx_code lcode = GET_CODE (lhs); | |
1061 | enum rtx_code rcode = GET_CODE (rhs); | |
1062 | ||
1063 | /* Widening multiplies usually extend both operands, but sometimes | |
1064 | they use a shift to extract a portion of a register. */ | |
1065 | if ((lcode == SIGN_EXTEND | |
1066 | || (lcode == ASHIFTRT && CONST_INT_P (XEXP (lhs, 1)))) | |
1067 | && (rcode == SIGN_EXTEND | |
1068 | || (rcode == ASHIFTRT && CONST_INT_P (XEXP (rhs, 1))))) | |
1069 | { | |
1070 | enum machine_mode lmode = GET_MODE (lhs); | |
1071 | enum machine_mode rmode = GET_MODE (rhs); | |
1072 | int bits; | |
1073 | ||
1074 | if (lcode == ASHIFTRT) | |
1075 | /* Number of bits not shifted off the end. */ | |
1076 | bits = GET_MODE_PRECISION (lmode) - INTVAL (XEXP (lhs, 1)); | |
1077 | else /* lcode == SIGN_EXTEND */ | |
1078 | /* Size of inner mode. */ | |
1079 | bits = GET_MODE_PRECISION (GET_MODE (XEXP (lhs, 0))); | |
1080 | ||
1081 | if (rcode == ASHIFTRT) | |
1082 | bits += GET_MODE_PRECISION (rmode) - INTVAL (XEXP (rhs, 1)); | |
1083 | else /* rcode == SIGN_EXTEND */ | |
1084 | bits += GET_MODE_PRECISION (GET_MODE (XEXP (rhs, 0))); | |
1085 | ||
1086 | /* We can only widen multiplies if the result is mathematiclly | |
1087 | equivalent. I.e. if overflow was impossible. */ | |
1088 | if (bits <= GET_MODE_PRECISION (GET_MODE (op))) | |
1089 | return simplify_gen_binary | |
1090 | (MULT, mode, | |
1091 | simplify_gen_unary (SIGN_EXTEND, mode, lhs, lmode), | |
1092 | simplify_gen_unary (SIGN_EXTEND, mode, rhs, rmode)); | |
1093 | } | |
1094 | } | |
1095 | ||
3b723a04 | 1096 | /* Check for a sign extension of a subreg of a promoted |
1097 | variable, where the promotion is sign-extended, and the | |
1098 | target mode is the same as the variable's promotion. */ | |
1099 | if (GET_CODE (op) == SUBREG | |
1100 | && SUBREG_PROMOTED_VAR_P (op) | |
1101 | && ! SUBREG_PROMOTED_UNSIGNED_P (op) | |
ad76ccf5 | 1102 | && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) |
1103 | return rtl_hooks.gen_lowpart_no_emit (mode, op); | |
3b723a04 | 1104 | |
641c53fd | 1105 | /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>). |
1106 | (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */ | |
1107 | if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND) | |
1108 | { | |
1109 | gcc_assert (GET_MODE_BITSIZE (mode) | |
1110 | > GET_MODE_BITSIZE (GET_MODE (op))); | |
1111 | return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0), | |
1112 | GET_MODE (XEXP (op, 0))); | |
1113 | } | |
4e261fcf | 1114 | |
1115 | /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I))) | |
1116 | is (sign_extend:M (subreg:O <X>)) if there is mode with | |
641c53fd | 1117 | GET_MODE_BITSIZE (N) - I bits. |
1118 | (sign_extend:M (lshiftrt:N (ashift <X> (const_int I)) (const_int I))) | |
1119 | is similarly (zero_extend:M (subreg:O <X>)). */ | |
1120 | if ((GET_CODE (op) == ASHIFTRT || GET_CODE (op) == LSHIFTRT) | |
4e261fcf | 1121 | && GET_CODE (XEXP (op, 0)) == ASHIFT |
1122 | && CONST_INT_P (XEXP (op, 1)) | |
1123 | && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) | |
1124 | && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1))) | |
1125 | { | |
1126 | enum machine_mode tmode | |
1127 | = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op)) | |
1128 | - INTVAL (XEXP (op, 1)), MODE_INT, 1); | |
641c53fd | 1129 | gcc_assert (GET_MODE_BITSIZE (mode) |
1130 | > GET_MODE_BITSIZE (GET_MODE (op))); | |
4e261fcf | 1131 | if (tmode != BLKmode) |
1132 | { | |
1133 | rtx inner = | |
1134 | rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); | |
641c53fd | 1135 | return simplify_gen_unary (GET_CODE (op) == ASHIFTRT |
1136 | ? SIGN_EXTEND : ZERO_EXTEND, | |
1137 | mode, inner, tmode); | |
4e261fcf | 1138 | } |
1139 | } | |
1140 | ||
3b723a04 | 1141 | #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend) |
04ec15fa | 1142 | /* As we do not know which address space the pointer is referring to, |
98155838 | 1143 | we can do this only if the target does not support different pointer |
1144 | or address modes depending on the address space. */ | |
1145 | if (target_default_pointer_address_modes_p () | |
1146 | && ! POINTERS_EXTEND_UNSIGNED | |
3b723a04 | 1147 | && mode == Pmode && GET_MODE (op) == ptr_mode |
1148 | && (CONSTANT_P (op) | |
1149 | || (GET_CODE (op) == SUBREG | |
1150 | && REG_P (SUBREG_REG (op)) | |
1151 | && REG_POINTER (SUBREG_REG (op)) | |
1152 | && GET_MODE (SUBREG_REG (op)) == Pmode))) | |
1153 | return convert_memory_address (Pmode, op); | |
1154 | #endif | |
1155 | break; | |
1156 | ||
1157 | case ZERO_EXTEND: | |
1158 | /* Check for a zero extension of a subreg of a promoted | |
1159 | variable, where the promotion is zero-extended, and the | |
1160 | target mode is the same as the variable's promotion. */ | |
1161 | if (GET_CODE (op) == SUBREG | |
1162 | && SUBREG_PROMOTED_VAR_P (op) | |
8fa4ef5a | 1163 | && SUBREG_PROMOTED_UNSIGNED_P (op) > 0 |
ad76ccf5 | 1164 | && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) |
1165 | return rtl_hooks.gen_lowpart_no_emit (mode, op); | |
3b723a04 | 1166 | |
9f9356e0 | 1167 | /* Extending a widening multiplication should be canonicalized to |
1168 | a wider widening multiplication. */ | |
1169 | if (GET_CODE (op) == MULT) | |
1170 | { | |
1171 | rtx lhs = XEXP (op, 0); | |
1172 | rtx rhs = XEXP (op, 1); | |
1173 | enum rtx_code lcode = GET_CODE (lhs); | |
1174 | enum rtx_code rcode = GET_CODE (rhs); | |
1175 | ||
1176 | /* Widening multiplies usually extend both operands, but sometimes | |
1177 | they use a shift to extract a portion of a register. */ | |
1178 | if ((lcode == ZERO_EXTEND | |
1179 | || (lcode == LSHIFTRT && CONST_INT_P (XEXP (lhs, 1)))) | |
1180 | && (rcode == ZERO_EXTEND | |
1181 | || (rcode == LSHIFTRT && CONST_INT_P (XEXP (rhs, 1))))) | |
1182 | { | |
1183 | enum machine_mode lmode = GET_MODE (lhs); | |
1184 | enum machine_mode rmode = GET_MODE (rhs); | |
1185 | int bits; | |
1186 | ||
1187 | if (lcode == LSHIFTRT) | |
1188 | /* Number of bits not shifted off the end. */ | |
1189 | bits = GET_MODE_PRECISION (lmode) - INTVAL (XEXP (lhs, 1)); | |
1190 | else /* lcode == ZERO_EXTEND */ | |
1191 | /* Size of inner mode. */ | |
1192 | bits = GET_MODE_PRECISION (GET_MODE (XEXP (lhs, 0))); | |
1193 | ||
1194 | if (rcode == LSHIFTRT) | |
1195 | bits += GET_MODE_PRECISION (rmode) - INTVAL (XEXP (rhs, 1)); | |
1196 | else /* rcode == ZERO_EXTEND */ | |
1197 | bits += GET_MODE_PRECISION (GET_MODE (XEXP (rhs, 0))); | |
1198 | ||
1199 | /* We can only widen multiplies if the result is mathematiclly | |
1200 | equivalent. I.e. if overflow was impossible. */ | |
1201 | if (bits <= GET_MODE_PRECISION (GET_MODE (op))) | |
1202 | return simplify_gen_binary | |
1203 | (MULT, mode, | |
1204 | simplify_gen_unary (ZERO_EXTEND, mode, lhs, lmode), | |
1205 | simplify_gen_unary (ZERO_EXTEND, mode, rhs, rmode)); | |
1206 | } | |
1207 | } | |
1208 | ||
4e261fcf | 1209 | /* (zero_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>). */ |
1210 | if (GET_CODE (op) == ZERO_EXTEND) | |
1211 | return simplify_gen_unary (ZERO_EXTEND, mode, XEXP (op, 0), | |
1212 | GET_MODE (XEXP (op, 0))); | |
1213 | ||
641c53fd | 1214 | /* (zero_extend:M (lshiftrt:N (ashift <X> (const_int I)) (const_int I))) |
1215 | is (zero_extend:M (subreg:O <X>)) if there is mode with | |
1216 | GET_MODE_BITSIZE (N) - I bits. */ | |
1217 | if (GET_CODE (op) == LSHIFTRT | |
1218 | && GET_CODE (XEXP (op, 0)) == ASHIFT | |
1219 | && CONST_INT_P (XEXP (op, 1)) | |
1220 | && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) | |
1221 | && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1))) | |
1222 | { | |
1223 | enum machine_mode tmode | |
1224 | = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op)) | |
1225 | - INTVAL (XEXP (op, 1)), MODE_INT, 1); | |
1226 | if (tmode != BLKmode) | |
1227 | { | |
1228 | rtx inner = | |
1229 | rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); | |
1230 | return simplify_gen_unary (ZERO_EXTEND, mode, inner, tmode); | |
1231 | } | |
1232 | } | |
1233 | ||
3b723a04 | 1234 | #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend) |
04ec15fa | 1235 | /* As we do not know which address space the pointer is referring to, |
98155838 | 1236 | we can do this only if the target does not support different pointer |
1237 | or address modes depending on the address space. */ | |
1238 | if (target_default_pointer_address_modes_p () | |
1239 | && POINTERS_EXTEND_UNSIGNED > 0 | |
3b723a04 | 1240 | && mode == Pmode && GET_MODE (op) == ptr_mode |
1241 | && (CONSTANT_P (op) | |
1242 | || (GET_CODE (op) == SUBREG | |
1243 | && REG_P (SUBREG_REG (op)) | |
1244 | && REG_POINTER (SUBREG_REG (op)) | |
1245 | && GET_MODE (SUBREG_REG (op)) == Pmode))) | |
1246 | return convert_memory_address (Pmode, op); | |
1247 | #endif | |
1248 | break; | |
1249 | ||
1250 | default: | |
1251 | break; | |
1252 | } | |
48e1416a | 1253 | |
3b723a04 | 1254 | return 0; |
1255 | } | |
1256 | ||
1257 | /* Try to compute the value of a unary operation CODE whose output mode is to | |
1258 | be MODE with input operand OP whose mode was originally OP_MODE. | |
1259 | Return zero if the value cannot be computed. */ | |
1260 | rtx | |
1261 | simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, | |
1262 | rtx op, enum machine_mode op_mode) | |
af21a202 | 1263 | { |
ded805e6 | 1264 | unsigned int width = GET_MODE_PRECISION (mode); |
1265 | unsigned int op_width = GET_MODE_PRECISION (op_mode); | |
af21a202 | 1266 | |
b649c04e | 1267 | if (code == VEC_DUPLICATE) |
1268 | { | |
04e579b6 | 1269 | gcc_assert (VECTOR_MODE_P (mode)); |
3b723a04 | 1270 | if (GET_MODE (op) != VOIDmode) |
04e579b6 | 1271 | { |
3b723a04 | 1272 | if (!VECTOR_MODE_P (GET_MODE (op))) |
1273 | gcc_assert (GET_MODE_INNER (mode) == GET_MODE (op)); | |
04e579b6 | 1274 | else |
1275 | gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER | |
3b723a04 | 1276 | (GET_MODE (op))); |
04e579b6 | 1277 | } |
971ba038 | 1278 | if (CONST_INT_P (op) || GET_CODE (op) == CONST_DOUBLE |
3b723a04 | 1279 | || GET_CODE (op) == CONST_VECTOR) |
b649c04e | 1280 | { |
1281 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); | |
1282 | unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); | |
1283 | rtvec v = rtvec_alloc (n_elts); | |
1284 | unsigned int i; | |
1285 | ||
3b723a04 | 1286 | if (GET_CODE (op) != CONST_VECTOR) |
b649c04e | 1287 | for (i = 0; i < n_elts; i++) |
3b723a04 | 1288 | RTVEC_ELT (v, i) = op; |
b649c04e | 1289 | else |
1290 | { | |
3b723a04 | 1291 | enum machine_mode inmode = GET_MODE (op); |
b649c04e | 1292 | int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode)); |
1293 | unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size); | |
1294 | ||
04e579b6 | 1295 | gcc_assert (in_n_elts < n_elts); |
1296 | gcc_assert ((n_elts % in_n_elts) == 0); | |
b649c04e | 1297 | for (i = 0; i < n_elts; i++) |
3b723a04 | 1298 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); |
b649c04e | 1299 | } |
1300 | return gen_rtx_CONST_VECTOR (mode, v); | |
1301 | } | |
1302 | } | |
1303 | ||
3b723a04 | 1304 | if (VECTOR_MODE_P (mode) && GET_CODE (op) == CONST_VECTOR) |
a7e82922 | 1305 | { |
1306 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); | |
1307 | unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); | |
3b723a04 | 1308 | enum machine_mode opmode = GET_MODE (op); |
a7e82922 | 1309 | int op_elt_size = GET_MODE_SIZE (GET_MODE_INNER (opmode)); |
1310 | unsigned op_n_elts = (GET_MODE_SIZE (opmode) / op_elt_size); | |
1311 | rtvec v = rtvec_alloc (n_elts); | |
1312 | unsigned int i; | |
1313 | ||
04e579b6 | 1314 | gcc_assert (op_n_elts == n_elts); |
a7e82922 | 1315 | for (i = 0; i < n_elts; i++) |
1316 | { | |
1317 | rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode), | |
3b723a04 | 1318 | CONST_VECTOR_ELT (op, i), |
a7e82922 | 1319 | GET_MODE_INNER (opmode)); |
1320 | if (!x) | |
1321 | return 0; | |
1322 | RTVEC_ELT (v, i) = x; | |
1323 | } | |
1324 | return gen_rtx_CONST_VECTOR (mode, v); | |
1325 | } | |
1326 | ||
af21a202 | 1327 | /* The order of these tests is critical so that, for example, we don't |
1328 | check the wrong mode (input vs. output) for a conversion operation, | |
1329 | such as FIX. At some point, this should be simplified. */ | |
1330 | ||
3b723a04 | 1331 | if (code == FLOAT && GET_MODE (op) == VOIDmode |
971ba038 | 1332 | && (GET_CODE (op) == CONST_DOUBLE || CONST_INT_P (op))) |
af21a202 | 1333 | { |
1334 | HOST_WIDE_INT hv, lv; | |
1335 | REAL_VALUE_TYPE d; | |
1336 | ||
971ba038 | 1337 | if (CONST_INT_P (op)) |
3b723a04 | 1338 | lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv); |
af21a202 | 1339 | else |
3b723a04 | 1340 | lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op); |
af21a202 | 1341 | |
af21a202 | 1342 | REAL_VALUE_FROM_INT (d, lv, hv, mode); |
af21a202 | 1343 | d = real_value_truncate (mode, d); |
1344 | return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); | |
1345 | } | |
3b723a04 | 1346 | else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode |
1347 | && (GET_CODE (op) == CONST_DOUBLE | |
971ba038 | 1348 | || CONST_INT_P (op))) |
af21a202 | 1349 | { |
1350 | HOST_WIDE_INT hv, lv; | |
1351 | REAL_VALUE_TYPE d; | |
1352 | ||
971ba038 | 1353 | if (CONST_INT_P (op)) |
3b723a04 | 1354 | lv = INTVAL (op), hv = HWI_SIGN_EXTEND (lv); |
af21a202 | 1355 | else |
3b723a04 | 1356 | lv = CONST_DOUBLE_LOW (op), hv = CONST_DOUBLE_HIGH (op); |
af21a202 | 1357 | |
db20fb47 | 1358 | if (op_mode == VOIDmode |
1359 | || GET_MODE_PRECISION (op_mode) > 2 * HOST_BITS_PER_WIDE_INT) | |
1360 | /* We should never get a negative number. */ | |
1361 | gcc_assert (hv >= 0); | |
1362 | else if (GET_MODE_PRECISION (op_mode) <= HOST_BITS_PER_WIDE_INT) | |
af21a202 | 1363 | hv = 0, lv &= GET_MODE_MASK (op_mode); |
1364 | ||
af21a202 | 1365 | REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode); |
af21a202 | 1366 | d = real_value_truncate (mode, d); |
1367 | return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); | |
1368 | } | |
af21a202 | 1369 | |
971ba038 | 1370 | if (CONST_INT_P (op) |
011b255e | 1371 | && width <= HOST_BITS_PER_WIDE_INT && width > 0) |
af21a202 | 1372 | { |
3b723a04 | 1373 | HOST_WIDE_INT arg0 = INTVAL (op); |
19cb6b50 | 1374 | HOST_WIDE_INT val; |
af21a202 | 1375 | |
1376 | switch (code) | |
1377 | { | |
1378 | case NOT: | |
1379 | val = ~ arg0; | |
1380 | break; | |
1381 | ||
1382 | case NEG: | |
1383 | val = - arg0; | |
1384 | break; | |
1385 | ||
1386 | case ABS: | |
1387 | val = (arg0 >= 0 ? arg0 : - arg0); | |
1388 | break; | |
1389 | ||
1390 | case FFS: | |
011b255e | 1391 | arg0 &= GET_MODE_MASK (mode); |
7e8d812e | 1392 | val = ffs_hwi (arg0); |
af21a202 | 1393 | break; |
1394 | ||
6a08d0ab | 1395 | case CLZ: |
011b255e | 1396 | arg0 &= GET_MODE_MASK (mode); |
1397 | if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val)) | |
8f4be2be | 1398 | ; |
1399 | else | |
011b255e | 1400 | val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 1; |
d8492bd3 | 1401 | break; |
1402 | ||
1403 | case CLRSB: | |
011b255e | 1404 | arg0 &= GET_MODE_MASK (mode); |
d8492bd3 | 1405 | if (arg0 == 0) |
011b255e | 1406 | val = GET_MODE_PRECISION (mode) - 1; |
d8492bd3 | 1407 | else if (arg0 >= 0) |
011b255e | 1408 | val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 2; |
d8492bd3 | 1409 | else if (arg0 < 0) |
011b255e | 1410 | val = GET_MODE_PRECISION (mode) - floor_log2 (~arg0) - 2; |
6a08d0ab | 1411 | break; |
1412 | ||
1413 | case CTZ: | |
011b255e | 1414 | arg0 &= GET_MODE_MASK (mode); |
8f4be2be | 1415 | if (arg0 == 0) |
1416 | { | |
1417 | /* Even if the value at zero is undefined, we have to come | |
1418 | up with some replacement. Seems good enough. */ | |
011b255e | 1419 | if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val)) |
1420 | val = GET_MODE_PRECISION (mode); | |
8f4be2be | 1421 | } |
1422 | else | |
7e8d812e | 1423 | val = ctz_hwi (arg0); |
6a08d0ab | 1424 | break; |
1425 | ||
1426 | case POPCOUNT: | |
011b255e | 1427 | arg0 &= GET_MODE_MASK (mode); |
6a08d0ab | 1428 | val = 0; |
1429 | while (arg0) | |
1430 | val++, arg0 &= arg0 - 1; | |
1431 | break; | |
1432 | ||
1433 | case PARITY: | |
011b255e | 1434 | arg0 &= GET_MODE_MASK (mode); |
6a08d0ab | 1435 | val = 0; |
1436 | while (arg0) | |
1437 | val++, arg0 &= arg0 - 1; | |
1438 | val &= 1; | |
1439 | break; | |
1440 | ||
42791117 | 1441 | case BSWAP: |
199c981a | 1442 | { |
1443 | unsigned int s; | |
1444 | ||
1445 | val = 0; | |
1446 | for (s = 0; s < width; s += 8) | |
1447 | { | |
1448 | unsigned int d = width - s - 8; | |
1449 | unsigned HOST_WIDE_INT byte; | |
1450 | byte = (arg0 >> s) & 0xff; | |
1451 | val |= byte << d; | |
1452 | } | |
1453 | } | |
1454 | break; | |
42791117 | 1455 | |
af21a202 | 1456 | case TRUNCATE: |
1457 | val = arg0; | |
1458 | break; | |
1459 | ||
1460 | case ZERO_EXTEND: | |
bd72d0ee | 1461 | /* When zero-extending a CONST_INT, we need to know its |
1462 | original mode. */ | |
04e579b6 | 1463 | gcc_assert (op_mode != VOIDmode); |
ded805e6 | 1464 | if (op_width == HOST_BITS_PER_WIDE_INT) |
af21a202 | 1465 | { |
1466 | /* If we were really extending the mode, | |
1467 | we would have to distinguish between zero-extension | |
1468 | and sign-extension. */ | |
ded805e6 | 1469 | gcc_assert (width == op_width); |
af21a202 | 1470 | val = arg0; |
1471 | } | |
1472 | else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) | |
f92430e0 | 1473 | val = arg0 & GET_MODE_MASK (op_mode); |
af21a202 | 1474 | else |
1475 | return 0; | |
1476 | break; | |
1477 | ||
1478 | case SIGN_EXTEND: | |
1479 | if (op_mode == VOIDmode) | |
1480 | op_mode = mode; | |
ded805e6 | 1481 | op_width = GET_MODE_PRECISION (op_mode); |
1482 | if (op_width == HOST_BITS_PER_WIDE_INT) | |
af21a202 | 1483 | { |
1484 | /* If we were really extending the mode, | |
1485 | we would have to distinguish between zero-extension | |
1486 | and sign-extension. */ | |
ded805e6 | 1487 | gcc_assert (width == op_width); |
af21a202 | 1488 | val = arg0; |
1489 | } | |
ded805e6 | 1490 | else if (op_width < HOST_BITS_PER_WIDE_INT) |
af21a202 | 1491 | { |
f92430e0 | 1492 | val = arg0 & GET_MODE_MASK (op_mode); |
1493 | if (val_signbit_known_set_p (op_mode, val)) | |
1494 | val |= ~GET_MODE_MASK (op_mode); | |
af21a202 | 1495 | } |
1496 | else | |
1497 | return 0; | |
1498 | break; | |
1499 | ||
1500 | case SQRT: | |
bf78c7a8 | 1501 | case FLOAT_EXTEND: |
1502 | case FLOAT_TRUNCATE: | |
d65bfb46 | 1503 | case SS_TRUNCATE: |
1504 | case US_TRUNCATE: | |
719ee5e5 | 1505 | case SS_NEG: |
b563b483 | 1506 | case US_NEG: |
bcd06eff | 1507 | case SS_ABS: |
af21a202 | 1508 | return 0; |
1509 | ||
1510 | default: | |
04e579b6 | 1511 | gcc_unreachable (); |
af21a202 | 1512 | } |
1513 | ||
69e41517 | 1514 | return gen_int_mode (val, mode); |
af21a202 | 1515 | } |
1516 | ||
1517 | /* We can do some operations on integer CONST_DOUBLEs. Also allow | |
1518 | for a DImode operation on a CONST_INT. */ | |
3b723a04 | 1519 | else if (GET_MODE (op) == VOIDmode |
bd72d0ee | 1520 | && width <= HOST_BITS_PER_WIDE_INT * 2 |
3b723a04 | 1521 | && (GET_CODE (op) == CONST_DOUBLE |
971ba038 | 1522 | || CONST_INT_P (op))) |
af21a202 | 1523 | { |
a8fb076f | 1524 | unsigned HOST_WIDE_INT l1, lv; |
1525 | HOST_WIDE_INT h1, hv; | |
af21a202 | 1526 | |
3b723a04 | 1527 | if (GET_CODE (op) == CONST_DOUBLE) |
1528 | l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op); | |
af21a202 | 1529 | else |
3b723a04 | 1530 | l1 = INTVAL (op), h1 = HWI_SIGN_EXTEND (l1); |
af21a202 | 1531 | |
1532 | switch (code) | |
1533 | { | |
1534 | case NOT: | |
1535 | lv = ~ l1; | |
1536 | hv = ~ h1; | |
1537 | break; | |
1538 | ||
1539 | case NEG: | |
1540 | neg_double (l1, h1, &lv, &hv); | |
1541 | break; | |
1542 | ||
1543 | case ABS: | |
1544 | if (h1 < 0) | |
1545 | neg_double (l1, h1, &lv, &hv); | |
1546 | else | |
1547 | lv = l1, hv = h1; | |
1548 | break; | |
1549 | ||
1550 | case FFS: | |
1551 | hv = 0; | |
7e8d812e | 1552 | if (l1 != 0) |
1553 | lv = ffs_hwi (l1); | |
1554 | else if (h1 != 0) | |
1555 | lv = HOST_BITS_PER_WIDE_INT + ffs_hwi (h1); | |
af21a202 | 1556 | else |
7e8d812e | 1557 | lv = 0; |
6a08d0ab | 1558 | break; |
1559 | ||
1560 | case CLZ: | |
1561 | hv = 0; | |
70fb4c07 | 1562 | if (h1 != 0) |
ded805e6 | 1563 | lv = GET_MODE_PRECISION (mode) - floor_log2 (h1) - 1 |
6a08d0ab | 1564 | - HOST_BITS_PER_WIDE_INT; |
70fb4c07 | 1565 | else if (l1 != 0) |
ded805e6 | 1566 | lv = GET_MODE_PRECISION (mode) - floor_log2 (l1) - 1; |
70fb4c07 | 1567 | else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv)) |
ded805e6 | 1568 | lv = GET_MODE_PRECISION (mode); |
6a08d0ab | 1569 | break; |
1570 | ||
1571 | case CTZ: | |
1572 | hv = 0; | |
70fb4c07 | 1573 | if (l1 != 0) |
7e8d812e | 1574 | lv = ctz_hwi (l1); |
70fb4c07 | 1575 | else if (h1 != 0) |
7e8d812e | 1576 | lv = HOST_BITS_PER_WIDE_INT + ctz_hwi (h1); |
70fb4c07 | 1577 | else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv)) |
ded805e6 | 1578 | lv = GET_MODE_PRECISION (mode); |
6a08d0ab | 1579 | break; |
1580 | ||
1581 | case POPCOUNT: | |
1582 | hv = 0; | |
1583 | lv = 0; | |
1584 | while (l1) | |
1585 | lv++, l1 &= l1 - 1; | |
1586 | while (h1) | |
1587 | lv++, h1 &= h1 - 1; | |
1588 | break; | |
1589 | ||
1590 | case PARITY: | |
1591 | hv = 0; | |
1592 | lv = 0; | |
1593 | while (l1) | |
1594 | lv++, l1 &= l1 - 1; | |
1595 | while (h1) | |
1596 | lv++, h1 &= h1 - 1; | |
1597 | lv &= 1; | |
af21a202 | 1598 | break; |
1599 | ||
199c981a | 1600 | case BSWAP: |
1601 | { | |
1602 | unsigned int s; | |
1603 | ||
1604 | hv = 0; | |
1605 | lv = 0; | |
1606 | for (s = 0; s < width; s += 8) | |
1607 | { | |
1608 | unsigned int d = width - s - 8; | |
1609 | unsigned HOST_WIDE_INT byte; | |
1610 | ||
1611 | if (s < HOST_BITS_PER_WIDE_INT) | |
1612 | byte = (l1 >> s) & 0xff; | |
1613 | else | |
1614 | byte = (h1 >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff; | |
1615 | ||
1616 | if (d < HOST_BITS_PER_WIDE_INT) | |
1617 | lv |= byte << d; | |
1618 | else | |
1619 | hv |= byte << (d - HOST_BITS_PER_WIDE_INT); | |
1620 | } | |
1621 | } | |
1622 | break; | |
1623 | ||
af21a202 | 1624 | case TRUNCATE: |
1625 | /* This is just a change-of-mode, so do nothing. */ | |
1626 | lv = l1, hv = h1; | |
1627 | break; | |
1628 | ||
1629 | case ZERO_EXTEND: | |
04e579b6 | 1630 | gcc_assert (op_mode != VOIDmode); |
bd72d0ee | 1631 | |
ded805e6 | 1632 | if (op_width > HOST_BITS_PER_WIDE_INT) |
af21a202 | 1633 | return 0; |
1634 | ||
1635 | hv = 0; | |
1636 | lv = l1 & GET_MODE_MASK (op_mode); | |
1637 | break; | |
1638 | ||
1639 | case SIGN_EXTEND: | |
1640 | if (op_mode == VOIDmode | |
ded805e6 | 1641 | || op_width > HOST_BITS_PER_WIDE_INT) |
af21a202 | 1642 | return 0; |
1643 | else | |
1644 | { | |
1645 | lv = l1 & GET_MODE_MASK (op_mode); | |
f92430e0 | 1646 | if (val_signbit_known_set_p (op_mode, lv)) |
1647 | lv |= ~GET_MODE_MASK (op_mode); | |
af21a202 | 1648 | |
2cae60d1 | 1649 | hv = HWI_SIGN_EXTEND (lv); |
af21a202 | 1650 | } |
1651 | break; | |
1652 | ||
1653 | case SQRT: | |
1654 | return 0; | |
1655 | ||
1656 | default: | |
1657 | return 0; | |
1658 | } | |
1659 | ||
1660 | return immed_double_const (lv, hv, mode); | |
1661 | } | |
1662 | ||
3b723a04 | 1663 | else if (GET_CODE (op) == CONST_DOUBLE |
21be4257 | 1664 | && SCALAR_FLOAT_MODE_P (mode) |
1665 | && SCALAR_FLOAT_MODE_P (GET_MODE (op))) | |
af21a202 | 1666 | { |
805e22b2 | 1667 | REAL_VALUE_TYPE d, t; |
3b723a04 | 1668 | REAL_VALUE_FROM_CONST_DOUBLE (d, op); |
af21a202 | 1669 | |
536f5fb1 | 1670 | switch (code) |
1671 | { | |
1672 | case SQRT: | |
805e22b2 | 1673 | if (HONOR_SNANS (mode) && real_isnan (&d)) |
1674 | return 0; | |
1675 | real_sqrt (&t, mode, &d); | |
1676 | d = t; | |
1677 | break; | |
43e2d3be | 1678 | case ABS: |
dae0b5cb | 1679 | d = real_value_abs (&d); |
43e2d3be | 1680 | break; |
1681 | case NEG: | |
dae0b5cb | 1682 | d = real_value_negate (&d); |
43e2d3be | 1683 | break; |
1684 | case FLOAT_TRUNCATE: | |
1685 | d = real_value_truncate (mode, d); | |
1686 | break; | |
1687 | case FLOAT_EXTEND: | |
21be4257 | 1688 | /* All this does is change the mode, unless changing |
1689 | mode class. */ | |
1690 | if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op))) | |
1691 | real_convert (&d, mode, &d); | |
43e2d3be | 1692 | break; |
1693 | case FIX: | |
1694 | real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); | |
1695 | break; | |
842672ee | 1696 | case NOT: |
1697 | { | |
1698 | long tmp[4]; | |
1699 | int i; | |
1700 | ||
3b723a04 | 1701 | real_to_target (tmp, &d, GET_MODE (op)); |
842672ee | 1702 | for (i = 0; i < 4; i++) |
1703 | tmp[i] = ~tmp[i]; | |
1704 | real_from_target (&d, tmp, mode); | |
3b723a04 | 1705 | break; |
842672ee | 1706 | } |
536f5fb1 | 1707 | default: |
04e579b6 | 1708 | gcc_unreachable (); |
536f5fb1 | 1709 | } |
1710 | return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); | |
af21a202 | 1711 | } |
1712 | ||
3b723a04 | 1713 | else if (GET_CODE (op) == CONST_DOUBLE |
cee7491d | 1714 | && SCALAR_FLOAT_MODE_P (GET_MODE (op)) |
af21a202 | 1715 | && GET_MODE_CLASS (mode) == MODE_INT |
db20fb47 | 1716 | && width <= 2 * HOST_BITS_PER_WIDE_INT && width > 0) |
af21a202 | 1717 | { |
67c65562 | 1718 | /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX |
f024691d | 1719 | operators are intentionally left unspecified (to ease implementation |
67c65562 | 1720 | by target backends), for consistency, this routine implements the |
1721 | same semantics for constant folding as used by the middle-end. */ | |
1722 | ||
3b723a04 | 1723 | /* This was formerly used only for non-IEEE float. |
1724 | eggert@twinsun.com says it is safe for IEEE also. */ | |
67c65562 | 1725 | HOST_WIDE_INT xh, xl, th, tl; |
1726 | REAL_VALUE_TYPE x, t; | |
3b723a04 | 1727 | REAL_VALUE_FROM_CONST_DOUBLE (x, op); |
536f5fb1 | 1728 | switch (code) |
1729 | { | |
67c65562 | 1730 | case FIX: |
1731 | if (REAL_VALUE_ISNAN (x)) | |
1732 | return const0_rtx; | |
1733 | ||
1734 | /* Test against the signed upper bound. */ | |
1735 | if (width > HOST_BITS_PER_WIDE_INT) | |
1736 | { | |
1737 | th = ((unsigned HOST_WIDE_INT) 1 | |
1738 | << (width - HOST_BITS_PER_WIDE_INT - 1)) - 1; | |
1739 | tl = -1; | |
1740 | } | |
1741 | else | |
1742 | { | |
1743 | th = 0; | |
1744 | tl = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; | |
1745 | } | |
1746 | real_from_integer (&t, VOIDmode, tl, th, 0); | |
1747 | if (REAL_VALUES_LESS (t, x)) | |
1748 | { | |
1749 | xh = th; | |
1750 | xl = tl; | |
1751 | break; | |
1752 | } | |
1753 | ||
1754 | /* Test against the signed lower bound. */ | |
1755 | if (width > HOST_BITS_PER_WIDE_INT) | |
1756 | { | |
23423d0e | 1757 | th = (unsigned HOST_WIDE_INT) (-1) |
1758 | << (width - HOST_BITS_PER_WIDE_INT - 1); | |
67c65562 | 1759 | tl = 0; |
1760 | } | |
1761 | else | |
1762 | { | |
1763 | th = -1; | |
23423d0e | 1764 | tl = (unsigned HOST_WIDE_INT) (-1) << (width - 1); |
67c65562 | 1765 | } |
1766 | real_from_integer (&t, VOIDmode, tl, th, 0); | |
1767 | if (REAL_VALUES_LESS (x, t)) | |
1768 | { | |
1769 | xh = th; | |
1770 | xl = tl; | |
1771 | break; | |
1772 | } | |
1773 | REAL_VALUE_TO_INT (&xl, &xh, x); | |
1774 | break; | |
1775 | ||
1776 | case UNSIGNED_FIX: | |
1777 | if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x)) | |
1778 | return const0_rtx; | |
1779 | ||
1780 | /* Test against the unsigned upper bound. */ | |
db20fb47 | 1781 | if (width == 2 * HOST_BITS_PER_WIDE_INT) |
67c65562 | 1782 | { |
1783 | th = -1; | |
1784 | tl = -1; | |
1785 | } | |
1786 | else if (width >= HOST_BITS_PER_WIDE_INT) | |
1787 | { | |
1788 | th = ((unsigned HOST_WIDE_INT) 1 | |
1789 | << (width - HOST_BITS_PER_WIDE_INT)) - 1; | |
1790 | tl = -1; | |
1791 | } | |
1792 | else | |
1793 | { | |
1794 | th = 0; | |
1795 | tl = ((unsigned HOST_WIDE_INT) 1 << width) - 1; | |
1796 | } | |
1797 | real_from_integer (&t, VOIDmode, tl, th, 1); | |
1798 | if (REAL_VALUES_LESS (t, x)) | |
1799 | { | |
1800 | xh = th; | |
1801 | xl = tl; | |
1802 | break; | |
1803 | } | |
1804 | ||
1805 | REAL_VALUE_TO_INT (&xl, &xh, x); | |
1806 | break; | |
1807 | ||
536f5fb1 | 1808 | default: |
04e579b6 | 1809 | gcc_unreachable (); |
536f5fb1 | 1810 | } |
67c65562 | 1811 | return immed_double_const (xl, xh, mode); |
af21a202 | 1812 | } |
4268f174 | 1813 | |
3b723a04 | 1814 | return NULL_RTX; |
af21a202 | 1815 | } |
1816 | \f | |
efbc8128 | 1817 | /* Subroutine of simplify_binary_operation to simplify a commutative, |
1818 | associative binary operation CODE with result mode MODE, operating | |
1819 | on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, | |
1820 | SMIN, SMAX, UMIN or UMAX. Return zero if no simplification or | |
1821 | canonicalization is possible. */ | |
049cadd6 | 1822 | |
049cadd6 | 1823 | static rtx |
1824 | simplify_associative_operation (enum rtx_code code, enum machine_mode mode, | |
1825 | rtx op0, rtx op1) | |
1826 | { | |
1827 | rtx tem; | |
1828 | ||
efbc8128 | 1829 | /* Linearize the operator to the left. */ |
1830 | if (GET_CODE (op1) == code) | |
049cadd6 | 1831 | { |
efbc8128 | 1832 | /* "(a op b) op (c op d)" becomes "((a op b) op c) op d)". */ |
1833 | if (GET_CODE (op0) == code) | |
1834 | { | |
1835 | tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); | |
1836 | return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); | |
1837 | } | |
049cadd6 | 1838 | |
efbc8128 | 1839 | /* "a op (b op c)" becomes "(b op c) op a". */ |
1840 | if (! swap_commutative_operands_p (op1, op0)) | |
1841 | return simplify_gen_binary (code, mode, op1, op0); | |
049cadd6 | 1842 | |
efbc8128 | 1843 | tem = op0; |
1844 | op0 = op1; | |
1845 | op1 = tem; | |
049cadd6 | 1846 | } |
1847 | ||
efbc8128 | 1848 | if (GET_CODE (op0) == code) |
049cadd6 | 1849 | { |
efbc8128 | 1850 | /* Canonicalize "(x op c) op y" as "(x op y) op c". */ |
1851 | if (swap_commutative_operands_p (XEXP (op0, 1), op1)) | |
1852 | { | |
1853 | tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); | |
1854 | return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); | |
1855 | } | |
1856 | ||
1857 | /* Attempt to simplify "(a op b) op c" as "a op (b op c)". */ | |
1f3b83af | 1858 | tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1); |
efbc8128 | 1859 | if (tem != 0) |
1860 | return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); | |
1861 | ||
1862 | /* Attempt to simplify "(a op b) op c" as "(a op c) op b". */ | |
1f3b83af | 1863 | tem = simplify_binary_operation (code, mode, XEXP (op0, 0), op1); |
efbc8128 | 1864 | if (tem != 0) |
1865 | return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); | |
049cadd6 | 1866 | } |
1867 | ||
1868 | return 0; | |
1869 | } | |
1870 | ||
3b723a04 | 1871 | |
af21a202 | 1872 | /* Simplify a binary operation CODE with result mode MODE, operating on OP0 |
1873 | and OP1. Return 0 if no simplification is possible. | |
1874 | ||
1875 | Don't use this for relational operations such as EQ or LT. | |
1876 | Use simplify_relational_operation instead. */ | |
af21a202 | 1877 | rtx |
60b8c5b3 | 1878 | simplify_binary_operation (enum rtx_code code, enum machine_mode mode, |
1879 | rtx op0, rtx op1) | |
af21a202 | 1880 | { |
efbc8128 | 1881 | rtx trueop0, trueop1; |
af21a202 | 1882 | rtx tem; |
1883 | ||
1884 | /* Relational operations don't work here. We must know the mode | |
1885 | of the operands in order to do the comparison correctly. | |
1886 | Assuming a full word can give incorrect results. | |
1887 | Consider comparing 128 with -128 in QImode. */ | |
04e579b6 | 1888 | gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE); |
1889 | gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE); | |
af21a202 | 1890 | |
02cd84cd | 1891 | /* Make sure the constant is second. */ |
6720e96c | 1892 | if (GET_RTX_CLASS (code) == RTX_COMM_ARITH |
efbc8128 | 1893 | && swap_commutative_operands_p (op0, op1)) |
02cd84cd | 1894 | { |
1895 | tem = op0, op0 = op1, op1 = tem; | |
02cd84cd | 1896 | } |
1897 | ||
efbc8128 | 1898 | trueop0 = avoid_constant_pool_reference (op0); |
1899 | trueop1 = avoid_constant_pool_reference (op1); | |
1900 | ||
3b723a04 | 1901 | tem = simplify_const_binary_operation (code, mode, trueop0, trueop1); |
1902 | if (tem) | |
1903 | return tem; | |
1904 | return simplify_binary_operation_1 (code, mode, op0, op1, trueop0, trueop1); | |
1905 | } | |
1906 | ||
c9b0adad | 1907 | /* Subroutine of simplify_binary_operation. Simplify a binary operation |
1908 | CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or | |
1909 | OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the | |
1910 | actual constants. */ | |
1911 | ||
3b723a04 | 1912 | static rtx |
1913 | simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, | |
1914 | rtx op0, rtx op1, rtx trueop0, rtx trueop1) | |
1915 | { | |
6516cbaf | 1916 | rtx tem, reversed, opleft, opright; |
3b723a04 | 1917 | HOST_WIDE_INT val; |
ded805e6 | 1918 | unsigned int width = GET_MODE_PRECISION (mode); |
3b723a04 | 1919 | |
1920 | /* Even if we can't compute a constant result, | |
1921 | there are some cases worth simplifying. */ | |
1922 | ||
1923 | switch (code) | |
a7e82922 | 1924 | { |
3b723a04 | 1925 | case PLUS: |
1926 | /* Maybe simplify x + 0 to x. The two expressions are equivalent | |
1927 | when x is NaN, infinite, or finite and nonzero. They aren't | |
1928 | when x is -0 and the rounding mode is not towards -infinity, | |
1929 | since (-0) + 0 is then 0. */ | |
1930 | if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode)) | |
1931 | return op0; | |
1932 | ||
1933 | /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These | |
1934 | transformations are safe even for IEEE. */ | |
1935 | if (GET_CODE (op0) == NEG) | |
1936 | return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0)); | |
1937 | else if (GET_CODE (op1) == NEG) | |
1938 | return simplify_gen_binary (MINUS, mode, op0, XEXP (op1, 0)); | |
1939 | ||
1940 | /* (~a) + 1 -> -a */ | |
1941 | if (INTEGRAL_MODE_P (mode) | |
1942 | && GET_CODE (op0) == NOT | |
1943 | && trueop1 == const1_rtx) | |
1944 | return simplify_gen_unary (NEG, mode, XEXP (op0, 0), mode); | |
1945 | ||
1946 | /* Handle both-operands-constant cases. We can only add | |
1947 | CONST_INTs to constants since the sum of relocatable symbols | |
1948 | can't be handled by most assemblers. Don't add CONST_INT | |
1949 | to CONST_INT since overflow won't be computed properly if wider | |
1950 | than HOST_BITS_PER_WIDE_INT. */ | |
1951 | ||
db46c9c3 | 1952 | if ((GET_CODE (op0) == CONST |
1953 | || GET_CODE (op0) == SYMBOL_REF | |
1954 | || GET_CODE (op0) == LABEL_REF) | |
971ba038 | 1955 | && CONST_INT_P (op1)) |
29c05e22 | 1956 | return plus_constant (mode, op0, INTVAL (op1)); |
db46c9c3 | 1957 | else if ((GET_CODE (op1) == CONST |
1958 | || GET_CODE (op1) == SYMBOL_REF | |
1959 | || GET_CODE (op1) == LABEL_REF) | |
971ba038 | 1960 | && CONST_INT_P (op0)) |
29c05e22 | 1961 | return plus_constant (mode, op1, INTVAL (op0)); |
3b723a04 | 1962 | |
1963 | /* See if this is something like X * C - X or vice versa or | |
1964 | if the multiplication is written as a shift. If so, we can | |
1965 | distribute and make a new multiply, shift, or maybe just | |
1966 | have X (if C is 2 in the example above). But don't make | |
1967 | something more expensive than we had before. */ | |
1968 | ||
46c0d795 | 1969 | if (SCALAR_INT_MODE_P (mode)) |
3b723a04 | 1970 | { |
3e052aec | 1971 | double_int coeff0, coeff1; |
3b723a04 | 1972 | rtx lhs = op0, rhs = op1; |
1973 | ||
3e052aec | 1974 | coeff0 = double_int_one; |
1975 | coeff1 = double_int_one; | |
1976 | ||
3b723a04 | 1977 | if (GET_CODE (lhs) == NEG) |
83095216 | 1978 | { |
3e052aec | 1979 | coeff0 = double_int_minus_one; |
83095216 | 1980 | lhs = XEXP (lhs, 0); |
1981 | } | |
3b723a04 | 1982 | else if (GET_CODE (lhs) == MULT |
971ba038 | 1983 | && CONST_INT_P (XEXP (lhs, 1))) |
83095216 | 1984 | { |
3e052aec | 1985 | coeff0 = shwi_to_double_int (INTVAL (XEXP (lhs, 1))); |
83095216 | 1986 | lhs = XEXP (lhs, 0); |
1987 | } | |
3b723a04 | 1988 | else if (GET_CODE (lhs) == ASHIFT |
971ba038 | 1989 | && CONST_INT_P (XEXP (lhs, 1)) |
3e052aec | 1990 | && INTVAL (XEXP (lhs, 1)) >= 0 |
3b723a04 | 1991 | && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) |
1992 | { | |
3e052aec | 1993 | coeff0 = double_int_setbit (double_int_zero, |
1994 | INTVAL (XEXP (lhs, 1))); | |
3b723a04 | 1995 | lhs = XEXP (lhs, 0); |
1996 | } | |
a7e82922 | 1997 | |
3b723a04 | 1998 | if (GET_CODE (rhs) == NEG) |
83095216 | 1999 | { |
3e052aec | 2000 | coeff1 = double_int_minus_one; |
83095216 | 2001 | rhs = XEXP (rhs, 0); |
2002 | } | |
3b723a04 | 2003 | else if (GET_CODE (rhs) == MULT |
971ba038 | 2004 | && CONST_INT_P (XEXP (rhs, 1))) |
3b723a04 | 2005 | { |
3e052aec | 2006 | coeff1 = shwi_to_double_int (INTVAL (XEXP (rhs, 1))); |
83095216 | 2007 | rhs = XEXP (rhs, 0); |
3b723a04 | 2008 | } |
2009 | else if (GET_CODE (rhs) == ASHIFT | |
971ba038 | 2010 | && CONST_INT_P (XEXP (rhs, 1)) |
3b723a04 | 2011 | && INTVAL (XEXP (rhs, 1)) >= 0 |
2012 | && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) | |
2013 | { | |
3e052aec | 2014 | coeff1 = double_int_setbit (double_int_zero, |
2015 | INTVAL (XEXP (rhs, 1))); | |
3b723a04 | 2016 | rhs = XEXP (rhs, 0); |
2017 | } | |
2018 | ||
2019 | if (rtx_equal_p (lhs, rhs)) | |
2020 | { | |
2021 | rtx orig = gen_rtx_PLUS (mode, op0, op1); | |
83095216 | 2022 | rtx coeff; |
3e052aec | 2023 | double_int val; |
f529eb25 | 2024 | bool speed = optimize_function_for_speed_p (cfun); |
83095216 | 2025 | |
3e052aec | 2026 | val = double_int_add (coeff0, coeff1); |
2027 | coeff = immed_double_int_const (val, mode); | |
83095216 | 2028 | |
2029 | tem = simplify_gen_binary (MULT, mode, lhs, coeff); | |
7013e87c | 2030 | return set_src_cost (tem, speed) <= set_src_cost (orig, speed) |
3b723a04 | 2031 | ? tem : 0; |
2032 | } | |
2033 | } | |
2034 | ||
2035 | /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit. */ | |
971ba038 | 2036 | if ((CONST_INT_P (op1) |
3b723a04 | 2037 | || GET_CODE (op1) == CONST_DOUBLE) |
2038 | && GET_CODE (op0) == XOR | |
971ba038 | 2039 | && (CONST_INT_P (XEXP (op0, 1)) |
3b723a04 | 2040 | || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) |
2041 | && mode_signbit_p (mode, op1)) | |
2042 | return simplify_gen_binary (XOR, mode, XEXP (op0, 0), | |
2043 | simplify_gen_binary (XOR, mode, op1, | |
2044 | XEXP (op0, 1))); | |
2045 | ||
6516cbaf | 2046 | /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)). */ |
516aa37d | 2047 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
2048 | && GET_CODE (op0) == MULT | |
6516cbaf | 2049 | && GET_CODE (XEXP (op0, 0)) == NEG) |
2050 | { | |
2051 | rtx in1, in2; | |
2052 | ||
2053 | in1 = XEXP (XEXP (op0, 0), 0); | |
2054 | in2 = XEXP (op0, 1); | |
2055 | return simplify_gen_binary (MINUS, mode, op1, | |
2056 | simplify_gen_binary (MULT, mode, | |
2057 | in1, in2)); | |
2058 | } | |
2059 | ||
2060 | /* (plus (comparison A B) C) can become (neg (rev-comp A B)) if | |
2061 | C is 1 and STORE_FLAG_VALUE is -1 or if C is -1 and STORE_FLAG_VALUE | |
2062 | is 1. */ | |
2063 | if (COMPARISON_P (op0) | |
2064 | && ((STORE_FLAG_VALUE == -1 && trueop1 == const1_rtx) | |
2065 | || (STORE_FLAG_VALUE == 1 && trueop1 == constm1_rtx)) | |
2066 | && (reversed = reversed_comparison (op0, mode))) | |
2067 | return | |
2068 | simplify_gen_unary (NEG, mode, reversed, mode); | |
2069 | ||
3b723a04 | 2070 | /* If one of the operands is a PLUS or a MINUS, see if we can |
2071 | simplify this by the associative law. | |
2072 | Don't use the associative law for floating point. | |
2073 | The inaccuracy makes it nonassociative, | |
2074 | and subtle programs can break if operations are associated. */ | |
2075 | ||
2076 | if (INTEGRAL_MODE_P (mode) | |
2077 | && (plus_minus_operand_p (op0) | |
2078 | || plus_minus_operand_p (op1)) | |
e9480a59 | 2079 | && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) |
3b723a04 | 2080 | return tem; |
2081 | ||
2082 | /* Reassociate floating point addition only when the user | |
49d060d7 | 2083 | specifies associative math operations. */ |
3b723a04 | 2084 | if (FLOAT_MODE_P (mode) |
49d060d7 | 2085 | && flag_associative_math) |
a7e82922 | 2086 | { |
3b723a04 | 2087 | tem = simplify_associative_operation (code, mode, op0, op1); |
2088 | if (tem) | |
2089 | return tem; | |
a7e82922 | 2090 | } |
3b723a04 | 2091 | break; |
a7e82922 | 2092 | |
3b723a04 | 2093 | case COMPARE: |
3b723a04 | 2094 | /* Convert (compare (gt (flags) 0) (lt (flags) 0)) to (flags). */ |
2095 | if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT) | |
2096 | || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU)) | |
2097 | && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx) | |
4c3f4e89 | 2098 | { |
3b723a04 | 2099 | rtx xop00 = XEXP (op0, 0); |
2100 | rtx xop10 = XEXP (op1, 0); | |
4c3f4e89 | 2101 | |
3b723a04 | 2102 | #ifdef HAVE_cc0 |
2103 | if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0) | |
2104 | #else | |
2105 | if (REG_P (xop00) && REG_P (xop10) | |
2106 | && GET_MODE (xop00) == GET_MODE (xop10) | |
2107 | && REGNO (xop00) == REGNO (xop10) | |
2108 | && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC | |
2109 | && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC) | |
2110 | #endif | |
2111 | return xop00; | |
4c3f4e89 | 2112 | } |
3b723a04 | 2113 | break; |
2114 | ||
2115 | case MINUS: | |
2116 | /* We can't assume x-x is 0 even with non-IEEE floating point, | |
2117 | but since it is zero except in very strange circumstances, we | |
19da70e0 | 2118 | will treat it as zero with -ffinite-math-only. */ |
3b723a04 | 2119 | if (rtx_equal_p (trueop0, trueop1) |
2120 | && ! side_effects_p (op0) | |
19da70e0 | 2121 | && (!FLOAT_MODE_P (mode) || !HONOR_NANS (mode))) |
3b723a04 | 2122 | return CONST0_RTX (mode); |
2123 | ||
2124 | /* Change subtraction from zero into negation. (0 - x) is the | |
2125 | same as -x when x is NaN, infinite, or finite and nonzero. | |
2126 | But if the mode has signed zeros, and does not round towards | |
2127 | -infinity, then 0 - 0 is 0, not -0. */ | |
2128 | if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode)) | |
2129 | return simplify_gen_unary (NEG, mode, op1, mode); | |
2130 | ||
2131 | /* (-1 - a) is ~a. */ | |
2132 | if (trueop0 == constm1_rtx) | |
2133 | return simplify_gen_unary (NOT, mode, op1, mode); | |
2134 | ||
2135 | /* Subtracting 0 has no effect unless the mode has signed zeros | |
2136 | and supports rounding towards -infinity. In such a case, | |
2137 | 0 - 0 is -0. */ | |
2138 | if (!(HONOR_SIGNED_ZEROS (mode) | |
2139 | && HONOR_SIGN_DEPENDENT_ROUNDING (mode)) | |
2140 | && trueop1 == CONST0_RTX (mode)) | |
2141 | return op0; | |
2142 | ||
2143 | /* See if this is something like X * C - X or vice versa or | |
2144 | if the multiplication is written as a shift. If so, we can | |
2145 | distribute and make a new multiply, shift, or maybe just | |
2146 | have X (if C is 2 in the example above). But don't make | |
2147 | something more expensive than we had before. */ | |
2148 | ||
46c0d795 | 2149 | if (SCALAR_INT_MODE_P (mode)) |
4c3f4e89 | 2150 | { |
3e052aec | 2151 | double_int coeff0, negcoeff1; |
3b723a04 | 2152 | rtx lhs = op0, rhs = op1; |
4c3f4e89 | 2153 | |
3e052aec | 2154 | coeff0 = double_int_one; |
2155 | negcoeff1 = double_int_minus_one; | |
2156 | ||
3b723a04 | 2157 | if (GET_CODE (lhs) == NEG) |
83095216 | 2158 | { |
3e052aec | 2159 | coeff0 = double_int_minus_one; |
83095216 | 2160 | lhs = XEXP (lhs, 0); |
2161 | } | |
3b723a04 | 2162 | else if (GET_CODE (lhs) == MULT |
971ba038 | 2163 | && CONST_INT_P (XEXP (lhs, 1))) |
3b723a04 | 2164 | { |
3e052aec | 2165 | coeff0 = shwi_to_double_int (INTVAL (XEXP (lhs, 1))); |
83095216 | 2166 | lhs = XEXP (lhs, 0); |
3b723a04 | 2167 | } |
2168 | else if (GET_CODE (lhs) == ASHIFT | |
971ba038 | 2169 | && CONST_INT_P (XEXP (lhs, 1)) |
3b723a04 | 2170 | && INTVAL (XEXP (lhs, 1)) >= 0 |
2171 | && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) | |
2172 | { | |
3e052aec | 2173 | coeff0 = double_int_setbit (double_int_zero, |
2174 | INTVAL (XEXP (lhs, 1))); | |
3b723a04 | 2175 | lhs = XEXP (lhs, 0); |
2176 | } | |
4c3f4e89 | 2177 | |
3b723a04 | 2178 | if (GET_CODE (rhs) == NEG) |
83095216 | 2179 | { |
3e052aec | 2180 | negcoeff1 = double_int_one; |
83095216 | 2181 | rhs = XEXP (rhs, 0); |
2182 | } | |
3b723a04 | 2183 | else if (GET_CODE (rhs) == MULT |
971ba038 | 2184 | && CONST_INT_P (XEXP (rhs, 1))) |
3b723a04 | 2185 | { |
3e052aec | 2186 | negcoeff1 = shwi_to_double_int (-INTVAL (XEXP (rhs, 1))); |
83095216 | 2187 | rhs = XEXP (rhs, 0); |
3b723a04 | 2188 | } |
2189 | else if (GET_CODE (rhs) == ASHIFT | |
971ba038 | 2190 | && CONST_INT_P (XEXP (rhs, 1)) |
3b723a04 | 2191 | && INTVAL (XEXP (rhs, 1)) >= 0 |
2192 | && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) | |
2193 | { | |
3e052aec | 2194 | negcoeff1 = double_int_setbit (double_int_zero, |
2195 | INTVAL (XEXP (rhs, 1))); | |
2196 | negcoeff1 = double_int_neg (negcoeff1); | |
3b723a04 | 2197 | rhs = XEXP (rhs, 0); |
2198 | } | |
2199 | ||
2200 | if (rtx_equal_p (lhs, rhs)) | |
2201 | { | |
2202 | rtx orig = gen_rtx_MINUS (mode, op0, op1); | |
83095216 | 2203 | rtx coeff; |
3e052aec | 2204 | double_int val; |
f529eb25 | 2205 | bool speed = optimize_function_for_speed_p (cfun); |
83095216 | 2206 | |
3e052aec | 2207 | val = double_int_add (coeff0, negcoeff1); |
2208 | coeff = immed_double_int_const (val, mode); | |
83095216 | 2209 | |
2210 | tem = simplify_gen_binary (MULT, mode, lhs, coeff); | |
7013e87c | 2211 | return set_src_cost (tem, speed) <= set_src_cost (orig, speed) |
3b723a04 | 2212 | ? tem : 0; |
2213 | } | |
4c3f4e89 | 2214 | } |
2215 | ||
3b723a04 | 2216 | /* (a - (-b)) -> (a + b). True even for IEEE. */ |
2217 | if (GET_CODE (op1) == NEG) | |
2218 | return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0)); | |
4c3f4e89 | 2219 | |
3b723a04 | 2220 | /* (-x - c) may be simplified as (-c - x). */ |
2221 | if (GET_CODE (op0) == NEG | |
971ba038 | 2222 | && (CONST_INT_P (op1) |
3b723a04 | 2223 | || GET_CODE (op1) == CONST_DOUBLE)) |
842672ee | 2224 | { |
3b723a04 | 2225 | tem = simplify_unary_operation (NEG, mode, op1, mode); |
2226 | if (tem) | |
2227 | return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0)); | |
2228 | } | |
842672ee | 2229 | |
3b723a04 | 2230 | /* Don't let a relocatable value get a negative coeff. */ |
971ba038 | 2231 | if (CONST_INT_P (op1) && GET_MODE (op0) != VOIDmode) |
3b723a04 | 2232 | return simplify_gen_binary (PLUS, mode, |
2233 | op0, | |
2234 | neg_const_int (mode, op1)); | |
2235 | ||
2236 | /* (x - (x & y)) -> (x & ~y) */ | |
2237 | if (GET_CODE (op1) == AND) | |
2238 | { | |
2239 | if (rtx_equal_p (op0, XEXP (op1, 0))) | |
842672ee | 2240 | { |
3b723a04 | 2241 | tem = simplify_gen_unary (NOT, mode, XEXP (op1, 1), |
2242 | GET_MODE (XEXP (op1, 1))); | |
2243 | return simplify_gen_binary (AND, mode, op0, tem); | |
2244 | } | |
2245 | if (rtx_equal_p (op0, XEXP (op1, 1))) | |
2246 | { | |
2247 | tem = simplify_gen_unary (NOT, mode, XEXP (op1, 0), | |
2248 | GET_MODE (XEXP (op1, 0))); | |
2249 | return simplify_gen_binary (AND, mode, op0, tem); | |
842672ee | 2250 | } |
842672ee | 2251 | } |
e9480a59 | 2252 | |
6516cbaf | 2253 | /* If STORE_FLAG_VALUE is 1, (minus 1 (comparison foo bar)) can be done |
2254 | by reversing the comparison code if valid. */ | |
2255 | if (STORE_FLAG_VALUE == 1 | |
2256 | && trueop0 == const1_rtx | |
2257 | && COMPARISON_P (op1) | |
2258 | && (reversed = reversed_comparison (op1, mode))) | |
2259 | return reversed; | |
2260 | ||
2261 | /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A). */ | |
516aa37d | 2262 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
2263 | && GET_CODE (op1) == MULT | |
6516cbaf | 2264 | && GET_CODE (XEXP (op1, 0)) == NEG) |
2265 | { | |
2266 | rtx in1, in2; | |
2267 | ||
2268 | in1 = XEXP (XEXP (op1, 0), 0); | |
2269 | in2 = XEXP (op1, 1); | |
2270 | return simplify_gen_binary (PLUS, mode, | |
2271 | simplify_gen_binary (MULT, mode, | |
2272 | in1, in2), | |
2273 | op0); | |
2274 | } | |
2275 | ||
2276 | /* Canonicalize (minus (neg A) (mult B C)) to | |
2277 | (minus (mult (neg B) C) A). */ | |
516aa37d | 2278 | if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) |
2279 | && GET_CODE (op1) == MULT | |
6516cbaf | 2280 | && GET_CODE (op0) == NEG) |
2281 | { | |
2282 | rtx in1, in2; | |
2283 | ||
2284 | in1 = simplify_gen_unary (NEG, mode, XEXP (op1, 0), mode); | |
2285 | in2 = XEXP (op1, 1); | |
2286 | return simplify_gen_binary (MINUS, mode, | |
2287 | simplify_gen_binary (MULT, mode, | |
2288 | in1, in2), | |
2289 | XEXP (op0, 0)); | |
2290 | } | |
2291 | ||
e9480a59 | 2292 | /* If one of the operands is a PLUS or a MINUS, see if we can |
2293 | simplify this by the associative law. This will, for example, | |
2294 | canonicalize (minus A (plus B C)) to (minus (minus A B) C). | |
2295 | Don't use the associative law for floating point. | |
2296 | The inaccuracy makes it nonassociative, | |
2297 | and subtle programs can break if operations are associated. */ | |
2298 | ||
2299 | if (INTEGRAL_MODE_P (mode) | |
2300 | && (plus_minus_operand_p (op0) | |
2301 | || plus_minus_operand_p (op1)) | |
2302 | && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) | |
2303 | return tem; | |
3b723a04 | 2304 | break; |
536f5fb1 | 2305 | |
3b723a04 | 2306 | case MULT: |
2307 | if (trueop1 == constm1_rtx) | |
2308 | return simplify_gen_unary (NEG, mode, op0, mode); | |
2309 | ||
422101e8 | 2310 | if (GET_CODE (op0) == NEG) |
2311 | { | |
2312 | rtx temp = simplify_unary_operation (NEG, mode, op1, mode); | |
0ed407e4 | 2313 | /* If op1 is a MULT as well and simplify_unary_operation |
2314 | just moved the NEG to the second operand, simplify_gen_binary | |
2315 | below could through simplify_associative_operation move | |
2316 | the NEG around again and recurse endlessly. */ | |
2317 | if (temp | |
2318 | && GET_CODE (op1) == MULT | |
2319 | && GET_CODE (temp) == MULT | |
2320 | && XEXP (op1, 0) == XEXP (temp, 0) | |
2321 | && GET_CODE (XEXP (temp, 1)) == NEG | |
2322 | && XEXP (op1, 1) == XEXP (XEXP (temp, 1), 0)) | |
2323 | temp = NULL_RTX; | |
422101e8 | 2324 | if (temp) |
2325 | return simplify_gen_binary (MULT, mode, XEXP (op0, 0), temp); | |
2326 | } | |
2327 | if (GET_CODE (op1) == NEG) | |
2328 | { | |
2329 | rtx temp = simplify_unary_operation (NEG, mode, op0, mode); | |
0ed407e4 | 2330 | /* If op0 is a MULT as well and simplify_unary_operation |
2331 | just moved the NEG to the second operand, simplify_gen_binary | |
2332 | below could through simplify_associative_operation move | |
2333 | the NEG around again and recurse endlessly. */ | |
2334 | if (temp | |
2335 | && GET_CODE (op0) == MULT | |
2336 | && GET_CODE (temp) == MULT | |
2337 | && XEXP (op0, 0) == XEXP (temp, 0) | |
2338 | && GET_CODE (XEXP (temp, 1)) == NEG | |
2339 | && XEXP (op0, 1) == XEXP (XEXP (temp, 1), 0)) | |
2340 | temp = NULL_RTX; | |
422101e8 | 2341 | if (temp) |
2342 | return simplify_gen_binary (MULT, mode, temp, XEXP (op1, 0)); | |
2343 | } | |
2344 | ||
3b723a04 | 2345 | /* Maybe simplify x * 0 to 0. The reduction is not valid if |
2346 | x is NaN, since x * 0 is then also NaN. Nor is it valid | |
2347 | when the mode has signed zeros, since multiplying a negative | |
2348 | number by 0 will give -0, not 0. */ | |
2349 | if (!HONOR_NANS (mode) | |
2350 | && !HONOR_SIGNED_ZEROS (mode) | |
2351 | && trueop1 == CONST0_RTX (mode) | |
2352 | && ! side_effects_p (op0)) | |
2353 | return op1; | |
2354 | ||
2355 | /* In IEEE floating point, x*1 is not equivalent to x for | |
2356 | signalling NaNs. */ | |
2357 | if (!HONOR_SNANS (mode) | |
2358 | && trueop1 == CONST1_RTX (mode)) | |
2359 | return op0; | |
2360 | ||
2361 | /* Convert multiply by constant power of two into shift unless | |
2362 | we are still generating RTL. This test is a kludge. */ | |
971ba038 | 2363 | if (CONST_INT_P (trueop1) |
23423d0e | 2364 | && (val = exact_log2 (UINTVAL (trueop1))) >= 0 |
3b723a04 | 2365 | /* If the mode is larger than the host word size, and the |
2366 | uppermost bit is set, then this isn't a power of two due | |
2367 | to implicit sign extension. */ | |
2368 | && (width <= HOST_BITS_PER_WIDE_INT | |
2369 | || val != HOST_BITS_PER_WIDE_INT - 1)) | |
2370 | return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); | |
2371 | ||
83095216 | 2372 | /* Likewise for multipliers wider than a word. */ |
c9b0adad | 2373 | if (GET_CODE (trueop1) == CONST_DOUBLE |
2374 | && (GET_MODE (trueop1) == VOIDmode | |
2375 | || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT) | |
2376 | && GET_MODE (op0) == mode | |
2377 | && CONST_DOUBLE_LOW (trueop1) == 0 | |
db20fb47 | 2378 | && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0 |
2379 | && (val < 2 * HOST_BITS_PER_WIDE_INT - 1 | |
2380 | || GET_MODE_BITSIZE (mode) <= 2 * HOST_BITS_PER_WIDE_INT)) | |
83095216 | 2381 | return simplify_gen_binary (ASHIFT, mode, op0, |
2382 | GEN_INT (val + HOST_BITS_PER_WIDE_INT)); | |
2383 | ||
3b723a04 | 2384 | /* x*2 is x+x and x*(-1) is -x */ |
2385 | if (GET_CODE (trueop1) == CONST_DOUBLE | |
cee7491d | 2386 | && SCALAR_FLOAT_MODE_P (GET_MODE (trueop1)) |
3db273fd | 2387 | && !DECIMAL_FLOAT_MODE_P (GET_MODE (trueop1)) |
3b723a04 | 2388 | && GET_MODE (op0) == mode) |
2389 | { | |
2390 | REAL_VALUE_TYPE d; | |
2391 | REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); | |
536f5fb1 | 2392 | |
3b723a04 | 2393 | if (REAL_VALUES_EQUAL (d, dconst2)) |
2394 | return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0)); | |
276beea2 | 2395 | |
c9b0adad | 2396 | if (!HONOR_SNANS (mode) |
2397 | && REAL_VALUES_EQUAL (d, dconstm1)) | |
3b723a04 | 2398 | return simplify_gen_unary (NEG, mode, op0, mode); |
2399 | } | |
536f5fb1 | 2400 | |
c9b0adad | 2401 | /* Optimize -x * -x as x * x. */ |
2402 | if (FLOAT_MODE_P (mode) | |
2403 | && GET_CODE (op0) == NEG | |
2404 | && GET_CODE (op1) == NEG | |
2405 | && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) | |
2406 | && !side_effects_p (XEXP (op0, 0))) | |
2407 | return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); | |
2408 | ||
2409 | /* Likewise, optimize abs(x) * abs(x) as x * x. */ | |
2410 | if (SCALAR_FLOAT_MODE_P (mode) | |
2411 | && GET_CODE (op0) == ABS | |
2412 | && GET_CODE (op1) == ABS | |
2413 | && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)) | |
2414 | && !side_effects_p (XEXP (op0, 0))) | |
2415 | return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0)); | |
2416 | ||
3b723a04 | 2417 | /* Reassociate multiplication, but for floating point MULTs |
2418 | only when the user specifies unsafe math optimizations. */ | |
2419 | if (! FLOAT_MODE_P (mode) | |
2420 | || flag_unsafe_math_optimizations) | |
2421 | { | |
2422 | tem = simplify_associative_operation (code, mode, op0, op1); | |
2423 | if (tem) | |
2424 | return tem; | |
2425 | } | |
2426 | break; | |
80f858b6 | 2427 | |
3b723a04 | 2428 | case IOR: |
84ff078e | 2429 | if (trueop1 == CONST0_RTX (mode)) |
3b723a04 | 2430 | return op0; |
ba8dfb08 | 2431 | if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode)) |
3b723a04 | 2432 | return op1; |
2433 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) | |
2434 | return op0; | |
2435 | /* A | (~A) -> -1 */ | |
2436 | if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) | |
2437 | || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) | |
2438 | && ! side_effects_p (op0) | |
1a16849b | 2439 | && SCALAR_INT_MODE_P (mode)) |
3b723a04 | 2440 | return constm1_rtx; |
6516cbaf | 2441 | |
2442 | /* (ior A C) is C if all bits of A that might be nonzero are on in C. */ | |
971ba038 | 2443 | if (CONST_INT_P (op1) |
f179ee60 | 2444 | && HWI_COMPUTABLE_MODE_P (mode) |
23423d0e | 2445 | && (nonzero_bits (op0, mode) & ~UINTVAL (op1)) == 0) |
6516cbaf | 2446 | return op1; |
48e1416a | 2447 | |
d7517e93 | 2448 | /* Canonicalize (X & C1) | C2. */ |
2449 | if (GET_CODE (op0) == AND | |
971ba038 | 2450 | && CONST_INT_P (trueop1) |
2451 | && CONST_INT_P (XEXP (op0, 1))) | |
d7517e93 | 2452 | { |
2453 | HOST_WIDE_INT mask = GET_MODE_MASK (mode); | |
2454 | HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1)); | |
2455 | HOST_WIDE_INT c2 = INTVAL (trueop1); | |
2456 | ||
2457 | /* If (C1&C2) == C1, then (X&C1)|C2 becomes X. */ | |
2458 | if ((c1 & c2) == c1 | |
2459 | && !side_effects_p (XEXP (op0, 0))) | |
2460 | return trueop1; | |
2461 | ||
2462 | /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */ | |
2463 | if (((c1|c2) & mask) == mask) | |
2464 | return simplify_gen_binary (IOR, mode, XEXP (op0, 0), op1); | |
2465 | ||
2466 | /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2. */ | |
2467 | if (((c1 & ~c2) & mask) != (c1 & mask)) | |
2468 | { | |
2469 | tem = simplify_gen_binary (AND, mode, XEXP (op0, 0), | |
2470 | gen_int_mode (c1 & ~c2, mode)); | |
2471 | return simplify_gen_binary (IOR, mode, tem, op1); | |
2472 | } | |
2473 | } | |
2474 | ||
6516cbaf | 2475 | /* Convert (A & B) | A to A. */ |
2476 | if (GET_CODE (op0) == AND | |
2477 | && (rtx_equal_p (XEXP (op0, 0), op1) | |
2478 | || rtx_equal_p (XEXP (op0, 1), op1)) | |
2479 | && ! side_effects_p (XEXP (op0, 0)) | |
2480 | && ! side_effects_p (XEXP (op0, 1))) | |
2481 | return op1; | |
2482 | ||
2483 | /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the | |
2484 | mode size to (rotate A CX). */ | |
2485 | ||
2486 | if (GET_CODE (op1) == ASHIFT | |
2487 | || GET_CODE (op1) == SUBREG) | |
2488 | { | |
2489 | opleft = op1; | |
2490 | opright = op0; | |
2491 | } | |
2492 | else | |
2493 | { | |
2494 | opright = op1; | |
2495 | opleft = op0; | |
2496 | } | |
2497 | ||
2498 | if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT | |
2499 | && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0)) | |
971ba038 | 2500 | && CONST_INT_P (XEXP (opleft, 1)) |
2501 | && CONST_INT_P (XEXP (opright, 1)) | |
6516cbaf | 2502 | && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1)) |
ded805e6 | 2503 | == GET_MODE_PRECISION (mode))) |
6516cbaf | 2504 | return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1)); |
2505 | ||
2506 | /* Same, but for ashift that has been "simplified" to a wider mode | |
2507 | by simplify_shift_const. */ | |
2508 | ||
2509 | if (GET_CODE (opleft) == SUBREG | |
2510 | && GET_CODE (SUBREG_REG (opleft)) == ASHIFT | |
2511 | && GET_CODE (opright) == LSHIFTRT | |
2512 | && GET_CODE (XEXP (opright, 0)) == SUBREG | |
2513 | && GET_MODE (opleft) == GET_MODE (XEXP (opright, 0)) | |
2514 | && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0)) | |
2515 | && (GET_MODE_SIZE (GET_MODE (opleft)) | |
2516 | < GET_MODE_SIZE (GET_MODE (SUBREG_REG (opleft)))) | |
2517 | && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), | |
2518 | SUBREG_REG (XEXP (opright, 0))) | |
971ba038 | 2519 | && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) |
2520 | && CONST_INT_P (XEXP (opright, 1)) | |
6516cbaf | 2521 | && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1)) |
ded805e6 | 2522 | == GET_MODE_PRECISION (mode))) |
6516cbaf | 2523 | return gen_rtx_ROTATE (mode, XEXP (opright, 0), |
d8d8579c | 2524 | XEXP (SUBREG_REG (opleft), 1)); |
6516cbaf | 2525 | |
2526 | /* If we have (ior (and (X C1) C2)), simplify this by making | |
2527 | C1 as small as possible if C1 actually changes. */ | |
971ba038 | 2528 | if (CONST_INT_P (op1) |
f179ee60 | 2529 | && (HWI_COMPUTABLE_MODE_P (mode) |
6516cbaf | 2530 | || INTVAL (op1) > 0) |
2531 | && GET_CODE (op0) == AND | |
971ba038 | 2532 | && CONST_INT_P (XEXP (op0, 1)) |
2533 | && CONST_INT_P (op1) | |
23423d0e | 2534 | && (UINTVAL (XEXP (op0, 1)) & UINTVAL (op1)) != 0) |
6516cbaf | 2535 | return simplify_gen_binary (IOR, mode, |
2536 | simplify_gen_binary | |
2537 | (AND, mode, XEXP (op0, 0), | |
23423d0e | 2538 | GEN_INT (UINTVAL (XEXP (op0, 1)) |
2539 | & ~UINTVAL (op1))), | |
6516cbaf | 2540 | op1); |
2541 | ||
2542 | /* If OP0 is (ashiftrt (plus ...) C), it might actually be | |
2543 | a (sign_extend (plus ...)). Then check if OP1 is a CONST_INT and | |
2544 | the PLUS does not affect any of the bits in OP1: then we can do | |
2545 | the IOR as a PLUS and we can associate. This is valid if OP1 | |
2546 | can be safely shifted left C bits. */ | |
971ba038 | 2547 | if (CONST_INT_P (trueop1) && GET_CODE (op0) == ASHIFTRT |
6516cbaf | 2548 | && GET_CODE (XEXP (op0, 0)) == PLUS |
971ba038 | 2549 | && CONST_INT_P (XEXP (XEXP (op0, 0), 1)) |
2550 | && CONST_INT_P (XEXP (op0, 1)) | |
6516cbaf | 2551 | && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT) |
2552 | { | |
2553 | int count = INTVAL (XEXP (op0, 1)); | |
2554 | HOST_WIDE_INT mask = INTVAL (trueop1) << count; | |
2555 | ||
2556 | if (mask >> count == INTVAL (trueop1) | |
2557 | && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0) | |
2558 | return simplify_gen_binary (ASHIFTRT, mode, | |
29c05e22 | 2559 | plus_constant (mode, XEXP (op0, 0), |
2560 | mask), | |
6516cbaf | 2561 | XEXP (op0, 1)); |
2562 | } | |
2563 | ||
3b723a04 | 2564 | tem = simplify_associative_operation (code, mode, op0, op1); |
2565 | if (tem) | |
2566 | return tem; | |
2567 | break; | |
2568 | ||
2569 | case XOR: | |
84ff078e | 2570 | if (trueop1 == CONST0_RTX (mode)) |
3b723a04 | 2571 | return op0; |
ba8dfb08 | 2572 | if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode)) |
3b723a04 | 2573 | return simplify_gen_unary (NOT, mode, op0, mode); |
78bd5ce2 | 2574 | if (rtx_equal_p (trueop0, trueop1) |
3b723a04 | 2575 | && ! side_effects_p (op0) |
2576 | && GET_MODE_CLASS (mode) != MODE_CC) | |
1c1b50e1 | 2577 | return CONST0_RTX (mode); |
3b723a04 | 2578 | |
2579 | /* Canonicalize XOR of the most significant bit to PLUS. */ | |
971ba038 | 2580 | if ((CONST_INT_P (op1) |
3b723a04 | 2581 | || GET_CODE (op1) == CONST_DOUBLE) |
2582 | && mode_signbit_p (mode, op1)) | |
2583 | return simplify_gen_binary (PLUS, mode, op0, op1); | |
2584 | /* (xor (plus X C1) C2) is (xor X (C1^C2)) if C1 is signbit. */ | |
971ba038 | 2585 | if ((CONST_INT_P (op1) |
3b723a04 | 2586 | || GET_CODE (op1) == CONST_DOUBLE) |
2587 | && GET_CODE (op0) == PLUS | |
971ba038 | 2588 | && (CONST_INT_P (XEXP (op0, 1)) |
3b723a04 | 2589 | || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE) |
2590 | && mode_signbit_p (mode, XEXP (op0, 1))) | |
2591 | return simplify_gen_binary (XOR, mode, XEXP (op0, 0), | |
2592 | simplify_gen_binary (XOR, mode, op1, | |
2593 | XEXP (op0, 1))); | |
6516cbaf | 2594 | |
2595 | /* If we are XORing two things that have no bits in common, | |
2596 | convert them into an IOR. This helps to detect rotation encoded | |
2597 | using those methods and possibly other simplifications. */ | |
2598 | ||
f179ee60 | 2599 | if (HWI_COMPUTABLE_MODE_P (mode) |
6516cbaf | 2600 | && (nonzero_bits (op0, mode) |
2601 | & nonzero_bits (op1, mode)) == 0) | |
2602 | return (simplify_gen_binary (IOR, mode, op0, op1)); | |
2603 | ||
2604 | /* Convert (XOR (NOT x) (NOT y)) to (XOR x y). | |
2605 | Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for | |
2606 | (NOT y). */ | |
2607 | { | |
2608 | int num_negated = 0; | |
2609 | ||
2610 | if (GET_CODE (op0) == NOT) | |
2611 | num_negated++, op0 = XEXP (op0, 0); | |
2612 | if (GET_CODE (op1) == NOT) | |
2613 | num_negated++, op1 = XEXP (op1, 0); | |
2614 | ||
2615 | if (num_negated == 2) | |
2616 | return simplify_gen_binary (XOR, mode, op0, op1); | |
2617 | else if (num_negated == 1) | |
2618 | return simplify_gen_unary (NOT, mode, | |
2619 | simplify_gen_binary (XOR, mode, op0, op1), | |
2620 | mode); | |
2621 | } | |
2622 | ||
2623 | /* Convert (xor (and A B) B) to (and (not A) B). The latter may | |
2624 | correspond to a machine insn or result in further simplifications | |
2625 | if B is a constant. */ | |
2626 | ||
2627 | if (GET_CODE (op0) == AND | |
2628 | && rtx_equal_p (XEXP (op0, 1), op1) | |
2629 | && ! side_effects_p (op1)) | |
2630 | return simplify_gen_binary (AND, mode, | |
2631 | simplify_gen_unary (NOT, mode, | |
2632 | XEXP (op0, 0), mode), | |
2633 | op1); | |
2634 | ||
2635 | else if (GET_CODE (op0) == AND | |
2636 | && rtx_equal_p (XEXP (op0, 0), op1) | |
2637 | && ! side_effects_p (op1)) | |
2638 | return simplify_gen_binary (AND, mode, | |
2639 | simplify_gen_unary (NOT, mode, | |
2640 | XEXP (op0, 1), mode), | |
2641 | op1); | |
2642 | ||
37b591fd | 2643 | /* Given (xor (and A B) C), using P^Q == (~P&Q) | (~Q&P), |
2644 | we can transform like this: | |
2645 | (A&B)^C == ~(A&B)&C | ~C&(A&B) | |
2646 | == (~A|~B)&C | ~C&(A&B) * DeMorgan's Law | |
2647 | == ~A&C | ~B&C | A&(~C&B) * Distribute and re-order | |
2648 | Attempt a few simplifications when B and C are both constants. */ | |
2649 | if (GET_CODE (op0) == AND | |
2650 | && CONST_INT_P (op1) | |
2651 | && CONST_INT_P (XEXP (op0, 1))) | |
2652 | { | |
2653 | rtx a = XEXP (op0, 0); | |
2654 | rtx b = XEXP (op0, 1); | |
2655 | rtx c = op1; | |
2656 | HOST_WIDE_INT bval = INTVAL (b); | |
2657 | HOST_WIDE_INT cval = INTVAL (c); | |
2658 | ||
2659 | rtx na_c | |
2660 | = simplify_binary_operation (AND, mode, | |
2661 | simplify_gen_unary (NOT, mode, a, mode), | |
2662 | c); | |
2663 | if ((~cval & bval) == 0) | |
2664 | { | |
2665 | /* Try to simplify ~A&C | ~B&C. */ | |
2666 | if (na_c != NULL_RTX) | |
2667 | return simplify_gen_binary (IOR, mode, na_c, | |
2668 | GEN_INT (~bval & cval)); | |
2669 | } | |
2670 | else | |
2671 | { | |
2672 | /* If ~A&C is zero, simplify A&(~C&B) | ~B&C. */ | |
2673 | if (na_c == const0_rtx) | |
2674 | { | |
2675 | rtx a_nc_b = simplify_gen_binary (AND, mode, a, | |
2676 | GEN_INT (~cval & bval)); | |
2677 | return simplify_gen_binary (IOR, mode, a_nc_b, | |
2678 | GEN_INT (~bval & cval)); | |
2679 | } | |
2680 | } | |
2681 | } | |
2682 | ||
6516cbaf | 2683 | /* (xor (comparison foo bar) (const_int 1)) can become the reversed |
2684 | comparison if STORE_FLAG_VALUE is 1. */ | |
2685 | if (STORE_FLAG_VALUE == 1 | |
2686 | && trueop1 == const1_rtx | |
2687 | && COMPARISON_P (op0) | |
2688 | && (reversed = reversed_comparison (op0, mode))) | |
2689 | return reversed; | |
2690 | ||
2691 | /* (lshiftrt foo C) where C is the number of bits in FOO minus 1 | |
2692 | is (lt foo (const_int 0)), so we can perform the above | |
2693 | simplification if STORE_FLAG_VALUE is 1. */ | |
2694 | ||
2695 | if (STORE_FLAG_VALUE == 1 | |
2696 | && trueop1 == const1_rtx | |
2697 | && GET_CODE (op0) == LSHIFTRT | |
971ba038 | 2698 | && CONST_INT_P (XEXP (op0, 1)) |
ded805e6 | 2699 | && INTVAL (XEXP (op0, 1)) == GET_MODE_PRECISION (mode) - 1) |
6516cbaf | 2700 | return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx); |
2701 | ||
2702 | /* (xor (comparison foo bar) (const_int sign-bit)) | |
2703 | when STORE_FLAG_VALUE is the sign bit. */ | |
f92430e0 | 2704 | if (val_signbit_p (mode, STORE_FLAG_VALUE) |
6516cbaf | 2705 | && trueop1 == const_true_rtx |
2706 | && COMPARISON_P (op0) | |
2707 | && (reversed = reversed_comparison (op0, mode))) | |
2708 | return reversed; | |
2709 | ||
3b723a04 | 2710 | tem = simplify_associative_operation (code, mode, op0, op1); |
2711 | if (tem) | |
2712 | return tem; | |
2713 | break; | |
2714 | ||
2715 | case AND: | |
1a16849b | 2716 | if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) |
2717 | return trueop1; | |
ba8dfb08 | 2718 | if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode)) |
2719 | return op0; | |
f179ee60 | 2720 | if (HWI_COMPUTABLE_MODE_P (mode)) |
b718fe63 | 2721 | { |
2722 | HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode); | |
c79d4a4d | 2723 | HOST_WIDE_INT nzop1; |
971ba038 | 2724 | if (CONST_INT_P (trueop1)) |
c79d4a4d | 2725 | { |
2726 | HOST_WIDE_INT val1 = INTVAL (trueop1); | |
2727 | /* If we are turning off bits already known off in OP0, we need | |
2728 | not do an AND. */ | |
2729 | if ((nzop0 & ~val1) == 0) | |
2730 | return op0; | |
2731 | } | |
2732 | nzop1 = nonzero_bits (trueop1, mode); | |
b718fe63 | 2733 | /* If we are clearing all the nonzero bits, the result is zero. */ |
c79d4a4d | 2734 | if ((nzop1 & nzop0) == 0 |
2735 | && !side_effects_p (op0) && !side_effects_p (op1)) | |
b718fe63 | 2736 | return CONST0_RTX (mode); |
2737 | } | |
78bd5ce2 | 2738 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0) |
3b723a04 | 2739 | && GET_MODE_CLASS (mode) != MODE_CC) |
2740 | return op0; | |
2741 | /* A & (~A) -> 0 */ | |
2742 | if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1)) | |
2743 | || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0))) | |
2744 | && ! side_effects_p (op0) | |
2745 | && GET_MODE_CLASS (mode) != MODE_CC) | |
1a16849b | 2746 | return CONST0_RTX (mode); |
3b723a04 | 2747 | |
2748 | /* Transform (and (extend X) C) into (zero_extend (and X C)) if | |
2749 | there are no nonzero bits of C outside of X's mode. */ | |
2750 | if ((GET_CODE (op0) == SIGN_EXTEND | |
2751 | || GET_CODE (op0) == ZERO_EXTEND) | |
971ba038 | 2752 | && CONST_INT_P (trueop1) |
f179ee60 | 2753 | && HWI_COMPUTABLE_MODE_P (mode) |
3b723a04 | 2754 | && (~GET_MODE_MASK (GET_MODE (XEXP (op0, 0))) |
23423d0e | 2755 | & UINTVAL (trueop1)) == 0) |
3b723a04 | 2756 | { |
2757 | enum machine_mode imode = GET_MODE (XEXP (op0, 0)); | |
2758 | tem = simplify_gen_binary (AND, imode, XEXP (op0, 0), | |
2759 | gen_int_mode (INTVAL (trueop1), | |
2760 | imode)); | |
2761 | return simplify_gen_unary (ZERO_EXTEND, mode, tem, imode); | |
2762 | } | |
2763 | ||
85ece28d | 2764 | /* Transform (and (truncate X) C) into (truncate (and X C)). This way |
2765 | we might be able to further simplify the AND with X and potentially | |
2766 | remove the truncation altogether. */ | |
2767 | if (GET_CODE (op0) == TRUNCATE && CONST_INT_P (trueop1)) | |
2768 | { | |
2769 | rtx x = XEXP (op0, 0); | |
2770 | enum machine_mode xmode = GET_MODE (x); | |
2771 | tem = simplify_gen_binary (AND, xmode, x, | |
2772 | gen_int_mode (INTVAL (trueop1), xmode)); | |
2773 | return simplify_gen_unary (TRUNCATE, mode, tem, xmode); | |
2774 | } | |
2775 | ||
d7517e93 | 2776 | /* Canonicalize (A | C1) & C2 as (A & C2) | (C1 & C2). */ |
2777 | if (GET_CODE (op0) == IOR | |
971ba038 | 2778 | && CONST_INT_P (trueop1) |
2779 | && CONST_INT_P (XEXP (op0, 1))) | |
d7517e93 | 2780 | { |
2781 | HOST_WIDE_INT tmp = INTVAL (trueop1) & INTVAL (XEXP (op0, 1)); | |
2782 | return simplify_gen_binary (IOR, mode, | |
2783 | simplify_gen_binary (AND, mode, | |
2784 | XEXP (op0, 0), op1), | |
2785 | gen_int_mode (tmp, mode)); | |
2786 | } | |
2787 | ||
6516cbaf | 2788 | /* Convert (A ^ B) & A to A & (~B) since the latter is often a single |
2789 | insn (and may simplify more). */ | |
2790 | if (GET_CODE (op0) == XOR | |
2791 | && rtx_equal_p (XEXP (op0, 0), op1) | |
2792 | && ! side_effects_p (op1)) | |
2793 | return simplify_gen_binary (AND, mode, | |
2794 | simplify_gen_unary (NOT, mode, | |
2795 | XEXP (op0, 1), mode), | |
2796 | op1); | |
2797 | ||
2798 | if (GET_CODE (op0) == XOR | |
2799 | && rtx_equal_p (XEXP (op0, 1), op1) | |
2800 | && ! side_effects_p (op1)) | |
2801 | return simplify_gen_binary (AND, mode, | |
2802 | simplify_gen_unary (NOT, mode, | |
2803 | XEXP (op0, 0), mode), | |
2804 | op1); | |
2805 | ||
2806 | /* Similarly for (~(A ^ B)) & A. */ | |
2807 | if (GET_CODE (op0) == NOT | |
2808 | && GET_CODE (XEXP (op0, 0)) == XOR | |
2809 | && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1) | |
2810 | && ! side_effects_p (op1)) | |
2811 | return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1); | |
2812 | ||
2813 | if (GET_CODE (op0) == NOT | |
2814 | && GET_CODE (XEXP (op0, 0)) == XOR | |
2815 | && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1) | |
2816 | && ! side_effects_p (op1)) | |
2817 | return simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1); | |
2818 | ||
2819 | /* Convert (A | B) & A to A. */ | |
2820 | if (GET_CODE (op0) == IOR | |
2821 | && (rtx_equal_p (XEXP (op0, 0), op1) | |
2822 | || rtx_equal_p (XEXP (op0, 1), op1)) | |
2823 | && ! side_effects_p (XEXP (op0, 0)) | |
2824 | && ! side_effects_p (XEXP (op0, 1))) | |
2825 | return op1; | |
2826 | ||
3b723a04 | 2827 | /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M, |
2828 | ((A & N) + B) & M -> (A + B) & M | |
2829 | Similarly if (N & M) == 0, | |
2830 | ((A | N) + B) & M -> (A + B) & M | |
b718fe63 | 2831 | and for - instead of + and/or ^ instead of |. |
2832 | Also, if (N & M) == 0, then | |
2833 | (A +- N) & M -> A & M. */ | |
971ba038 | 2834 | if (CONST_INT_P (trueop1) |
f179ee60 | 2835 | && HWI_COMPUTABLE_MODE_P (mode) |
23423d0e | 2836 | && ~UINTVAL (trueop1) |
2837 | && (UINTVAL (trueop1) & (UINTVAL (trueop1) + 1)) == 0 | |
3b723a04 | 2838 | && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS)) |
2839 | { | |
2840 | rtx pmop[2]; | |
2841 | int which; | |
2842 | ||
2843 | pmop[0] = XEXP (op0, 0); | |
2844 | pmop[1] = XEXP (op0, 1); | |
2845 | ||
971ba038 | 2846 | if (CONST_INT_P (pmop[1]) |
23423d0e | 2847 | && (UINTVAL (pmop[1]) & UINTVAL (trueop1)) == 0) |
b718fe63 | 2848 | return simplify_gen_binary (AND, mode, pmop[0], op1); |
2849 | ||
3b723a04 | 2850 | for (which = 0; which < 2; which++) |
2851 | { | |
2852 | tem = pmop[which]; | |
2853 | switch (GET_CODE (tem)) | |
80f858b6 | 2854 | { |
3b723a04 | 2855 | case AND: |
971ba038 | 2856 | if (CONST_INT_P (XEXP (tem, 1)) |
23423d0e | 2857 | && (UINTVAL (XEXP (tem, 1)) & UINTVAL (trueop1)) |
2858 | == UINTVAL (trueop1)) | |
3b723a04 | 2859 | pmop[which] = XEXP (tem, 0); |
80f858b6 | 2860 | break; |
3b723a04 | 2861 | case IOR: |
2862 | case XOR: | |
971ba038 | 2863 | if (CONST_INT_P (XEXP (tem, 1)) |
23423d0e | 2864 | && (UINTVAL (XEXP (tem, 1)) & UINTVAL (trueop1)) == 0) |
3b723a04 | 2865 | pmop[which] = XEXP (tem, 0); |
80f858b6 | 2866 | break; |
80f858b6 | 2867 | default: |
2868 | break; | |
2869 | } | |
2870 | } | |
2871 | ||
3b723a04 | 2872 | if (pmop[0] != XEXP (op0, 0) || pmop[1] != XEXP (op0, 1)) |
2873 | { | |
2874 | tem = simplify_gen_binary (GET_CODE (op0), mode, | |
2875 | pmop[0], pmop[1]); | |
2876 | return simplify_gen_binary (code, mode, tem, op1); | |
2877 | } | |
2878 | } | |
3d72a1b5 | 2879 | |
2880 | /* (and X (ior (not X) Y) -> (and X Y) */ | |
2881 | if (GET_CODE (op1) == IOR | |
2882 | && GET_CODE (XEXP (op1, 0)) == NOT | |
2883 | && op0 == XEXP (XEXP (op1, 0), 0)) | |
2884 | return simplify_gen_binary (AND, mode, op0, XEXP (op1, 1)); | |
2885 | ||
2886 | /* (and (ior (not X) Y) X) -> (and X Y) */ | |
2887 | if (GET_CODE (op0) == IOR | |
2888 | && GET_CODE (XEXP (op0, 0)) == NOT | |
2889 | && op1 == XEXP (XEXP (op0, 0), 0)) | |
2890 | return simplify_gen_binary (AND, mode, op1, XEXP (op0, 1)); | |
2891 | ||
3b723a04 | 2892 | tem = simplify_associative_operation (code, mode, op0, op1); |
2893 | if (tem) | |
2894 | return tem; | |
2895 | break; | |
09fde96c | 2896 | |
3b723a04 | 2897 | case UDIV: |
2898 | /* 0/x is 0 (or x&0 if x has side-effects). */ | |
1a16849b | 2899 | if (trueop0 == CONST0_RTX (mode)) |
2900 | { | |
2901 | if (side_effects_p (op1)) | |
2902 | return simplify_gen_binary (AND, mode, op1, trueop0); | |
2903 | return trueop0; | |
2904 | } | |
2905 | /* x/1 is x. */ | |
2906 | if (trueop1 == CONST1_RTX (mode)) | |
2907 | return rtl_hooks.gen_lowpart_no_emit (mode, op0); | |
2908 | /* Convert divide by power of two into shift. */ | |
971ba038 | 2909 | if (CONST_INT_P (trueop1) |
23423d0e | 2910 | && (val = exact_log2 (UINTVAL (trueop1))) > 0) |
1a16849b | 2911 | return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); |
2912 | break; | |
a47b9d79 | 2913 | |
3b723a04 | 2914 | case DIV: |
2915 | /* Handle floating point and integers separately. */ | |
cee7491d | 2916 | if (SCALAR_FLOAT_MODE_P (mode)) |
3b723a04 | 2917 | { |
2918 | /* Maybe change 0.0 / x to 0.0. This transformation isn't | |
2919 | safe for modes with NaNs, since 0.0 / 0.0 will then be | |
2920 | NaN rather than 0.0. Nor is it safe for modes with signed | |
2921 | zeros, since dividing 0 by a negative number gives -0.0 */ | |
2922 | if (trueop0 == CONST0_RTX (mode) | |
2923 | && !HONOR_NANS (mode) | |
2924 | && !HONOR_SIGNED_ZEROS (mode) | |
2925 | && ! side_effects_p (op1)) | |
2926 | return op0; | |
2927 | /* x/1.0 is x. */ | |
2928 | if (trueop1 == CONST1_RTX (mode) | |
2929 | && !HONOR_SNANS (mode)) | |
2930 | return op0; | |
af21a202 | 2931 | |
3b723a04 | 2932 | if (GET_CODE (trueop1) == CONST_DOUBLE |
2933 | && trueop1 != CONST0_RTX (mode)) | |
2934 | { | |
2935 | REAL_VALUE_TYPE d; | |
2936 | REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1); | |
af21a202 | 2937 | |
3b723a04 | 2938 | /* x/-1.0 is -x. */ |
2939 | if (REAL_VALUES_EQUAL (d, dconstm1) | |
2940 | && !HONOR_SNANS (mode)) | |
2941 | return simplify_gen_unary (NEG, mode, op0, mode); | |
af21a202 | 2942 | |
3b723a04 | 2943 | /* Change FP division by a constant into multiplication. |
49d060d7 | 2944 | Only do this with -freciprocal-math. */ |
2945 | if (flag_reciprocal_math | |
3b723a04 | 2946 | && !REAL_VALUES_EQUAL (d, dconst0)) |
2947 | { | |
2948 | REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d); | |
2949 | tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode); | |
2950 | return simplify_gen_binary (MULT, mode, op0, tem); | |
2951 | } | |
2952 | } | |
2953 | } | |
a2b6106f | 2954 | else if (SCALAR_INT_MODE_P (mode)) |
af21a202 | 2955 | { |
3b723a04 | 2956 | /* 0/x is 0 (or x&0 if x has side-effects). */ |
47d397e1 | 2957 | if (trueop0 == CONST0_RTX (mode) |
2958 | && !cfun->can_throw_non_call_exceptions) | |
1a16849b | 2959 | { |
2960 | if (side_effects_p (op1)) | |
2961 | return simplify_gen_binary (AND, mode, op1, trueop0); | |
2962 | return trueop0; | |
2963 | } | |
3b723a04 | 2964 | /* x/1 is x. */ |
1a16849b | 2965 | if (trueop1 == CONST1_RTX (mode)) |
8666c391 | 2966 | return rtl_hooks.gen_lowpart_no_emit (mode, op0); |
3b723a04 | 2967 | /* x/-1 is -x. */ |
2968 | if (trueop1 == constm1_rtx) | |
2969 | { | |
8666c391 | 2970 | rtx x = rtl_hooks.gen_lowpart_no_emit (mode, op0); |
3b723a04 | 2971 | return simplify_gen_unary (NEG, mode, x, mode); |
2972 | } | |
2973 | } | |
2974 | break; | |
af21a202 | 2975 | |
3b723a04 | 2976 | case UMOD: |
2977 | /* 0%x is 0 (or x&0 if x has side-effects). */ | |
1a16849b | 2978 | if (trueop0 == CONST0_RTX (mode)) |
2979 | { | |
2980 | if (side_effects_p (op1)) | |
2981 | return simplify_gen_binary (AND, mode, op1, trueop0); | |
2982 | return trueop0; | |
2983 | } | |
2984 | /* x%1 is 0 (of x&0 if x has side-effects). */ | |
2985 | if (trueop1 == CONST1_RTX (mode)) | |
2986 | { | |
2987 | if (side_effects_p (op0)) | |
2988 | return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); | |
2989 | return CONST0_RTX (mode); | |
2990 | } | |
2991 | /* Implement modulus by power of two as AND. */ | |
971ba038 | 2992 | if (CONST_INT_P (trueop1) |
23423d0e | 2993 | && exact_log2 (UINTVAL (trueop1)) > 0) |
1a16849b | 2994 | return simplify_gen_binary (AND, mode, op0, |
2995 | GEN_INT (INTVAL (op1) - 1)); | |
2996 | break; | |
af21a202 | 2997 | |
3b723a04 | 2998 | case MOD: |
2999 | /* 0%x is 0 (or x&0 if x has side-effects). */ | |
1a16849b | 3000 | if (trueop0 == CONST0_RTX (mode)) |
3001 | { | |
3002 | if (side_effects_p (op1)) | |
3003 | return simplify_gen_binary (AND, mode, op1, trueop0); | |
3004 | return trueop0; | |
3005 | } | |
3006 | /* x%1 and x%-1 is 0 (or x&0 if x has side-effects). */ | |
3007 | if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx) | |
3008 | { | |
3009 | if (side_effects_p (op0)) | |
3010 | return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode)); | |
3011 | return CONST0_RTX (mode); | |
3012 | } | |
3013 | break; | |
af21a202 | 3014 | |
3b723a04 | 3015 | case ROTATERT: |
3016 | case ROTATE: | |
3017 | case ASHIFTRT: | |
445e5fbb | 3018 | if (trueop1 == CONST0_RTX (mode)) |
3019 | return op0; | |
3020 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) | |
3021 | return op0; | |
3b723a04 | 3022 | /* Rotating ~0 always results in ~0. */ |
971ba038 | 3023 | if (CONST_INT_P (trueop0) && width <= HOST_BITS_PER_WIDE_INT |
23423d0e | 3024 | && UINTVAL (trueop0) == GET_MODE_MASK (mode) |
3b723a04 | 3025 | && ! side_effects_p (op1)) |
3026 | return op0; | |
5fe63105 | 3027 | canonicalize_shift: |
971ba038 | 3028 | if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) |
5fe63105 | 3029 | { |
3030 | val = INTVAL (op1) & (GET_MODE_BITSIZE (mode) - 1); | |
3031 | if (val != INTVAL (op1)) | |
3032 | return simplify_gen_binary (code, mode, op0, GEN_INT (val)); | |
3033 | } | |
445e5fbb | 3034 | break; |
2e746e59 | 3035 | |
3b723a04 | 3036 | case ASHIFT: |
719ee5e5 | 3037 | case SS_ASHIFT: |
b563b483 | 3038 | case US_ASHIFT: |
445e5fbb | 3039 | if (trueop1 == CONST0_RTX (mode)) |
3040 | return op0; | |
3041 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) | |
3042 | return op0; | |
5fe63105 | 3043 | goto canonicalize_shift; |
445e5fbb | 3044 | |
3b723a04 | 3045 | case LSHIFTRT: |
1a16849b | 3046 | if (trueop1 == CONST0_RTX (mode)) |
3b723a04 | 3047 | return op0; |
1a16849b | 3048 | if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1)) |
3b723a04 | 3049 | return op0; |
445e5fbb | 3050 | /* Optimize (lshiftrt (clz X) C) as (eq X 0). */ |
3051 | if (GET_CODE (op0) == CLZ | |
971ba038 | 3052 | && CONST_INT_P (trueop1) |
445e5fbb | 3053 | && STORE_FLAG_VALUE == 1 |
885fe2d1 | 3054 | && INTVAL (trueop1) < (HOST_WIDE_INT)width) |
445e5fbb | 3055 | { |
3056 | enum machine_mode imode = GET_MODE (XEXP (op0, 0)); | |
3057 | unsigned HOST_WIDE_INT zero_val = 0; | |
3058 | ||
3059 | if (CLZ_DEFINED_VALUE_AT_ZERO (imode, zero_val) | |
ded805e6 | 3060 | && zero_val == GET_MODE_PRECISION (imode) |
445e5fbb | 3061 | && INTVAL (trueop1) == exact_log2 (zero_val)) |
3062 | return simplify_gen_relational (EQ, mode, imode, | |
3063 | XEXP (op0, 0), const0_rtx); | |
3064 | } | |
5fe63105 | 3065 | goto canonicalize_shift; |
2e746e59 | 3066 | |
3b723a04 | 3067 | case SMIN: |
3068 | if (width <= HOST_BITS_PER_WIDE_INT | |
f92430e0 | 3069 | && mode_signbit_p (mode, trueop1) |
3b723a04 | 3070 | && ! side_effects_p (op0)) |
3071 | return op1; | |
3072 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) | |
3073 | return op0; | |
3074 | tem = simplify_associative_operation (code, mode, op0, op1); | |
3075 | if (tem) | |
3076 | return tem; | |
3077 | break; | |
af21a202 | 3078 | |
3b723a04 | 3079 | case SMAX: |
3080 | if (width <= HOST_BITS_PER_WIDE_INT | |
971ba038 | 3081 | && CONST_INT_P (trueop1) |
23423d0e | 3082 | && (UINTVAL (trueop1) == GET_MODE_MASK (mode) >> 1) |
3b723a04 | 3083 | && ! side_effects_p (op0)) |
3084 | return op1; | |
3085 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) | |
3086 | return op0; | |
3087 | tem = simplify_associative_operation (code, mode, op0, op1); | |
3088 | if (tem) | |
3089 | return tem; | |
3090 | break; | |
af21a202 | 3091 | |
3b723a04 | 3092 | case UMIN: |
1a16849b | 3093 | if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0)) |
3b723a04 | 3094 | return op1; |
3095 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) | |
3096 | return op0; | |
3097 | tem = simplify_associative_operation (code, mode, op0, op1); | |
3098 | if (tem) | |
3099 | return tem; | |
3100 | break; | |
af21a202 | 3101 | |
3b723a04 | 3102 | case UMAX: |
3103 | if (trueop1 == constm1_rtx && ! side_effects_p (op0)) | |
3104 | return op1; | |
3105 | if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) | |
3106 | return op0; | |
3107 | tem = simplify_associative_operation (code, mode, op0, op1); | |
3108 | if (tem) | |
3109 | return tem; | |
3110 | break; | |
af21a202 | 3111 | |
3b723a04 | 3112 | case SS_PLUS: |
3113 | case US_PLUS: | |
3114 | case SS_MINUS: | |
3115 | case US_MINUS: | |
b563b483 | 3116 | case SS_MULT: |
3117 | case US_MULT: | |
3118 | case SS_DIV: | |
3119 | case US_DIV: | |
3b723a04 | 3120 | /* ??? There are simplifications that can be done. */ |
3121 | return 0; | |
af21a202 | 3122 | |
3b723a04 | 3123 | case VEC_SELECT: |
3124 | if (!VECTOR_MODE_P (mode)) | |
3125 | { | |
3126 | gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); | |
3127 | gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0))); | |
3128 | gcc_assert (GET_CODE (trueop1) == PARALLEL); | |
3129 | gcc_assert (XVECLEN (trueop1, 0) == 1); | |
971ba038 | 3130 | gcc_assert (CONST_INT_P (XVECEXP (trueop1, 0, 0))); |
3b723a04 | 3131 | |
3132 | if (GET_CODE (trueop0) == CONST_VECTOR) | |
3133 | return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP | |
3134 | (trueop1, 0, 0))); | |
31a981d7 | 3135 | |
3136 | /* Extract a scalar element from a nested VEC_SELECT expression | |
3137 | (with optional nested VEC_CONCAT expression). Some targets | |
3138 | (i386) extract scalar element from a vector using chain of | |
3139 | nested VEC_SELECT expressions. When input operand is a memory | |
3140 | operand, this operation can be simplified to a simple scalar | |
3141 | load from an offseted memory address. */ | |
3142 | if (GET_CODE (trueop0) == VEC_SELECT) | |
3143 | { | |
3144 | rtx op0 = XEXP (trueop0, 0); | |
3145 | rtx op1 = XEXP (trueop0, 1); | |
3146 | ||
3147 | enum machine_mode opmode = GET_MODE (op0); | |
3148 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (opmode)); | |
3149 | int n_elts = GET_MODE_SIZE (opmode) / elt_size; | |
3150 | ||
3151 | int i = INTVAL (XVECEXP (trueop1, 0, 0)); | |
3152 | int elem; | |
3153 | ||
3154 | rtvec vec; | |
3155 | rtx tmp_op, tmp; | |
3156 | ||
3157 | gcc_assert (GET_CODE (op1) == PARALLEL); | |
3158 | gcc_assert (i < n_elts); | |
3159 | ||
3160 | /* Select element, pointed by nested selector. */ | |
e86f91b1 | 3161 | elem = INTVAL (XVECEXP (op1, 0, i)); |
31a981d7 | 3162 | |
3163 | /* Handle the case when nested VEC_SELECT wraps VEC_CONCAT. */ | |
3164 | if (GET_CODE (op0) == VEC_CONCAT) | |
3165 | { | |
3166 | rtx op00 = XEXP (op0, 0); | |
3167 | rtx op01 = XEXP (op0, 1); | |
3168 | ||
3169 | enum machine_mode mode00, mode01; | |
3170 | int n_elts00, n_elts01; | |
3171 | ||
3172 | mode00 = GET_MODE (op00); | |
3173 | mode01 = GET_MODE (op01); | |
3174 | ||
3175 | /* Find out number of elements of each operand. */ | |
3176 | if (VECTOR_MODE_P (mode00)) | |
3177 | { | |
3178 | elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode00)); | |
3179 | n_elts00 = GET_MODE_SIZE (mode00) / elt_size; | |
3180 | } | |
3181 | else | |
3182 | n_elts00 = 1; | |
3183 | ||
3184 | if (VECTOR_MODE_P (mode01)) | |
3185 | { | |
3186 | elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode01)); | |
3187 | n_elts01 = GET_MODE_SIZE (mode01) / elt_size; | |
3188 | } | |
3189 | else | |
3190 | n_elts01 = 1; | |
3191 | ||
3192 | gcc_assert (n_elts == n_elts00 + n_elts01); | |
3193 | ||
3194 | /* Select correct operand of VEC_CONCAT | |
3195 | and adjust selector. */ | |
3196 | if (elem < n_elts01) | |
3197 | tmp_op = op00; | |
3198 | else | |
3199 | { | |
3200 | tmp_op = op01; | |
3201 | elem -= n_elts00; | |
3202 | } | |
3203 | } | |
3204 | else | |
3205 | tmp_op = op0; | |
3206 | ||
3207 | vec = rtvec_alloc (1); | |
3208 | RTVEC_ELT (vec, 0) = GEN_INT (elem); | |
3209 | ||
3210 | tmp = gen_rtx_fmt_ee (code, mode, | |
3211 | tmp_op, gen_rtx_PARALLEL (VOIDmode, vec)); | |
3212 | return tmp; | |
3213 | } | |
ed92279c | 3214 | if (GET_CODE (trueop0) == VEC_DUPLICATE |
3215 | && GET_MODE (XEXP (trueop0, 0)) == mode) | |
3216 | return XEXP (trueop0, 0); | |
3b723a04 | 3217 | } |
3218 | else | |
3219 | { | |
3220 | gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0))); | |
3221 | gcc_assert (GET_MODE_INNER (mode) | |
3222 | == GET_MODE_INNER (GET_MODE (trueop0))); | |
3223 | gcc_assert (GET_CODE (trueop1) == PARALLEL); | |
af21a202 | 3224 | |
3b723a04 | 3225 | if (GET_CODE (trueop0) == CONST_VECTOR) |
3226 | { | |
3227 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); | |
3228 | unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); | |
3229 | rtvec v = rtvec_alloc (n_elts); | |
3230 | unsigned int i; | |
af21a202 | 3231 | |
3b723a04 | 3232 | gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts); |
3233 | for (i = 0; i < n_elts; i++) | |
3234 | { | |
3235 | rtx x = XVECEXP (trueop1, 0, i); | |
af21a202 | 3236 | |
971ba038 | 3237 | gcc_assert (CONST_INT_P (x)); |
3b723a04 | 3238 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, |
3239 | INTVAL (x)); | |
af21a202 | 3240 | } |
3241 | ||
3b723a04 | 3242 | return gen_rtx_CONST_VECTOR (mode, v); |
049cadd6 | 3243 | } |
22bcc33d | 3244 | |
3245 | /* If we build {a,b} then permute it, build the result directly. */ | |
3246 | if (XVECLEN (trueop1, 0) == 2 | |
3247 | && CONST_INT_P (XVECEXP (trueop1, 0, 0)) | |
3248 | && CONST_INT_P (XVECEXP (trueop1, 0, 1)) | |
3249 | && GET_CODE (trueop0) == VEC_CONCAT | |
3250 | && GET_CODE (XEXP (trueop0, 0)) == VEC_CONCAT | |
3251 | && GET_MODE (XEXP (trueop0, 0)) == mode | |
3252 | && GET_CODE (XEXP (trueop0, 1)) == VEC_CONCAT | |
3253 | && GET_MODE (XEXP (trueop0, 1)) == mode) | |
3254 | { | |
3255 | unsigned int i0 = INTVAL (XVECEXP (trueop1, 0, 0)); | |
3256 | unsigned int i1 = INTVAL (XVECEXP (trueop1, 0, 1)); | |
3257 | rtx subop0, subop1; | |
3258 | ||
3259 | gcc_assert (i0 < 4 && i1 < 4); | |
3260 | subop0 = XEXP (XEXP (trueop0, i0 / 2), i0 % 2); | |
3261 | subop1 = XEXP (XEXP (trueop0, i1 / 2), i1 % 2); | |
3262 | ||
3263 | return simplify_gen_binary (VEC_CONCAT, mode, subop0, subop1); | |
3264 | } | |
3b723a04 | 3265 | } |
6516cbaf | 3266 | |
3267 | if (XVECLEN (trueop1, 0) == 1 | |
971ba038 | 3268 | && CONST_INT_P (XVECEXP (trueop1, 0, 0)) |
6516cbaf | 3269 | && GET_CODE (trueop0) == VEC_CONCAT) |
3270 | { | |
3271 | rtx vec = trueop0; | |
3272 | int offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode); | |
3273 | ||
3274 | /* Try to find the element in the VEC_CONCAT. */ | |
3275 | while (GET_MODE (vec) != mode | |
3276 | && GET_CODE (vec) == VEC_CONCAT) | |
3277 | { | |
3278 | HOST_WIDE_INT vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); | |
3279 | if (offset < vec_size) | |
3280 | vec = XEXP (vec, 0); | |
3281 | else | |
3282 | { | |
3283 | offset -= vec_size; | |
3284 | vec = XEXP (vec, 1); | |
3285 | } | |
3286 | vec = avoid_constant_pool_reference (vec); | |
3287 | } | |
3288 | ||
3289 | if (GET_MODE (vec) == mode) | |
3290 | return vec; | |
3291 | } | |
3292 | ||
3b723a04 | 3293 | return 0; |
3294 | case VEC_CONCAT: | |
3295 | { | |
3296 | enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode | |
3297 | ? GET_MODE (trueop0) | |
3298 | : GET_MODE_INNER (mode)); | |
3299 | enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode | |
3300 | ? GET_MODE (trueop1) | |
3301 | : GET_MODE_INNER (mode)); | |
3302 | ||
3303 | gcc_assert (VECTOR_MODE_P (mode)); | |
3304 | gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode) | |
3305 | == GET_MODE_SIZE (mode)); | |
3306 | ||
3307 | if (VECTOR_MODE_P (op0_mode)) | |
3308 | gcc_assert (GET_MODE_INNER (mode) | |
3309 | == GET_MODE_INNER (op0_mode)); | |
3310 | else | |
3311 | gcc_assert (GET_MODE_INNER (mode) == op0_mode); | |
af21a202 | 3312 | |
3b723a04 | 3313 | if (VECTOR_MODE_P (op1_mode)) |
3314 | gcc_assert (GET_MODE_INNER (mode) | |
3315 | == GET_MODE_INNER (op1_mode)); | |
3316 | else | |
3317 | gcc_assert (GET_MODE_INNER (mode) == op1_mode); | |
3318 | ||
3319 | if ((GET_CODE (trueop0) == CONST_VECTOR | |
971ba038 | 3320 | || CONST_INT_P (trueop0) |
3b723a04 | 3321 | || GET_CODE (trueop0) == CONST_DOUBLE) |
3322 | && (GET_CODE (trueop1) == CONST_VECTOR | |
971ba038 | 3323 | || CONST_INT_P (trueop1) |
3b723a04 | 3324 | || GET_CODE (trueop1) == CONST_DOUBLE)) |
3325 | { | |
3326 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); | |
3327 | unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); | |
3328 | rtvec v = rtvec_alloc (n_elts); | |
3329 | unsigned int i; | |
3330 | unsigned in_n_elts = 1; | |
fa5cf47b | 3331 | |
3b723a04 | 3332 | if (VECTOR_MODE_P (op0_mode)) |
3333 | in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size); | |
3334 | for (i = 0; i < n_elts; i++) | |
3335 | { | |
3336 | if (i < in_n_elts) | |
3337 | { | |
3338 | if (!VECTOR_MODE_P (op0_mode)) | |
3339 | RTVEC_ELT (v, i) = trueop0; | |
3340 | else | |
3341 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i); | |
3342 | } | |
3343 | else | |
3344 | { | |
3345 | if (!VECTOR_MODE_P (op1_mode)) | |
3346 | RTVEC_ELT (v, i) = trueop1; | |
3347 | else | |
3348 | RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1, | |
3349 | i - in_n_elts); | |
3350 | } | |
3351 | } | |
af21a202 | 3352 | |
3b723a04 | 3353 | return gen_rtx_CONST_VECTOR (mode, v); |
3354 | } | |
3355 | } | |
3356 | return 0; | |
af21a202 | 3357 | |
3b723a04 | 3358 | default: |
3359 | gcc_unreachable (); | |
3360 | } | |
af21a202 | 3361 | |
3b723a04 | 3362 | return 0; |
3363 | } | |
af21a202 | 3364 | |
3b723a04 | 3365 | rtx |
3366 | simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode, | |
3367 | rtx op0, rtx op1) | |
3368 | { | |
3369 | HOST_WIDE_INT arg0, arg1, arg0s, arg1s; | |
3370 | HOST_WIDE_INT val; | |
ded805e6 | 3371 | unsigned int width = GET_MODE_PRECISION (mode); |
af21a202 | 3372 | |
3b723a04 | 3373 | if (VECTOR_MODE_P (mode) |
3374 | && code != VEC_CONCAT | |
3375 | && GET_CODE (op0) == CONST_VECTOR | |
3376 | && GET_CODE (op1) == CONST_VECTOR) | |
3377 | { | |
3378 | unsigned n_elts = GET_MODE_NUNITS (mode); | |
3379 | enum machine_mode op0mode = GET_MODE (op0); | |
3380 | unsigned op0_n_elts = GET_MODE_NUNITS (op0mode); | |
3381 | enum machine_mode op1mode = GET_MODE (op1); | |
3382 | unsigned op1_n_elts = GET_MODE_NUNITS (op1mode); | |
3383 | rtvec v = rtvec_alloc (n_elts); | |
3384 | unsigned int i; | |
af21a202 | 3385 | |
3b723a04 | 3386 | gcc_assert (op0_n_elts == n_elts); |
3387 | gcc_assert (op1_n_elts == n_elts); | |
3388 | for (i = 0; i < n_elts; i++) | |
3389 | { | |
3390 | rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode), | |
3391 | CONST_VECTOR_ELT (op0, i), | |
3392 | CONST_VECTOR_ELT (op1, i)); | |
3393 | if (!x) | |
3394 | return 0; | |
3395 | RTVEC_ELT (v, i) = x; | |
3396 | } | |
af21a202 | 3397 | |
3b723a04 | 3398 | return gen_rtx_CONST_VECTOR (mode, v); |
3399 | } | |
af21a202 | 3400 | |
3b723a04 | 3401 | if (VECTOR_MODE_P (mode) |
3402 | && code == VEC_CONCAT | |
72412d4b | 3403 | && (CONST_INT_P (op0) |
3404 | || GET_CODE (op0) == CONST_DOUBLE | |
3405 | || GET_CODE (op0) == CONST_FIXED) | |
3406 | && (CONST_INT_P (op1) | |
3407 | || GET_CODE (op1) == CONST_DOUBLE | |
3408 | || GET_CODE (op1) == CONST_FIXED)) | |
3b723a04 | 3409 | { |
3410 | unsigned n_elts = GET_MODE_NUNITS (mode); | |
3411 | rtvec v = rtvec_alloc (n_elts); | |
af21a202 | 3412 | |
3b723a04 | 3413 | gcc_assert (n_elts >= 2); |
3414 | if (n_elts == 2) | |
3415 | { | |
3416 | gcc_assert (GET_CODE (op0) != CONST_VECTOR); | |
3417 | gcc_assert (GET_CODE (op1) != CONST_VECTOR); | |
049cadd6 | 3418 | |
3b723a04 | 3419 | RTVEC_ELT (v, 0) = op0; |
3420 | RTVEC_ELT (v, 1) = op1; | |
3421 | } | |
3422 | else | |
3423 | { | |
3424 | unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (op0)); | |
3425 | unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (op1)); | |
3426 | unsigned i; | |
af21a202 | 3427 | |
3b723a04 | 3428 | gcc_assert (GET_CODE (op0) == CONST_VECTOR); |
3429 | gcc_assert (GET_CODE (op1) == CONST_VECTOR); | |
3430 | gcc_assert (op0_n_elts + op1_n_elts == n_elts); | |
af21a202 | 3431 | |
3b723a04 | 3432 | for (i = 0; i < op0_n_elts; ++i) |
3433 | RTVEC_ELT (v, i) = XVECEXP (op0, 0, i); | |
3434 | for (i = 0; i < op1_n_elts; ++i) | |
3435 | RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i); | |
3436 | } | |
502bc734 | 3437 | |
3b723a04 | 3438 | return gen_rtx_CONST_VECTOR (mode, v); |
3439 | } | |
af21a202 | 3440 | |
cee7491d | 3441 | if (SCALAR_FLOAT_MODE_P (mode) |
3b723a04 | 3442 | && GET_CODE (op0) == CONST_DOUBLE |
3443 | && GET_CODE (op1) == CONST_DOUBLE | |
3444 | && mode == GET_MODE (op0) && mode == GET_MODE (op1)) | |
3445 | { | |
3446 | if (code == AND | |
3447 | || code == IOR | |
3448 | || code == XOR) | |
3449 | { | |
3450 | long tmp0[4]; | |
3451 | long tmp1[4]; | |
3452 | REAL_VALUE_TYPE r; | |
3453 | int i; | |
a3715b00 | 3454 | |
3b723a04 | 3455 | real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0), |
3456 | GET_MODE (op0)); | |
3457 | real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1), | |
3458 | GET_MODE (op1)); | |
3459 | for (i = 0; i < 4; i++) | |
a3715b00 | 3460 | { |
3b723a04 | 3461 | switch (code) |
3462 | { | |
3463 | case AND: | |
3464 | tmp0[i] &= tmp1[i]; | |
3465 | break; | |
3466 | case IOR: | |
3467 | tmp0[i] |= tmp1[i]; | |
3468 | break; | |
3469 | case XOR: | |
3470 | tmp0[i] ^= tmp1[i]; | |
3471 | break; | |
3472 | default: | |
3473 | gcc_unreachable (); | |
3474 | } | |
a3715b00 | 3475 | } |
3b723a04 | 3476 | real_from_target (&r, tmp0, mode); |
3477 | return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); | |
3478 | } | |
3479 | else | |
3480 | { | |
3481 | REAL_VALUE_TYPE f0, f1, value, result; | |
3482 | bool inexact; | |
a3715b00 | 3483 | |
3b723a04 | 3484 | REAL_VALUE_FROM_CONST_DOUBLE (f0, op0); |
3485 | REAL_VALUE_FROM_CONST_DOUBLE (f1, op1); | |
3486 | real_convert (&f0, mode, &f0); | |
3487 | real_convert (&f1, mode, &f1); | |
0717ec39 | 3488 | |
3b723a04 | 3489 | if (HONOR_SNANS (mode) |
3490 | && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) | |
3491 | return 0; | |
af21a202 | 3492 | |
3b723a04 | 3493 | if (code == DIV |
3494 | && REAL_VALUES_EQUAL (f1, dconst0) | |
3495 | && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) | |
3496 | return 0; | |
af21a202 | 3497 | |
3b723a04 | 3498 | if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) |
3499 | && flag_trapping_math | |
3500 | && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) | |
af21a202 | 3501 | { |
3b723a04 | 3502 | int s0 = REAL_VALUE_NEGATIVE (f0); |
3503 | int s1 = REAL_VALUE_NEGATIVE (f1); | |
af21a202 | 3504 | |
3b723a04 | 3505 | switch (code) |
90fc95ee | 3506 | { |
3b723a04 | 3507 | case PLUS: |
3508 | /* Inf + -Inf = NaN plus exception. */ | |
3509 | if (s0 != s1) | |
3510 | return 0; | |
3511 | break; | |
3512 | case MINUS: | |
3513 | /* Inf - Inf = NaN plus exception. */ | |
3514 | if (s0 == s1) | |
3515 | return 0; | |
3516 | break; | |
3517 | case DIV: | |
3518 | /* Inf / Inf = NaN plus exception. */ | |
3519 | return 0; | |
3520 | default: | |
3521 | break; | |
af21a202 | 3522 | } |
3523 | } | |
af21a202 | 3524 | |
3b723a04 | 3525 | if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) |
3526 | && flag_trapping_math | |
3527 | && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0)) | |
3528 | || (REAL_VALUE_ISINF (f1) | |
3529 | && REAL_VALUES_EQUAL (f0, dconst0)))) | |
3530 | /* Inf * 0 = NaN plus exception. */ | |
3531 | return 0; | |
a7e82922 | 3532 | |
3b723a04 | 3533 | inexact = real_arithmetic (&value, rtx_to_tree_code (code), |
3534 | &f0, &f1); | |
3535 | real_convert (&result, mode, &value); | |
04e579b6 | 3536 | |
f2e0dda3 | 3537 | /* Don't constant fold this floating point operation if |
3538 | the result has overflowed and flag_trapping_math. */ | |
3539 | ||
3540 | if (flag_trapping_math | |
3541 | && MODE_HAS_INFINITIES (mode) | |
3542 | && REAL_VALUE_ISINF (result) | |
3543 | && !REAL_VALUE_ISINF (f0) | |
3544 | && !REAL_VALUE_ISINF (f1)) | |
3545 | /* Overflow plus exception. */ | |
3546 | return 0; | |
3547 | ||
3b723a04 | 3548 | /* Don't constant fold this floating point operation if the |
3549 | result may dependent upon the run-time rounding mode and | |
3550 | flag_rounding_math is set, or if GCC's software emulation | |
3551 | is unable to accurately represent the result. */ | |
a7e82922 | 3552 | |
3b723a04 | 3553 | if ((flag_rounding_math |
f2b38121 | 3554 | || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations)) |
3b723a04 | 3555 | && (inexact || !real_identical (&result, &value))) |
3556 | return NULL_RTX; | |
b649c04e | 3557 | |
3b723a04 | 3558 | return CONST_DOUBLE_FROM_REAL_VALUE (result, mode); |
af21a202 | 3559 | } |
af21a202 | 3560 | } |
3561 | ||
3b723a04 | 3562 | /* We can fold some multi-word operations. */ |
3563 | if (GET_MODE_CLASS (mode) == MODE_INT | |
90739616 | 3564 | && width == HOST_BITS_PER_DOUBLE_INT |
3565 | && (CONST_DOUBLE_P (op0) || CONST_INT_P (op0)) | |
3566 | && (CONST_DOUBLE_P (op1) || CONST_INT_P (op1))) | |
3b723a04 | 3567 | { |
90739616 | 3568 | double_int o0, o1, res, tmp; |
af21a202 | 3569 | |
90739616 | 3570 | o0 = rtx_to_double_int (op0); |
3571 | o1 = rtx_to_double_int (op1); | |
af21a202 | 3572 | |
3b723a04 | 3573 | switch (code) |
3574 | { | |
3575 | case MINUS: | |
3576 | /* A - B == A + (-B). */ | |
90739616 | 3577 | o1 = double_int_neg (o1); |
af21a202 | 3578 | |
3b723a04 | 3579 | /* Fall through.... */ |
af21a202 | 3580 | |
3b723a04 | 3581 | case PLUS: |
90739616 | 3582 | res = double_int_add (o0, o1); |
3b723a04 | 3583 | break; |
af21a202 | 3584 | |
3b723a04 | 3585 | case MULT: |
90739616 | 3586 | res = double_int_mul (o0, o1); |
3b723a04 | 3587 | break; |
af21a202 | 3588 | |
3b723a04 | 3589 | case DIV: |
90739616 | 3590 | if (div_and_round_double (TRUNC_DIV_EXPR, 0, |
3591 | o0.low, o0.high, o1.low, o1.high, | |
3592 | &res.low, &res.high, | |
3593 | &tmp.low, &tmp.high)) | |
3b723a04 | 3594 | return 0; |
3595 | break; | |
af21a202 | 3596 | |
3b723a04 | 3597 | case MOD: |
90739616 | 3598 | if (div_and_round_double (TRUNC_DIV_EXPR, 0, |
3599 | o0.low, o0.high, o1.low, o1.high, | |
3600 | &tmp.low, &tmp.high, | |
3601 | &res.low, &res.high)) | |
3b723a04 | 3602 | return 0; |
3603 | break; | |
af21a202 | 3604 | |
3b723a04 | 3605 | case UDIV: |
90739616 | 3606 | if (div_and_round_double (TRUNC_DIV_EXPR, 1, |
3607 | o0.low, o0.high, o1.low, o1.high, | |
3608 | &res.low, &res.high, | |
3609 | &tmp.low, &tmp.high)) | |
3b723a04 | 3610 | return 0; |
3611 | break; | |
af21a202 | 3612 | |
3b723a04 | 3613 | case UMOD: |
90739616 | 3614 | if (div_and_round_double (TRUNC_DIV_EXPR, 1, |
3615 | o0.low, o0.high, o1.low, o1.high, | |
3616 | &tmp.low, &tmp.high, | |
3617 | &res.low, &res.high)) | |
3b723a04 | 3618 | return 0; |
3619 | break; | |
af21a202 | 3620 | |
3b723a04 | 3621 | case AND: |
90739616 | 3622 | res = double_int_and (o0, o1); |
3b723a04 | 3623 | break; |
af21a202 | 3624 | |
3b723a04 | 3625 | case IOR: |
90739616 | 3626 | res = double_int_ior (o0, o1); |
3b723a04 | 3627 | break; |
af21a202 | 3628 | |
3b723a04 | 3629 | case XOR: |
90739616 | 3630 | res = double_int_xor (o0, o1); |
3b723a04 | 3631 | break; |
af21a202 | 3632 | |
3b723a04 | 3633 | case SMIN: |
90739616 | 3634 | res = double_int_smin (o0, o1); |
3b723a04 | 3635 | break; |
af21a202 | 3636 | |
3b723a04 | 3637 | case SMAX: |
90739616 | 3638 | res = double_int_smax (o0, o1); |
3b723a04 | 3639 | break; |
af21a202 | 3640 | |
3b723a04 | 3641 | case UMIN: |
90739616 | 3642 | res = double_int_umin (o0, o1); |
3b723a04 | 3643 | break; |
af21a202 | 3644 | |
3b723a04 | 3645 | case UMAX: |
90739616 | 3646 | res = double_int_umax (o0, o1); |
3b723a04 | 3647 | break; |
af21a202 | 3648 | |
3b723a04 | 3649 | case LSHIFTRT: case ASHIFTRT: |
3650 | case ASHIFT: | |
3651 | case ROTATE: case ROTATERT: | |
90739616 | 3652 | { |
3653 | unsigned HOST_WIDE_INT cnt; | |
3654 | ||
3655 | if (SHIFT_COUNT_TRUNCATED) | |
ded805e6 | 3656 | o1 = double_int_zext (o1, GET_MODE_PRECISION (mode)); |
90739616 | 3657 | |
3658 | if (!double_int_fits_in_uhwi_p (o1) | |
ded805e6 | 3659 | || double_int_to_uhwi (o1) >= GET_MODE_PRECISION (mode)) |
90739616 | 3660 | return 0; |
3661 | ||
3662 | cnt = double_int_to_uhwi (o1); | |
3663 | ||
3664 | if (code == LSHIFTRT || code == ASHIFTRT) | |
ded805e6 | 3665 | res = double_int_rshift (o0, cnt, GET_MODE_PRECISION (mode), |
90739616 | 3666 | code == ASHIFTRT); |
3667 | else if (code == ASHIFT) | |
ded805e6 | 3668 | res = double_int_lshift (o0, cnt, GET_MODE_PRECISION (mode), |
90739616 | 3669 | true); |
3670 | else if (code == ROTATE) | |
ded805e6 | 3671 | res = double_int_lrotate (o0, cnt, GET_MODE_PRECISION (mode)); |
90739616 | 3672 | else /* code == ROTATERT */ |
ded805e6 | 3673 | res = double_int_rrotate (o0, cnt, GET_MODE_PRECISION (mode)); |
90739616 | 3674 | } |
3b723a04 | 3675 | break; |
af21a202 | 3676 | |
3b723a04 | 3677 | default: |
3678 | return 0; | |
3679 | } | |
af21a202 | 3680 | |
90739616 | 3681 | return immed_double_int_const (res, mode); |
3b723a04 | 3682 | } |
af21a202 | 3683 | |
971ba038 | 3684 | if (CONST_INT_P (op0) && CONST_INT_P (op1) |
3b723a04 | 3685 | && width <= HOST_BITS_PER_WIDE_INT && width != 0) |
3686 | { | |
3687 | /* Get the integer argument values in two forms: | |
3688 | zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S. */ | |
af21a202 | 3689 | |
3b723a04 | 3690 | arg0 = INTVAL (op0); |
3691 | arg1 = INTVAL (op1); | |
af21a202 | 3692 | |
3b723a04 | 3693 | if (width < HOST_BITS_PER_WIDE_INT) |
3694 | { | |
f92430e0 | 3695 | arg0 &= GET_MODE_MASK (mode); |
3696 | arg1 &= GET_MODE_MASK (mode); | |
af21a202 | 3697 | |
3b723a04 | 3698 | arg0s = arg0; |
f92430e0 | 3699 | if (val_signbit_known_set_p (mode, arg0s)) |
3700 | arg0s |= ~GET_MODE_MASK (mode); | |
7b5a33a4 | 3701 | |
f92430e0 | 3702 | arg1s = arg1; |
3703 | if (val_signbit_known_set_p (mode, arg1s)) | |
3704 | arg1s |= ~GET_MODE_MASK (mode); | |
3b723a04 | 3705 | } |
3706 | else | |
3707 | { | |
3708 | arg0s = arg0; | |
3709 | arg1s = arg1; | |
3710 | } | |
48e1416a | 3711 | |
3b723a04 | 3712 | /* Compute the value of the arithmetic. */ |
48e1416a | 3713 | |
3b723a04 | 3714 | switch (code) |
3715 | { | |
3716 | case PLUS: | |
3717 | val = arg0s + arg1s; | |
3718 | break; | |
48e1416a | 3719 | |
3b723a04 | 3720 | case MINUS: |
3721 | val = arg0s - arg1s; | |
3722 | break; | |
48e1416a | 3723 | |
3b723a04 | 3724 | case MULT: |
3725 | val = arg0s * arg1s; | |
3726 | break; | |
48e1416a | 3727 | |
3b723a04 | 3728 | case DIV: |
3729 | if (arg1s == 0 | |
23423d0e | 3730 | || ((unsigned HOST_WIDE_INT) arg0s |
3731 | == (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) | |
3b723a04 | 3732 | && arg1s == -1)) |
3733 | return 0; | |
3734 | val = arg0s / arg1s; | |
3735 | break; | |
48e1416a | 3736 | |
3b723a04 | 3737 | case MOD: |
3738 | if (arg1s == 0 | |
23423d0e | 3739 | || ((unsigned HOST_WIDE_INT) arg0s |
3740 | == (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) | |
3b723a04 | 3741 | && arg1s == -1)) |
3742 | return 0; | |
3743 | val = arg0s % arg1s; | |
3744 | break; | |
48e1416a | 3745 | |
3b723a04 | 3746 | case UDIV: |
3747 | if (arg1 == 0 | |
23423d0e | 3748 | || ((unsigned HOST_WIDE_INT) arg0s |
3749 | == (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) | |
3b723a04 | 3750 | && arg1s == -1)) |
3751 | return 0; | |
3752 | val = (unsigned HOST_WIDE_INT) arg0 / arg1; | |
3753 | break; | |
48e1416a | 3754 | |
3b723a04 | 3755 | case UMOD: |
3756 | if (arg1 == 0 | |
23423d0e | 3757 | || ((unsigned HOST_WIDE_INT) arg0s |
3758 | == (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1) | |
3b723a04 | 3759 | && arg1s == -1)) |
3760 | return 0; | |
3761 | val = (unsigned HOST_WIDE_INT) arg0 % arg1; | |
3762 | break; | |
48e1416a | 3763 | |
3b723a04 | 3764 | case AND: |
3765 | val = arg0 & arg1; | |
3766 | break; | |
48e1416a | 3767 | |
3b723a04 | 3768 | case IOR: |
3769 | val = arg0 | arg1; | |
3770 | break; | |
48e1416a | 3771 | |
3b723a04 | 3772 | case XOR: |
3773 | val = arg0 ^ arg1; | |
3774 | break; | |
48e1416a | 3775 | |
3b723a04 | 3776 | case LSHIFTRT: |
3777 | case ASHIFT: | |
3778 | case ASHIFTRT: | |
3779 | /* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure | |
3780 | the value is in range. We can't return any old value for | |
3781 | out-of-range arguments because either the middle-end (via | |
3782 | shift_truncation_mask) or the back-end might be relying on | |
3783 | target-specific knowledge. Nor can we rely on | |
3784 | shift_truncation_mask, since the shift might not be part of an | |
3785 | ashlM3, lshrM3 or ashrM3 instruction. */ | |
3786 | if (SHIFT_COUNT_TRUNCATED) | |
b3003238 | 3787 | arg1 = (unsigned HOST_WIDE_INT) arg1 % width; |
3788 | else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode)) | |
3b723a04 | 3789 | return 0; |
48e1416a | 3790 | |
3b723a04 | 3791 | val = (code == ASHIFT |
3792 | ? ((unsigned HOST_WIDE_INT) arg0) << arg1 | |
3793 | : ((unsigned HOST_WIDE_INT) arg0) >> arg1); | |
48e1416a | 3794 | |
3b723a04 | 3795 | /* Sign-extend the result for arithmetic right shifts. */ |
3796 | if (code == ASHIFTRT && arg0s < 0 && arg1 > 0) | |
23423d0e | 3797 | val |= ((unsigned HOST_WIDE_INT) (-1)) << (width - arg1); |
3b723a04 | 3798 | break; |
48e1416a | 3799 | |
3b723a04 | 3800 | case ROTATERT: |
3801 | if (arg1 < 0) | |
3802 | return 0; | |
48e1416a | 3803 | |
3b723a04 | 3804 | arg1 %= width; |
3805 | val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1)) | |
3806 | | (((unsigned HOST_WIDE_INT) arg0) >> arg1)); | |
3807 | break; | |
48e1416a | 3808 | |
3b723a04 | 3809 | case ROTATE: |
3810 | if (arg1 < 0) | |
3811 | return 0; | |
48e1416a | 3812 | |
3b723a04 | 3813 | arg1 %= width; |
3814 | val = ((((unsigned HOST_WIDE_INT) arg0) << arg1) | |
3815 | | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1))); | |
3816 | break; | |
48e1416a | 3817 | |
3b723a04 | 3818 | case COMPARE: |
3819 | /* Do nothing here. */ | |
3820 | return 0; | |
48e1416a | 3821 | |
3b723a04 | 3822 | case SMIN: |
3823 | val = arg0s <= arg1s ? arg0s : arg1s; | |
3824 | break; | |
48e1416a | 3825 | |
3b723a04 | 3826 | case UMIN: |
3827 | val = ((unsigned HOST_WIDE_INT) arg0 | |
3828 | <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); | |
3829 | break; | |
48e1416a | 3830 | |
3b723a04 | 3831 | case SMAX: |
3832 | val = arg0s > arg1s ? arg0s : arg1s; | |
3833 | break; | |
48e1416a | 3834 | |
3b723a04 | 3835 | case UMAX: |
3836 | val = ((unsigned HOST_WIDE_INT) arg0 | |
3837 | > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); | |
3838 | break; | |
48e1416a | 3839 | |
3b723a04 | 3840 | case SS_PLUS: |
3841 | case US_PLUS: | |
3842 | case SS_MINUS: | |
3843 | case US_MINUS: | |
b563b483 | 3844 | case SS_MULT: |
3845 | case US_MULT: | |
3846 | case SS_DIV: | |
3847 | case US_DIV: | |
719ee5e5 | 3848 | case SS_ASHIFT: |
b563b483 | 3849 | case US_ASHIFT: |
3b723a04 | 3850 | /* ??? There are simplifications that can be done. */ |
3851 | return 0; | |
48e1416a | 3852 | |
3b723a04 | 3853 | default: |
3854 | gcc_unreachable (); | |
3855 | } | |
af21a202 | 3856 | |
69e41517 | 3857 | return gen_int_mode (val, mode); |
3b723a04 | 3858 | } |
af21a202 | 3859 | |
3b723a04 | 3860 | return NULL_RTX; |
af21a202 | 3861 | } |
3b723a04 | 3862 | |
3863 | ||
af21a202 | 3864 | \f |
3865 | /* Simplify a PLUS or MINUS, at least one of whose operands may be another | |
3866 | PLUS or MINUS. | |
3867 | ||
3868 | Rather than test for specific case, we do this by a brute-force method | |
3869 | and do all possible simplifications until no more changes occur. Then | |
e9480a59 | 3870 | we rebuild the operation. */ |
af21a202 | 3871 | |
f4ad60b7 | 3872 | struct simplify_plus_minus_op_data |
3873 | { | |
3874 | rtx op; | |
31bf99ef | 3875 | short neg; |
f4ad60b7 | 3876 | }; |
3877 | ||
1f3b83af | 3878 | static bool |
3879 | simplify_plus_minus_op_data_cmp (rtx x, rtx y) | |
f4ad60b7 | 3880 | { |
31bf99ef | 3881 | int result; |
f4ad60b7 | 3882 | |
1f3b83af | 3883 | result = (commutative_operand_precedence (y) |
3884 | - commutative_operand_precedence (x)); | |
31bf99ef | 3885 | if (result) |
1f3b83af | 3886 | return result > 0; |
8d7243cc | 3887 | |
3888 | /* Group together equal REGs to do more simplification. */ | |
1f3b83af | 3889 | if (REG_P (x) && REG_P (y)) |
3890 | return REGNO (x) > REGNO (y); | |
8d7243cc | 3891 | else |
1f3b83af | 3892 | return false; |
f4ad60b7 | 3893 | } |
3894 | ||
af21a202 | 3895 | static rtx |
60b8c5b3 | 3896 | simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0, |
e9480a59 | 3897 | rtx op1) |
af21a202 | 3898 | { |
f4ad60b7 | 3899 | struct simplify_plus_minus_op_data ops[8]; |
af21a202 | 3900 | rtx result, tem; |
e0ea7483 | 3901 | int n_ops = 2, input_ops = 2; |
8d7243cc | 3902 | int changed, n_constants = 0, canonicalized = 0; |
af21a202 | 3903 | int i, j; |
3904 | ||
f0af5a88 | 3905 | memset (ops, 0, sizeof ops); |
40734805 | 3906 | |
af21a202 | 3907 | /* Set up the two operands and then expand them until nothing has been |
3908 | changed. If we run out of room in our array, give up; this should | |
3909 | almost never happen. */ | |
3910 | ||
f4ad60b7 | 3911 | ops[0].op = op0; |
3912 | ops[0].neg = 0; | |
3913 | ops[1].op = op1; | |
3914 | ops[1].neg = (code == MINUS); | |
af21a202 | 3915 | |
f4ad60b7 | 3916 | do |
af21a202 | 3917 | { |
3918 | changed = 0; | |
3919 | ||
3920 | for (i = 0; i < n_ops; i++) | |
f4ad60b7 | 3921 | { |
3922 | rtx this_op = ops[i].op; | |
3923 | int this_neg = ops[i].neg; | |
3924 | enum rtx_code this_code = GET_CODE (this_op); | |
af21a202 | 3925 | |
f4ad60b7 | 3926 | switch (this_code) |
3927 | { | |
3928 | case PLUS: | |
3929 | case MINUS: | |
3930 | if (n_ops == 7) | |
907bb1cf | 3931 | return NULL_RTX; |
af21a202 | 3932 | |
f4ad60b7 | 3933 | ops[n_ops].op = XEXP (this_op, 1); |
3934 | ops[n_ops].neg = (this_code == MINUS) ^ this_neg; | |
3935 | n_ops++; | |
3936 | ||
3937 | ops[i].op = XEXP (this_op, 0); | |
3938 | input_ops++; | |
3939 | changed = 1; | |
e9480a59 | 3940 | canonicalized |= this_neg; |
f4ad60b7 | 3941 | break; |
3942 | ||
3943 | case NEG: | |
3944 | ops[i].op = XEXP (this_op, 0); | |
3945 | ops[i].neg = ! this_neg; | |
3946 | changed = 1; | |
e9480a59 | 3947 | canonicalized = 1; |
f4ad60b7 | 3948 | break; |
3949 | ||
3950 | case CONST: | |
fac6aae6 | 3951 | if (n_ops < 7 |
3952 | && GET_CODE (XEXP (this_op, 0)) == PLUS | |
3953 | && CONSTANT_P (XEXP (XEXP (this_op, 0), 0)) | |
3954 | && CONSTANT_P (XEXP (XEXP (this_op, 0), 1))) | |
3955 | { | |
3956 | ops[i].op = XEXP (XEXP (this_op, 0), 0); | |
3957 | ops[n_ops].op = XEXP (XEXP (this_op, 0), 1); | |
3958 | ops[n_ops].neg = this_neg; | |
3959 | n_ops++; | |
fac6aae6 | 3960 | changed = 1; |
e9480a59 | 3961 | canonicalized = 1; |
fac6aae6 | 3962 | } |
f4ad60b7 | 3963 | break; |
3964 | ||
3965 | case NOT: | |
3966 | /* ~a -> (-a - 1) */ | |
3967 | if (n_ops != 7) | |
3968 | { | |
3e527904 | 3969 | ops[n_ops].op = CONSTM1_RTX (mode); |
d2100772 | 3970 | ops[n_ops++].neg = this_neg; |
f4ad60b7 | 3971 | ops[i].op = XEXP (this_op, 0); |
3972 | ops[i].neg = !this_neg; | |
3973 | changed = 1; | |
e9480a59 | 3974 | canonicalized = 1; |
f4ad60b7 | 3975 | } |
3976 | break; | |
af21a202 | 3977 | |
f4ad60b7 | 3978 | case CONST_INT: |
8d7243cc | 3979 | n_constants++; |
f4ad60b7 | 3980 | if (this_neg) |
3981 | { | |
7d6080d6 | 3982 | ops[i].op = neg_const_int (mode, this_op); |
f4ad60b7 | 3983 | ops[i].neg = 0; |
3984 | changed = 1; | |
e9480a59 | 3985 | canonicalized = 1; |
f4ad60b7 | 3986 | } |
3987 | break; | |
af21a202 | 3988 | |
f4ad60b7 | 3989 | default: |
3990 | break; | |
3991 | } | |
3992 | } | |
af21a202 | 3993 | } |
f4ad60b7 | 3994 | while (changed); |
af21a202 | 3995 | |
8d7243cc | 3996 | if (n_constants > 1) |
3997 | canonicalized = 1; | |
e0ea7483 | 3998 | |
8d7243cc | 3999 | gcc_assert (n_ops >= 2); |
af21a202 | 4000 | |
e9480a59 | 4001 | /* If we only have two operands, we can avoid the loops. */ |
4002 | if (n_ops == 2) | |
4003 | { | |
4004 | enum rtx_code code = ops[0].neg || ops[1].neg ? MINUS : PLUS; | |
4005 | rtx lhs, rhs; | |
4006 | ||
4007 | /* Get the two operands. Be careful with the order, especially for | |
4008 | the cases where code == MINUS. */ | |
4009 | if (ops[0].neg && ops[1].neg) | |
4010 | { | |
4011 | lhs = gen_rtx_NEG (mode, ops[0].op); | |
4012 | rhs = ops[1].op; | |
4013 | } | |
4014 | else if (ops[0].neg) | |
4015 | { | |
4016 | lhs = ops[1].op; | |
4017 | rhs = ops[0].op; | |
4018 | } | |
4019 | else | |
4020 | { | |
4021 | lhs = ops[0].op; | |
4022 | rhs = ops[1].op; | |
4023 | } | |
4024 | ||
4025 | return simplify_const_binary_operation (code, mode, lhs, rhs); | |
4026 | } | |
4027 | ||
8d7243cc | 4028 | /* Now simplify each pair of operands until nothing changes. */ |
f4ad60b7 | 4029 | do |
af21a202 | 4030 | { |
8d7243cc | 4031 | /* Insertion sort is good enough for an eight-element array. */ |
4032 | for (i = 1; i < n_ops; i++) | |
4033 | { | |
4034 | struct simplify_plus_minus_op_data save; | |
4035 | j = i - 1; | |
1f3b83af | 4036 | if (!simplify_plus_minus_op_data_cmp (ops[j].op, ops[i].op)) |
8d7243cc | 4037 | continue; |
4038 | ||
4039 | canonicalized = 1; | |
4040 | save = ops[i]; | |
4041 | do | |
4042 | ops[j + 1] = ops[j]; | |
1f3b83af | 4043 | while (j-- && simplify_plus_minus_op_data_cmp (ops[j].op, save.op)); |
8d7243cc | 4044 | ops[j + 1] = save; |
4045 | } | |
af21a202 | 4046 | |
8d7243cc | 4047 | changed = 0; |
4048 | for (i = n_ops - 1; i > 0; i--) | |
4049 | for (j = i - 1; j >= 0; j--) | |
f4ad60b7 | 4050 | { |
8d7243cc | 4051 | rtx lhs = ops[j].op, rhs = ops[i].op; |
4052 | int lneg = ops[j].neg, rneg = ops[i].neg; | |
af21a202 | 4053 | |
8d7243cc | 4054 | if (lhs != 0 && rhs != 0) |
f4ad60b7 | 4055 | { |
4056 | enum rtx_code ncode = PLUS; | |
4057 | ||
4058 | if (lneg != rneg) | |
4059 | { | |
4060 | ncode = MINUS; | |
4061 | if (lneg) | |
4062 | tem = lhs, lhs = rhs, rhs = tem; | |
4063 | } | |
4064 | else if (swap_commutative_operands_p (lhs, rhs)) | |
4065 | tem = lhs, lhs = rhs, rhs = tem; | |
4066 | ||
971ba038 | 4067 | if ((GET_CODE (lhs) == CONST || CONST_INT_P (lhs)) |
4068 | && (GET_CODE (rhs) == CONST || CONST_INT_P (rhs))) | |
dc44b957 | 4069 | { |
4070 | rtx tem_lhs, tem_rhs; | |
4071 | ||
4072 | tem_lhs = GET_CODE (lhs) == CONST ? XEXP (lhs, 0) : lhs; | |
4073 | tem_rhs = GET_CODE (rhs) == CONST ? XEXP (rhs, 0) : rhs; | |
4074 | tem = simplify_binary_operation (ncode, mode, tem_lhs, tem_rhs); | |
f4ad60b7 | 4075 | |
dc44b957 | 4076 | if (tem && !CONSTANT_P (tem)) |
4077 | tem = gen_rtx_CONST (GET_MODE (tem), tem); | |
4078 | } | |
4079 | else | |
4080 | tem = simplify_binary_operation (ncode, mode, lhs, rhs); | |
48e1416a | 4081 | |
40734805 | 4082 | /* Reject "simplifications" that just wrap the two |
f4ad60b7 | 4083 | arguments in a CONST. Failure to do so can result |
4084 | in infinite recursion with simplify_binary_operation | |
4085 | when it calls us to simplify CONST operations. */ | |
4086 | if (tem | |
4087 | && ! (GET_CODE (tem) == CONST | |
4088 | && GET_CODE (XEXP (tem, 0)) == ncode | |
4089 | && XEXP (XEXP (tem, 0), 0) == lhs | |
8d7243cc | 4090 | && XEXP (XEXP (tem, 0), 1) == rhs)) |
f4ad60b7 | 4091 | { |
4092 | lneg &= rneg; | |
4093 | if (GET_CODE (tem) == NEG) | |
4094 | tem = XEXP (tem, 0), lneg = !lneg; | |
971ba038 | 4095 | if (CONST_INT_P (tem) && lneg) |
7d6080d6 | 4096 | tem = neg_const_int (mode, tem), lneg = 0; |
f4ad60b7 | 4097 | |
4098 | ops[i].op = tem; | |
4099 | ops[i].neg = lneg; | |
4100 | ops[j].op = NULL_RTX; | |
4101 | changed = 1; | |
b718fe63 | 4102 | canonicalized = 1; |
f4ad60b7 | 4103 | } |
4104 | } | |
4105 | } | |
af21a202 | 4106 | |
b718fe63 | 4107 | /* If nothing changed, fail. */ |
4108 | if (!canonicalized) | |
4109 | return NULL_RTX; | |
4110 | ||
8d7243cc | 4111 | /* Pack all the operands to the lower-numbered entries. */ |
4112 | for (i = 0, j = 0; j < n_ops; j++) | |
4113 | if (ops[j].op) | |
4114 | { | |
4115 | ops[i] = ops[j]; | |
4116 | i++; | |
4117 | } | |
4118 | n_ops = i; | |
af21a202 | 4119 | } |
f4ad60b7 | 4120 | while (changed); |
af21a202 | 4121 | |
fa5cf47b | 4122 | /* Create (minus -C X) instead of (neg (const (plus X C))). */ |
4123 | if (n_ops == 2 | |
971ba038 | 4124 | && CONST_INT_P (ops[1].op) |
fa5cf47b | 4125 | && CONSTANT_P (ops[0].op) |
4126 | && ops[0].neg) | |
4127 | return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op); | |
48e1416a | 4128 | |
f4ad60b7 | 4129 | /* We suppressed creation of trivial CONST expressions in the |
4130 | combination loop to avoid recursion. Create one manually now. | |
4131 | The combination loop should have ensured that there is exactly | |
4132 | one CONST_INT, and the sort will have ensured that it is last | |
4133 | in the array and that any other constant will be next-to-last. */ | |
af21a202 | 4134 | |
f4ad60b7 | 4135 | if (n_ops > 1 |
971ba038 | 4136 | && CONST_INT_P (ops[n_ops - 1].op) |
f4ad60b7 | 4137 | && CONSTANT_P (ops[n_ops - 2].op)) |
4138 | { | |
7d6080d6 | 4139 | rtx value = ops[n_ops - 1].op; |
ada548c3 | 4140 | if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg) |
7d6080d6 | 4141 | value = neg_const_int (mode, value); |
29c05e22 | 4142 | ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op, |
4143 | INTVAL (value)); | |
f4ad60b7 | 4144 | n_ops--; |
4145 | } | |
4146 | ||
65b62c6f | 4147 | /* Put a non-negated operand first, if possible. */ |
af21a202 | 4148 | |
f4ad60b7 | 4149 | for (i = 0; i < n_ops && ops[i].neg; i++) |
4150 | continue; | |
af21a202 | 4151 | if (i == n_ops) |
65b62c6f | 4152 | ops[0].op = gen_rtx_NEG (mode, ops[0].op); |
af21a202 | 4153 | else if (i != 0) |
4154 | { | |
f4ad60b7 | 4155 | tem = ops[0].op; |
4156 | ops[0] = ops[i]; | |
4157 | ops[i].op = tem; | |
4158 | ops[i].neg = 1; | |
af21a202 | 4159 | } |
4160 | ||
4161 | /* Now make the result by performing the requested operations. */ | |
f4ad60b7 | 4162 | result = ops[0].op; |
af21a202 | 4163 | for (i = 1; i < n_ops; i++) |
f4ad60b7 | 4164 | result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS, |
4165 | mode, result, ops[i].op); | |
af21a202 | 4166 | |
65b62c6f | 4167 | return result; |
af21a202 | 4168 | } |
4169 | ||
70fb5d1c | 4170 | /* Check whether an operand is suitable for calling simplify_plus_minus. */ |
4171 | static bool | |
dd9b9fc5 | 4172 | plus_minus_operand_p (const_rtx x) |
70fb5d1c | 4173 | { |
4174 | return GET_CODE (x) == PLUS | |
4175 | || GET_CODE (x) == MINUS | |
4176 | || (GET_CODE (x) == CONST | |
4177 | && GET_CODE (XEXP (x, 0)) == PLUS | |
4178 | && CONSTANT_P (XEXP (XEXP (x, 0), 0)) | |
4179 | && CONSTANT_P (XEXP (XEXP (x, 0), 1))); | |
4180 | } | |
4181 | ||
af21a202 | 4182 | /* Like simplify_binary_operation except used for relational operators. |
ac503e50 | 4183 | MODE is the mode of the result. If MODE is VOIDmode, both operands must |
7be10878 | 4184 | not also be VOIDmode. |
ac503e50 | 4185 | |
4186 | CMP_MODE specifies in which mode the comparison is done in, so it is | |
4187 | the mode of the operands. If CMP_MODE is VOIDmode, it is taken from | |
4188 | the operands or, if both are VOIDmode, the operands are compared in | |
4189 | "infinite precision". */ | |
4190 | rtx | |
4191 | simplify_relational_operation (enum rtx_code code, enum machine_mode mode, | |
4192 | enum machine_mode cmp_mode, rtx op0, rtx op1) | |
4193 | { | |
4194 | rtx tem, trueop0, trueop1; | |
4195 | ||
4196 | if (cmp_mode == VOIDmode) | |
4197 | cmp_mode = GET_MODE (op0); | |
4198 | if (cmp_mode == VOIDmode) | |
4199 | cmp_mode = GET_MODE (op1); | |
4200 | ||
4201 | tem = simplify_const_relational_operation (code, cmp_mode, op0, op1); | |
4202 | if (tem) | |
4203 | { | |
cee7491d | 4204 | if (SCALAR_FLOAT_MODE_P (mode)) |
ac503e50 | 4205 | { |
4206 | if (tem == const0_rtx) | |
4207 | return CONST0_RTX (mode); | |
7be10878 | 4208 | #ifdef FLOAT_STORE_FLAG_VALUE |
4209 | { | |
4210 | REAL_VALUE_TYPE val; | |
4211 | val = FLOAT_STORE_FLAG_VALUE (mode); | |
4212 | return CONST_DOUBLE_FROM_REAL_VALUE (val, mode); | |
4213 | } | |
4214 | #else | |
4215 | return NULL_RTX; | |
48e1416a | 4216 | #endif |
ac503e50 | 4217 | } |
7be10878 | 4218 | if (VECTOR_MODE_P (mode)) |
4219 | { | |
4220 | if (tem == const0_rtx) | |
4221 | return CONST0_RTX (mode); | |
4222 | #ifdef VECTOR_STORE_FLAG_VALUE | |
4223 | { | |
4224 | int i, units; | |
5b2d8298 | 4225 | rtvec v; |
7be10878 | 4226 | |
4227 | rtx val = VECTOR_STORE_FLAG_VALUE (mode); | |
4228 | if (val == NULL_RTX) | |
4229 | return NULL_RTX; | |
4230 | if (val == const1_rtx) | |
4231 | return CONST1_RTX (mode); | |
4232 | ||
4233 | units = GET_MODE_NUNITS (mode); | |
4234 | v = rtvec_alloc (units); | |
4235 | for (i = 0; i < units; i++) | |
4236 | RTVEC_ELT (v, i) = val; | |
4237 | return gen_rtx_raw_CONST_VECTOR (mode, v); | |
4238 | } | |
4239 | #else | |
4240 | return NULL_RTX; | |
ac503e50 | 4241 | #endif |
7be10878 | 4242 | } |
ac503e50 | 4243 | |
4244 | return tem; | |
4245 | } | |
4246 | ||
4247 | /* For the following tests, ensure const0_rtx is op1. */ | |
4248 | if (swap_commutative_operands_p (op0, op1) | |
4249 | || (op0 == const0_rtx && op1 != const0_rtx)) | |
4250 | tem = op0, op0 = op1, op1 = tem, code = swap_condition (code); | |
4251 | ||
4252 | /* If op0 is a compare, extract the comparison arguments from it. */ | |
4253 | if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) | |
74f4459c | 4254 | return simplify_gen_relational (code, mode, VOIDmode, |
4255 | XEXP (op0, 0), XEXP (op0, 1)); | |
ac503e50 | 4256 | |
3bc6a7ce | 4257 | if (GET_MODE_CLASS (cmp_mode) == MODE_CC |
ac503e50 | 4258 | || CC0_P (op0)) |
4259 | return NULL_RTX; | |
4260 | ||
4261 | trueop0 = avoid_constant_pool_reference (op0); | |
4262 | trueop1 = avoid_constant_pool_reference (op1); | |
4263 | return simplify_relational_operation_1 (code, mode, cmp_mode, | |
4264 | trueop0, trueop1); | |
4265 | } | |
4266 | ||
4267 | /* This part of simplify_relational_operation is only used when CMP_MODE | |
4268 | is not in class MODE_CC (i.e. it is a real comparison). | |
4269 | ||
4270 | MODE is the mode of the result, while CMP_MODE specifies in which | |
4271 | mode the comparison is done in, so it is the mode of the operands. */ | |
fc2ac93a | 4272 | |
4273 | static rtx | |
ac503e50 | 4274 | simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode, |
4275 | enum machine_mode cmp_mode, rtx op0, rtx op1) | |
4276 | { | |
fc2ac93a | 4277 | enum rtx_code op0code = GET_CODE (op0); |
4278 | ||
b114d7da | 4279 | if (op1 == const0_rtx && COMPARISON_P (op0)) |
ac503e50 | 4280 | { |
b114d7da | 4281 | /* If op0 is a comparison, extract the comparison arguments |
4282 | from it. */ | |
4283 | if (code == NE) | |
ac503e50 | 4284 | { |
b114d7da | 4285 | if (GET_MODE (op0) == mode) |
4286 | return simplify_rtx (op0); | |
4287 | else | |
4288 | return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode, | |
4289 | XEXP (op0, 0), XEXP (op0, 1)); | |
4290 | } | |
4291 | else if (code == EQ) | |
4292 | { | |
4293 | enum rtx_code new_code = reversed_comparison_code (op0, NULL_RTX); | |
4294 | if (new_code != UNKNOWN) | |
4295 | return simplify_gen_relational (new_code, mode, VOIDmode, | |
4296 | XEXP (op0, 0), XEXP (op0, 1)); | |
4297 | } | |
4298 | } | |
4299 | ||
d2cb78ca | 4300 | /* (LTU/GEU (PLUS a C) C), where C is constant, can be simplified to |
4301 | (GEU/LTU a -C). Likewise for (LTU/GEU (PLUS a C) a). */ | |
4302 | if ((code == LTU || code == GEU) | |
4303 | && GET_CODE (op0) == PLUS | |
971ba038 | 4304 | && CONST_INT_P (XEXP (op0, 1)) |
d2cb78ca | 4305 | && (rtx_equal_p (op1, XEXP (op0, 0)) |
4306 | || rtx_equal_p (op1, XEXP (op0, 1)))) | |
4307 | { | |
4308 | rtx new_cmp | |
4309 | = simplify_gen_unary (NEG, cmp_mode, XEXP (op0, 1), cmp_mode); | |
4310 | return simplify_gen_relational ((code == LTU ? GEU : LTU), mode, | |
4311 | cmp_mode, XEXP (op0, 0), new_cmp); | |
4312 | } | |
4313 | ||
7333737f | 4314 | /* Canonicalize (LTU/GEU (PLUS a b) b) as (LTU/GEU (PLUS a b) a). */ |
4315 | if ((code == LTU || code == GEU) | |
4316 | && GET_CODE (op0) == PLUS | |
ecd7bb68 | 4317 | && rtx_equal_p (op1, XEXP (op0, 1)) |
4318 | /* Don't recurse "infinitely" for (LTU/GEU (PLUS b b) b). */ | |
4319 | && !rtx_equal_p (op1, XEXP (op0, 0))) | |
fe8274f8 | 4320 | return simplify_gen_relational (code, mode, cmp_mode, op0, |
4321 | copy_rtx (XEXP (op0, 0))); | |
7333737f | 4322 | |
b114d7da | 4323 | if (op1 == const0_rtx) |
4324 | { | |
4325 | /* Canonicalize (GTU x 0) as (NE x 0). */ | |
4326 | if (code == GTU) | |
4327 | return simplify_gen_relational (NE, mode, cmp_mode, op0, op1); | |
4328 | /* Canonicalize (LEU x 0) as (EQ x 0). */ | |
4329 | if (code == LEU) | |
4330 | return simplify_gen_relational (EQ, mode, cmp_mode, op0, op1); | |
4331 | } | |
4332 | else if (op1 == const1_rtx) | |
4333 | { | |
4334 | switch (code) | |
4335 | { | |
4336 | case GE: | |
4337 | /* Canonicalize (GE x 1) as (GT x 0). */ | |
4338 | return simplify_gen_relational (GT, mode, cmp_mode, | |
4339 | op0, const0_rtx); | |
4340 | case GEU: | |
4341 | /* Canonicalize (GEU x 1) as (NE x 0). */ | |
4342 | return simplify_gen_relational (NE, mode, cmp_mode, | |
4343 | op0, const0_rtx); | |
4344 | case LT: | |
4345 | /* Canonicalize (LT x 1) as (LE x 0). */ | |
4346 | return simplify_gen_relational (LE, mode, cmp_mode, | |
4347 | op0, const0_rtx); | |
4348 | case LTU: | |
4349 | /* Canonicalize (LTU x 1) as (EQ x 0). */ | |
4350 | return simplify_gen_relational (EQ, mode, cmp_mode, | |
4351 | op0, const0_rtx); | |
4352 | default: | |
4353 | break; | |
ac503e50 | 4354 | } |
4355 | } | |
b114d7da | 4356 | else if (op1 == constm1_rtx) |
4357 | { | |
4358 | /* Canonicalize (LE x -1) as (LT x 0). */ | |
4359 | if (code == LE) | |
4360 | return simplify_gen_relational (LT, mode, cmp_mode, op0, const0_rtx); | |
4361 | /* Canonicalize (GT x -1) as (GE x 0). */ | |
4362 | if (code == GT) | |
4363 | return simplify_gen_relational (GE, mode, cmp_mode, op0, const0_rtx); | |
4364 | } | |
af21a202 | 4365 | |
fc2ac93a | 4366 | /* (eq/ne (plus x cst1) cst2) simplifies to (eq/ne x (cst2 - cst1)) */ |
4367 | if ((code == EQ || code == NE) | |
4368 | && (op0code == PLUS || op0code == MINUS) | |
4369 | && CONSTANT_P (op1) | |
d5545189 | 4370 | && CONSTANT_P (XEXP (op0, 1)) |
4371 | && (INTEGRAL_MODE_P (cmp_mode) || flag_unsafe_math_optimizations)) | |
fc2ac93a | 4372 | { |
4373 | rtx x = XEXP (op0, 0); | |
4374 | rtx c = XEXP (op0, 1); | |
5998acf1 | 4375 | enum rtx_code invcode = op0code == PLUS ? MINUS : PLUS; |
4376 | rtx tem = simplify_gen_binary (invcode, cmp_mode, op1, c); | |
4377 | ||
4378 | /* Detect an infinite recursive condition, where we oscillate at this | |
4379 | simplification case between: | |
4380 | A + B == C <---> C - B == A, | |
4381 | where A, B, and C are all constants with non-simplifiable expressions, | |
4382 | usually SYMBOL_REFs. */ | |
4383 | if (GET_CODE (tem) == invcode | |
4384 | && CONSTANT_P (x) | |
4385 | && rtx_equal_p (c, XEXP (tem, 1))) | |
4386 | return NULL_RTX; | |
4387 | ||
4388 | return simplify_gen_relational (code, mode, cmp_mode, x, tem); | |
fc2ac93a | 4389 | } |
4390 | ||
870b7a32 | 4391 | /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is |
4392 | the same as (zero_extract:SI FOO (const_int 1) BAR). */ | |
4393 | if (code == NE | |
4394 | && op1 == const0_rtx | |
4395 | && GET_MODE_CLASS (mode) == MODE_INT | |
4396 | && cmp_mode != VOIDmode | |
feba5c4b | 4397 | /* ??? Work-around BImode bugs in the ia64 backend. */ |
4398 | && mode != BImode | |
632e2175 | 4399 | && cmp_mode != BImode |
870b7a32 | 4400 | && nonzero_bits (op0, cmp_mode) == 1 |
4401 | && STORE_FLAG_VALUE == 1) | |
632e2175 | 4402 | return GET_MODE_SIZE (mode) > GET_MODE_SIZE (cmp_mode) |
4403 | ? simplify_gen_unary (ZERO_EXTEND, mode, op0, cmp_mode) | |
4404 | : lowpart_subreg (mode, op0, cmp_mode); | |
870b7a32 | 4405 | |
c11ee826 | 4406 | /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y). */ |
4407 | if ((code == EQ || code == NE) | |
4408 | && op1 == const0_rtx | |
4409 | && op0code == XOR) | |
4410 | return simplify_gen_relational (code, mode, cmp_mode, | |
4411 | XEXP (op0, 0), XEXP (op0, 1)); | |
4412 | ||
d76f0821 | 4413 | /* (eq/ne (xor x y) x) simplifies to (eq/ne y 0). */ |
c11ee826 | 4414 | if ((code == EQ || code == NE) |
4415 | && op0code == XOR | |
4416 | && rtx_equal_p (XEXP (op0, 0), op1) | |
d76f0821 | 4417 | && !side_effects_p (XEXP (op0, 0))) |
4418 | return simplify_gen_relational (code, mode, cmp_mode, | |
4419 | XEXP (op0, 1), const0_rtx); | |
4420 | ||
4421 | /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne x 0). */ | |
c11ee826 | 4422 | if ((code == EQ || code == NE) |
4423 | && op0code == XOR | |
4424 | && rtx_equal_p (XEXP (op0, 1), op1) | |
d76f0821 | 4425 | && !side_effects_p (XEXP (op0, 1))) |
4426 | return simplify_gen_relational (code, mode, cmp_mode, | |
4427 | XEXP (op0, 0), const0_rtx); | |
c11ee826 | 4428 | |
4429 | /* (eq/ne (xor x C1) C2) simplifies to (eq/ne x (C1^C2)). */ | |
4430 | if ((code == EQ || code == NE) | |
4431 | && op0code == XOR | |
971ba038 | 4432 | && (CONST_INT_P (op1) |
c11ee826 | 4433 | || GET_CODE (op1) == CONST_DOUBLE) |
971ba038 | 4434 | && (CONST_INT_P (XEXP (op0, 1)) |
c11ee826 | 4435 | || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)) |
4436 | return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), | |
4437 | simplify_gen_binary (XOR, cmp_mode, | |
4438 | XEXP (op0, 1), op1)); | |
4439 | ||
ecf8b614 | 4440 | if (op0code == POPCOUNT && op1 == const0_rtx) |
4441 | switch (code) | |
4442 | { | |
4443 | case EQ: | |
4444 | case LE: | |
4445 | case LEU: | |
4446 | /* (eq (popcount x) (const_int 0)) -> (eq x (const_int 0)). */ | |
4447 | return simplify_gen_relational (EQ, mode, GET_MODE (XEXP (op0, 0)), | |
4448 | XEXP (op0, 0), const0_rtx); | |
4449 | ||
4450 | case NE: | |
4451 | case GT: | |
4452 | case GTU: | |
4453 | /* (ne (popcount x) (const_int 0)) -> (ne x (const_int 0)). */ | |
9966a430 | 4454 | return simplify_gen_relational (NE, mode, GET_MODE (XEXP (op0, 0)), |
ecf8b614 | 4455 | XEXP (op0, 0), const0_rtx); |
4456 | ||
4457 | default: | |
4458 | break; | |
4459 | } | |
4460 | ||
ac503e50 | 4461 | return NULL_RTX; |
4462 | } | |
4463 | ||
48e1416a | 4464 | enum |
3bac3cce | 4465 | { |
887d52fb | 4466 | CMP_EQ = 1, |
4467 | CMP_LT = 2, | |
4468 | CMP_GT = 4, | |
4469 | CMP_LTU = 8, | |
4470 | CMP_GTU = 16 | |
3bac3cce | 4471 | }; |
4472 | ||
4473 | ||
4474 | /* Convert the known results for EQ, LT, GT, LTU, GTU contained in | |
4475 | KNOWN_RESULT to a CONST_INT, based on the requested comparison CODE | |
48e1416a | 4476 | For KNOWN_RESULT to make sense it should be either CMP_EQ, or the |
887d52fb | 4477 | logical OR of one of (CMP_LT, CMP_GT) and one of (CMP_LTU, CMP_GTU). |
3bac3cce | 4478 | For floating-point comparisons, assume that the operands were ordered. */ |
4479 | ||
4480 | static rtx | |
4481 | comparison_result (enum rtx_code code, int known_results) | |
4482 | { | |
3bac3cce | 4483 | switch (code) |
4484 | { | |
4485 | case EQ: | |
4486 | case UNEQ: | |
887d52fb | 4487 | return (known_results & CMP_EQ) ? const_true_rtx : const0_rtx; |
3bac3cce | 4488 | case NE: |
4489 | case LTGT: | |
887d52fb | 4490 | return (known_results & CMP_EQ) ? const0_rtx : const_true_rtx; |
3bac3cce | 4491 | |
4492 | case LT: | |
4493 | case UNLT: | |
887d52fb | 4494 | return (known_results & CMP_LT) ? const_true_rtx : const0_rtx; |
3bac3cce | 4495 | case GE: |
4496 | case UNGE: | |
887d52fb | 4497 | return (known_results & CMP_LT) ? const0_rtx : const_true_rtx; |
3bac3cce | 4498 | |
4499 | case GT: | |
4500 | case UNGT: | |
887d52fb | 4501 | return (known_results & CMP_GT) ? const_true_rtx : const0_rtx; |
3bac3cce | 4502 | case LE: |
4503 | case UNLE: | |
887d52fb | 4504 | return (known_results & CMP_GT) ? const0_rtx : const_true_rtx; |
3bac3cce | 4505 | |
4506 | case LTU: | |
887d52fb | 4507 | return (known_results & CMP_LTU) ? const_true_rtx : const0_rtx; |
3bac3cce | 4508 | case GEU: |
887d52fb | 4509 | return (known_results & CMP_LTU) ? const0_rtx : const_true_rtx; |
3bac3cce | 4510 | |
4511 | case GTU: | |
887d52fb | 4512 | return (known_results & CMP_GTU) ? const_true_rtx : const0_rtx; |
3bac3cce | 4513 | case LEU: |
887d52fb | 4514 | return (known_results & CMP_GTU) ? const0_rtx : const_true_rtx; |
3bac3cce | 4515 | |
4516 | case ORDERED: | |
4517 | return const_true_rtx; | |
4518 | case UNORDERED: | |
4519 | return const0_rtx; | |
4520 | default: | |
4521 | gcc_unreachable (); | |
4522 | } | |
4523 | } | |
4524 | ||
ac503e50 | 4525 | /* Check if the given comparison (done in the given MODE) is actually a |
4526 | tautology or a contradiction. | |
089b4730 | 4527 | If no simplification is possible, this function returns zero. |
4528 | Otherwise, it returns either const_true_rtx or const0_rtx. */ | |
af21a202 | 4529 | |
4530 | rtx | |
089b4730 | 4531 | simplify_const_relational_operation (enum rtx_code code, |
4532 | enum machine_mode mode, | |
4533 | rtx op0, rtx op1) | |
af21a202 | 4534 | { |
af21a202 | 4535 | rtx tem; |
02cd84cd | 4536 | rtx trueop0; |
4537 | rtx trueop1; | |
af21a202 | 4538 | |
04e579b6 | 4539 | gcc_assert (mode != VOIDmode |
4540 | || (GET_MODE (op0) == VOIDmode | |
4541 | && GET_MODE (op1) == VOIDmode)); | |
67405ba4 | 4542 | |
af21a202 | 4543 | /* If op0 is a compare, extract the comparison arguments from it. */ |
4544 | if (GET_CODE (op0) == COMPARE && op1 == const0_rtx) | |
a6d17235 | 4545 | { |
4546 | op1 = XEXP (op0, 1); | |
4547 | op0 = XEXP (op0, 0); | |
4548 | ||
4549 | if (GET_MODE (op0) != VOIDmode) | |
4550 | mode = GET_MODE (op0); | |
4551 | else if (GET_MODE (op1) != VOIDmode) | |
4552 | mode = GET_MODE (op1); | |
4553 | else | |
4554 | return 0; | |
4555 | } | |
af21a202 | 4556 | |
4557 | /* We can't simplify MODE_CC values since we don't know what the | |
4558 | actual comparison is. */ | |
a4589b78 | 4559 | if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0)) |
af21a202 | 4560 | return 0; |
4561 | ||
125b9253 | 4562 | /* Make sure the constant is second. */ |
efbc8128 | 4563 | if (swap_commutative_operands_p (op0, op1)) |
125b9253 | 4564 | { |
4565 | tem = op0, op0 = op1, op1 = tem; | |
4566 | code = swap_condition (code); | |
4567 | } | |
4568 | ||
efbc8128 | 4569 | trueop0 = avoid_constant_pool_reference (op0); |
4570 | trueop1 = avoid_constant_pool_reference (op1); | |
4571 | ||
af21a202 | 4572 | /* For integer comparisons of A and B maybe we can simplify A - B and can |
4573 | then simplify a comparison of that with zero. If A and B are both either | |
4574 | a register or a CONST_INT, this can't help; testing for these cases will | |
4575 | prevent infinite recursion here and speed things up. | |
4576 | ||
3cea28d7 | 4577 | We can only do this for EQ and NE comparisons as otherwise we may |
4578 | lose or introduce overflow which we cannot disregard as undefined as | |
4579 | we do not know the signedness of the operation on either the left or | |
4580 | the right hand side of the comparison. */ | |
af21a202 | 4581 | |
3cea28d7 | 4582 | if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx |
4583 | && (code == EQ || code == NE) | |
971ba038 | 4584 | && ! ((REG_P (op0) || CONST_INT_P (trueop0)) |
4585 | && (REG_P (op1) || CONST_INT_P (trueop1))) | |
af21a202 | 4586 | && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1)) |
3cea28d7 | 4587 | /* We cannot do this if tem is a nonzero address. */ |
4588 | && ! nonzero_address_p (tem)) | |
089b4730 | 4589 | return simplify_const_relational_operation (signed_condition (code), |
4590 | mode, tem, const0_rtx); | |
af21a202 | 4591 | |
b5518e7e | 4592 | if (! HONOR_NANS (mode) && code == ORDERED) |
79b403d4 | 4593 | return const_true_rtx; |
4594 | ||
b5518e7e | 4595 | if (! HONOR_NANS (mode) && code == UNORDERED) |
79b403d4 | 4596 | return const0_rtx; |
4597 | ||
920d0fb5 | 4598 | /* For modes without NaNs, if the two operands are equal, we know the |
3bac3cce | 4599 | result except if they have side-effects. Even with NaNs we know |
4600 | the result of unordered comparisons and, if signaling NaNs are | |
4601 | irrelevant, also the result of LT/GT/LTGT. */ | |
4602 | if ((! HONOR_NANS (GET_MODE (trueop0)) | |
4603 | || code == UNEQ || code == UNLE || code == UNGE | |
4604 | || ((code == LT || code == GT || code == LTGT) | |
4605 | && ! HONOR_SNANS (GET_MODE (trueop0)))) | |
73364b4c | 4606 | && rtx_equal_p (trueop0, trueop1) |
4607 | && ! side_effects_p (trueop0)) | |
887d52fb | 4608 | return comparison_result (code, CMP_EQ); |
af21a202 | 4609 | |
4610 | /* If the operands are floating-point constants, see if we can fold | |
4611 | the result. */ | |
3bac3cce | 4612 | if (GET_CODE (trueop0) == CONST_DOUBLE |
4613 | && GET_CODE (trueop1) == CONST_DOUBLE | |
4614 | && SCALAR_FLOAT_MODE_P (GET_MODE (trueop0))) | |
af21a202 | 4615 | { |
536f5fb1 | 4616 | REAL_VALUE_TYPE d0, d1; |
af21a202 | 4617 | |
536f5fb1 | 4618 | REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0); |
4619 | REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1); | |
5377f687 | 4620 | |
a113df96 | 4621 | /* Comparisons are unordered iff at least one of the values is NaN. */ |
536f5fb1 | 4622 | if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1)) |
5377f687 | 4623 | switch (code) |
4624 | { | |
4625 | case UNEQ: | |
4626 | case UNLT: | |
4627 | case UNGT: | |
4628 | case UNLE: | |
4629 | case UNGE: | |
4630 | case NE: | |
4631 | case UNORDERED: | |
4632 | return const_true_rtx; | |
4633 | case EQ: | |
4634 | case LT: | |
4635 | case GT: | |
4636 | case LE: | |
4637 | case GE: | |
4638 | case LTGT: | |
4639 | case ORDERED: | |
4640 | return const0_rtx; | |
4641 | default: | |
4642 | return 0; | |
4643 | } | |
af21a202 | 4644 | |
3bac3cce | 4645 | return comparison_result (code, |
887d52fb | 4646 | (REAL_VALUES_EQUAL (d0, d1) ? CMP_EQ : |
4647 | REAL_VALUES_LESS (d0, d1) ? CMP_LT : CMP_GT)); | |
af21a202 | 4648 | } |
af21a202 | 4649 | |
4650 | /* Otherwise, see if the operands are both integers. */ | |
3bac3cce | 4651 | if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode) |
4652 | && (GET_CODE (trueop0) == CONST_DOUBLE | |
971ba038 | 4653 | || CONST_INT_P (trueop0)) |
3bac3cce | 4654 | && (GET_CODE (trueop1) == CONST_DOUBLE |
971ba038 | 4655 | || CONST_INT_P (trueop1))) |
af21a202 | 4656 | { |
ded805e6 | 4657 | int width = GET_MODE_PRECISION (mode); |
af21a202 | 4658 | HOST_WIDE_INT l0s, h0s, l1s, h1s; |
4659 | unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u; | |
4660 | ||
4661 | /* Get the two words comprising each integer constant. */ | |
02cd84cd | 4662 | if (GET_CODE (trueop0) == CONST_DOUBLE) |
af21a202 | 4663 | { |
02cd84cd | 4664 | l0u = l0s = CONST_DOUBLE_LOW (trueop0); |
4665 | h0u = h0s = CONST_DOUBLE_HIGH (trueop0); | |
af21a202 | 4666 | } |
4667 | else | |
4668 | { | |
02cd84cd | 4669 | l0u = l0s = INTVAL (trueop0); |
2cae60d1 | 4670 | h0u = h0s = HWI_SIGN_EXTEND (l0s); |
af21a202 | 4671 | } |
40734805 | 4672 | |
02cd84cd | 4673 | if (GET_CODE (trueop1) == CONST_DOUBLE) |
af21a202 | 4674 | { |
02cd84cd | 4675 | l1u = l1s = CONST_DOUBLE_LOW (trueop1); |
4676 | h1u = h1s = CONST_DOUBLE_HIGH (trueop1); | |
af21a202 | 4677 | } |
4678 | else | |
4679 | { | |
02cd84cd | 4680 | l1u = l1s = INTVAL (trueop1); |
2cae60d1 | 4681 | h1u = h1s = HWI_SIGN_EXTEND (l1s); |
af21a202 | 4682 | } |
4683 | ||
4684 | /* If WIDTH is nonzero and smaller than HOST_BITS_PER_WIDE_INT, | |
4685 | we have to sign or zero-extend the values. */ | |
af21a202 | 4686 | if (width != 0 && width < HOST_BITS_PER_WIDE_INT) |
4687 | { | |
f92430e0 | 4688 | l0u &= GET_MODE_MASK (mode); |
4689 | l1u &= GET_MODE_MASK (mode); | |
af21a202 | 4690 | |
f92430e0 | 4691 | if (val_signbit_known_set_p (mode, l0s)) |
4692 | l0s |= ~GET_MODE_MASK (mode); | |
af21a202 | 4693 | |
f92430e0 | 4694 | if (val_signbit_known_set_p (mode, l1s)) |
4695 | l1s |= ~GET_MODE_MASK (mode); | |
af21a202 | 4696 | } |
f7d1f6d0 | 4697 | if (width != 0 && width <= HOST_BITS_PER_WIDE_INT) |
4698 | h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s); | |
af21a202 | 4699 | |
3bac3cce | 4700 | if (h0u == h1u && l0u == l1u) |
887d52fb | 4701 | return comparison_result (code, CMP_EQ); |
3bac3cce | 4702 | else |
4703 | { | |
4704 | int cr; | |
887d52fb | 4705 | cr = (h0s < h1s || (h0s == h1s && l0u < l1u)) ? CMP_LT : CMP_GT; |
4706 | cr |= (h0u < h1u || (h0u == h1u && l0u < l1u)) ? CMP_LTU : CMP_GTU; | |
4707 | return comparison_result (code, cr); | |
3bac3cce | 4708 | } |
af21a202 | 4709 | } |
4710 | ||
3bac3cce | 4711 | /* Optimize comparisons with upper and lower bounds. */ |
f179ee60 | 4712 | if (HWI_COMPUTABLE_MODE_P (mode) |
971ba038 | 4713 | && CONST_INT_P (trueop1)) |
af21a202 | 4714 | { |
3bac3cce | 4715 | int sign; |
4716 | unsigned HOST_WIDE_INT nonzero = nonzero_bits (trueop0, mode); | |
4717 | HOST_WIDE_INT val = INTVAL (trueop1); | |
4718 | HOST_WIDE_INT mmin, mmax; | |
4719 | ||
4720 | if (code == GEU | |
4721 | || code == LEU | |
4722 | || code == GTU | |
4723 | || code == LTU) | |
4724 | sign = 0; | |
4725 | else | |
4726 | sign = 1; | |
a6629703 | 4727 | |
3bac3cce | 4728 | /* Get a reduced range if the sign bit is zero. */ |
4729 | if (nonzero <= (GET_MODE_MASK (mode) >> 1)) | |
4730 | { | |
4731 | mmin = 0; | |
4732 | mmax = nonzero; | |
4733 | } | |
4734 | else | |
4735 | { | |
4736 | rtx mmin_rtx, mmax_rtx; | |
887d52fb | 4737 | get_mode_bounds (mode, sign, mode, &mmin_rtx, &mmax_rtx); |
3bac3cce | 4738 | |
a6871c1e | 4739 | mmin = INTVAL (mmin_rtx); |
4740 | mmax = INTVAL (mmax_rtx); | |
4741 | if (sign) | |
4742 | { | |
4743 | unsigned int sign_copies = num_sign_bit_copies (trueop0, mode); | |
4744 | ||
4745 | mmin >>= (sign_copies - 1); | |
4746 | mmax >>= (sign_copies - 1); | |
4747 | } | |
a6629703 | 4748 | } |
4749 | ||
af21a202 | 4750 | switch (code) |
4751 | { | |
3bac3cce | 4752 | /* x >= y is always true for y <= mmin, always false for y > mmax. */ |
4753 | case GEU: | |
4754 | if ((unsigned HOST_WIDE_INT) val <= (unsigned HOST_WIDE_INT) mmin) | |
4755 | return const_true_rtx; | |
4756 | if ((unsigned HOST_WIDE_INT) val > (unsigned HOST_WIDE_INT) mmax) | |
4757 | return const0_rtx; | |
4758 | break; | |
4759 | case GE: | |
4760 | if (val <= mmin) | |
4761 | return const_true_rtx; | |
4762 | if (val > mmax) | |
4763 | return const0_rtx; | |
4764 | break; | |
4765 | ||
4766 | /* x <= y is always true for y >= mmax, always false for y < mmin. */ | |
4767 | case LEU: | |
4768 | if ((unsigned HOST_WIDE_INT) val >= (unsigned HOST_WIDE_INT) mmax) | |
4769 | return const_true_rtx; | |
4770 | if ((unsigned HOST_WIDE_INT) val < (unsigned HOST_WIDE_INT) mmin) | |
4771 | return const0_rtx; | |
4772 | break; | |
4773 | case LE: | |
4774 | if (val >= mmax) | |
4775 | return const_true_rtx; | |
4776 | if (val < mmin) | |
4777 | return const0_rtx; | |
4778 | break; | |
4779 | ||
af21a202 | 4780 | case EQ: |
3bac3cce | 4781 | /* x == y is always false for y out of range. */ |
4782 | if (val < mmin || val > mmax) | |
4783 | return const0_rtx; | |
4784 | break; | |
4785 | ||
4786 | /* x > y is always false for y >= mmax, always true for y < mmin. */ | |
4787 | case GTU: | |
4788 | if ((unsigned HOST_WIDE_INT) val >= (unsigned HOST_WIDE_INT) mmax) | |
4789 | return const0_rtx; | |
4790 | if ((unsigned HOST_WIDE_INT) val < (unsigned HOST_WIDE_INT) mmin) | |
4791 | return const_true_rtx; | |
4792 | break; | |
4793 | case GT: | |
4794 | if (val >= mmax) | |
4795 | return const0_rtx; | |
4796 | if (val < mmin) | |
4797 | return const_true_rtx; | |
4798 | break; | |
4799 | ||
4800 | /* x < y is always false for y <= mmin, always true for y > mmax. */ | |
4801 | case LTU: | |
4802 | if ((unsigned HOST_WIDE_INT) val <= (unsigned HOST_WIDE_INT) mmin) | |
4803 | return const0_rtx; | |
4804 | if ((unsigned HOST_WIDE_INT) val > (unsigned HOST_WIDE_INT) mmax) | |
4805 | return const_true_rtx; | |
4806 | break; | |
4807 | case LT: | |
4808 | if (val <= mmin) | |
af21a202 | 4809 | return const0_rtx; |
3bac3cce | 4810 | if (val > mmax) |
4811 | return const_true_rtx; | |
af21a202 | 4812 | break; |
4813 | ||
4814 | case NE: | |
3bac3cce | 4815 | /* x != y is always true for y out of range. */ |
4816 | if (val < mmin || val > mmax) | |
af21a202 | 4817 | return const_true_rtx; |
4818 | break; | |
4819 | ||
3bac3cce | 4820 | default: |
4821 | break; | |
4822 | } | |
4823 | } | |
4824 | ||
4825 | /* Optimize integer comparisons with zero. */ | |
4826 | if (trueop1 == const0_rtx) | |
4827 | { | |
4828 | /* Some addresses are known to be nonzero. We don't know | |
887d52fb | 4829 | their sign, but equality comparisons are known. */ |
3bac3cce | 4830 | if (nonzero_address_p (trueop0)) |
887d52fb | 4831 | { |
3bac3cce | 4832 | if (code == EQ || code == LEU) |
4833 | return const0_rtx; | |
4834 | if (code == NE || code == GTU) | |
4835 | return const_true_rtx; | |
887d52fb | 4836 | } |
3bac3cce | 4837 | |
4838 | /* See if the first operand is an IOR with a constant. If so, we | |
4839 | may be able to determine the result of this comparison. */ | |
4840 | if (GET_CODE (op0) == IOR) | |
887d52fb | 4841 | { |
3bac3cce | 4842 | rtx inner_const = avoid_constant_pool_reference (XEXP (op0, 1)); |
971ba038 | 4843 | if (CONST_INT_P (inner_const) && inner_const != const0_rtx) |
3bac3cce | 4844 | { |
ded805e6 | 4845 | int sign_bitnum = GET_MODE_PRECISION (mode) - 1; |
887d52fb | 4846 | int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum |
23423d0e | 4847 | && (UINTVAL (inner_const) |
4848 | & ((unsigned HOST_WIDE_INT) 1 | |
4849 | << sign_bitnum))); | |
887d52fb | 4850 | |
4851 | switch (code) | |
4852 | { | |
4853 | case EQ: | |
3bac3cce | 4854 | case LEU: |
887d52fb | 4855 | return const0_rtx; |
4856 | case NE: | |
3bac3cce | 4857 | case GTU: |
887d52fb | 4858 | return const_true_rtx; |
4859 | case LT: | |
4860 | case LE: | |
4861 | if (has_sign) | |
4862 | return const_true_rtx; | |
4863 | break; | |
4864 | case GT: | |
3bac3cce | 4865 | case GE: |
887d52fb | 4866 | if (has_sign) |
4867 | return const0_rtx; | |
4868 | break; | |
4869 | default: | |
4870 | break; | |
4871 | } | |
4872 | } | |
3bac3cce | 4873 | } |
4874 | } | |
4875 | ||
4876 | /* Optimize comparison of ABS with zero. */ | |
4877 | if (trueop1 == CONST0_RTX (mode) | |
4878 | && (GET_CODE (trueop0) == ABS | |
4879 | || (GET_CODE (trueop0) == FLOAT_EXTEND | |
4880 | && GET_CODE (XEXP (trueop0, 0)) == ABS))) | |
4881 | { | |
4882 | switch (code) | |
4883 | { | |
88d97b05 | 4884 | case LT: |
4885 | /* Optimize abs(x) < 0.0. */ | |
3bac3cce | 4886 | if (!HONOR_SNANS (mode) |
981eb798 | 4887 | && (!INTEGRAL_MODE_P (mode) |
4888 | || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) | |
88d97b05 | 4889 | { |
3bac3cce | 4890 | if (INTEGRAL_MODE_P (mode) |
4891 | && (issue_strict_overflow_warning | |
4892 | (WARN_STRICT_OVERFLOW_CONDITIONAL))) | |
4893 | warning (OPT_Wstrict_overflow, | |
4894 | ("assuming signed overflow does not occur when " | |
4895 | "assuming abs (x) < 0 is false")); | |
4896 | return const0_rtx; | |
88d97b05 | 4897 | } |
4898 | break; | |
4899 | ||
4900 | case GE: | |
4901 | /* Optimize abs(x) >= 0.0. */ | |
3bac3cce | 4902 | if (!HONOR_NANS (mode) |
981eb798 | 4903 | && (!INTEGRAL_MODE_P (mode) |
4904 | || (!flag_wrapv && !flag_trapv && flag_strict_overflow))) | |
88d97b05 | 4905 | { |
3bac3cce | 4906 | if (INTEGRAL_MODE_P (mode) |
4907 | && (issue_strict_overflow_warning | |
4908 | (WARN_STRICT_OVERFLOW_CONDITIONAL))) | |
4909 | warning (OPT_Wstrict_overflow, | |
4910 | ("assuming signed overflow does not occur when " | |
4911 | "assuming abs (x) >= 0 is true")); | |
4912 | return const_true_rtx; | |
88d97b05 | 4913 | } |
4914 | break; | |
4915 | ||
d4a16194 | 4916 | case UNGE: |
4917 | /* Optimize ! (abs(x) < 0.0). */ | |
3bac3cce | 4918 | return const_true_rtx; |
60b8c5b3 | 4919 | |
af21a202 | 4920 | default: |
4921 | break; | |
4922 | } | |
af21a202 | 4923 | } |
4924 | ||
3bac3cce | 4925 | return 0; |
af21a202 | 4926 | } |
4927 | \f | |
4928 | /* Simplify CODE, an operation with result mode MODE and three operands, | |
4929 | OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became | |
4930 | a constant. Return 0 if no simplifications is possible. */ | |
4931 | ||
4932 | rtx | |
60b8c5b3 | 4933 | simplify_ternary_operation (enum rtx_code code, enum machine_mode mode, |
4934 | enum machine_mode op0_mode, rtx op0, rtx op1, | |
4935 | rtx op2) | |
af21a202 | 4936 | { |
ded805e6 | 4937 | unsigned int width = GET_MODE_PRECISION (mode); |
5d4d1c96 | 4938 | bool any_change = false; |
4939 | rtx tem; | |
af21a202 | 4940 | |
4941 | /* VOIDmode means "infinite" precision. */ | |
4942 | if (width == 0) | |
4943 | width = HOST_BITS_PER_WIDE_INT; | |
4944 | ||
4945 | switch (code) | |
4946 | { | |
7e0713b1 | 4947 | case FMA: |
5d4d1c96 | 4948 | /* Simplify negations around the multiplication. */ |
4949 | /* -a * -b + c => a * b + c. */ | |
4950 | if (GET_CODE (op0) == NEG) | |
4951 | { | |
4952 | tem = simplify_unary_operation (NEG, mode, op1, mode); | |
4953 | if (tem) | |
4954 | op1 = tem, op0 = XEXP (op0, 0), any_change = true; | |
4955 | } | |
4956 | else if (GET_CODE (op1) == NEG) | |
4957 | { | |
4958 | tem = simplify_unary_operation (NEG, mode, op0, mode); | |
4959 | if (tem) | |
4960 | op0 = tem, op1 = XEXP (op1, 0), any_change = true; | |
4961 | } | |
4962 | ||
4963 | /* Canonicalize the two multiplication operands. */ | |
4964 | /* a * -b + c => -b * a + c. */ | |
4965 | if (swap_commutative_operands_p (op0, op1)) | |
4966 | tem = op0, op0 = op1, op1 = tem, any_change = true; | |
4967 | ||
4968 | if (any_change) | |
4969 | return gen_rtx_FMA (mode, op0, op1, op2); | |
7e0713b1 | 4970 | return NULL_RTX; |
4971 | ||
af21a202 | 4972 | case SIGN_EXTRACT: |
4973 | case ZERO_EXTRACT: | |
971ba038 | 4974 | if (CONST_INT_P (op0) |
4975 | && CONST_INT_P (op1) | |
4976 | && CONST_INT_P (op2) | |
e2496245 | 4977 | && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width) |
4491f79f | 4978 | && width <= (unsigned) HOST_BITS_PER_WIDE_INT) |
af21a202 | 4979 | { |
4980 | /* Extracting a bit-field from a constant */ | |
23423d0e | 4981 | unsigned HOST_WIDE_INT val = UINTVAL (op0); |
ded805e6 | 4982 | HOST_WIDE_INT op1val = INTVAL (op1); |
4983 | HOST_WIDE_INT op2val = INTVAL (op2); | |
af21a202 | 4984 | if (BITS_BIG_ENDIAN) |
ded805e6 | 4985 | val >>= GET_MODE_PRECISION (op0_mode) - op2val - op1val; |
af21a202 | 4986 | else |
ded805e6 | 4987 | val >>= op2val; |
af21a202 | 4988 | |
ded805e6 | 4989 | if (HOST_BITS_PER_WIDE_INT != op1val) |
af21a202 | 4990 | { |
4991 | /* First zero-extend. */ | |
ded805e6 | 4992 | val &= ((unsigned HOST_WIDE_INT) 1 << op1val) - 1; |
af21a202 | 4993 | /* If desired, propagate sign bit. */ |
4994 | if (code == SIGN_EXTRACT | |
ded805e6 | 4995 | && (val & ((unsigned HOST_WIDE_INT) 1 << (op1val - 1))) |
23423d0e | 4996 | != 0) |
ded805e6 | 4997 | val |= ~ (((unsigned HOST_WIDE_INT) 1 << op1val) - 1); |
af21a202 | 4998 | } |
4999 | ||
ff8365c7 | 5000 | return gen_int_mode (val, mode); |
af21a202 | 5001 | } |
5002 | break; | |
5003 | ||
5004 | case IF_THEN_ELSE: | |
971ba038 | 5005 | if (CONST_INT_P (op0)) |
af21a202 | 5006 | return op0 != const0_rtx ? op1 : op2; |
5007 | ||
357b5a1f | 5008 | /* Convert c ? a : a into "a". */ |
5009 | if (rtx_equal_p (op1, op2) && ! side_effects_p (op0)) | |
af21a202 | 5010 | return op1; |
357b5a1f | 5011 | |
5012 | /* Convert a != b ? a : b into "a". */ | |
5013 | if (GET_CODE (op0) == NE | |
5014 | && ! side_effects_p (op0) | |
5015 | && ! HONOR_NANS (mode) | |
5016 | && ! HONOR_SIGNED_ZEROS (mode) | |
5017 | && ((rtx_equal_p (XEXP (op0, 0), op1) | |
5018 | && rtx_equal_p (XEXP (op0, 1), op2)) | |
5019 | || (rtx_equal_p (XEXP (op0, 0), op2) | |
5020 | && rtx_equal_p (XEXP (op0, 1), op1)))) | |
5021 | return op1; | |
5022 | ||
5023 | /* Convert a == b ? a : b into "b". */ | |
5024 | if (GET_CODE (op0) == EQ | |
5025 | && ! side_effects_p (op0) | |
5026 | && ! HONOR_NANS (mode) | |
5027 | && ! HONOR_SIGNED_ZEROS (mode) | |
5028 | && ((rtx_equal_p (XEXP (op0, 0), op1) | |
5029 | && rtx_equal_p (XEXP (op0, 1), op2)) | |
5030 | || (rtx_equal_p (XEXP (op0, 0), op2) | |
5031 | && rtx_equal_p (XEXP (op0, 1), op1)))) | |
af21a202 | 5032 | return op2; |
357b5a1f | 5033 | |
6720e96c | 5034 | if (COMPARISON_P (op0) && ! side_effects_p (op0)) |
af21a202 | 5035 | { |
67405ba4 | 5036 | enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode |
5037 | ? GET_MODE (XEXP (op0, 1)) | |
5038 | : GET_MODE (XEXP (op0, 0))); | |
b6564518 | 5039 | rtx temp; |
c21ff061 | 5040 | |
5041 | /* Look for happy constants in op1 and op2. */ | |
971ba038 | 5042 | if (CONST_INT_P (op1) && CONST_INT_P (op2)) |
c21ff061 | 5043 | { |
5044 | HOST_WIDE_INT t = INTVAL (op1); | |
5045 | HOST_WIDE_INT f = INTVAL (op2); | |
40734805 | 5046 | |
c21ff061 | 5047 | if (t == STORE_FLAG_VALUE && f == 0) |
5048 | code = GET_CODE (op0); | |
7da6ea0c | 5049 | else if (t == 0 && f == STORE_FLAG_VALUE) |
5050 | { | |
5051 | enum rtx_code tmp; | |
5052 | tmp = reversed_comparison_code (op0, NULL_RTX); | |
5053 | if (tmp == UNKNOWN) | |
5054 | break; | |
5055 | code = tmp; | |
5056 | } | |
c21ff061 | 5057 | else |
5058 | break; | |
5059 | ||
32e9936c | 5060 | return simplify_gen_relational (code, mode, cmp_mode, |
ac503e50 | 5061 | XEXP (op0, 0), XEXP (op0, 1)); |
5062 | } | |
5063 | ||
5064 | if (cmp_mode == VOIDmode) | |
5065 | cmp_mode = op0_mode; | |
5066 | temp = simplify_relational_operation (GET_CODE (op0), op0_mode, | |
5067 | cmp_mode, XEXP (op0, 0), | |
5068 | XEXP (op0, 1)); | |
5069 | ||
5070 | /* See if any simplifications were possible. */ | |
5071 | if (temp) | |
5072 | { | |
971ba038 | 5073 | if (CONST_INT_P (temp)) |
ac503e50 | 5074 | return temp == const0_rtx ? op2 : op1; |
5075 | else if (temp) | |
5076 | return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2); | |
c21ff061 | 5077 | } |
af21a202 | 5078 | } |
5079 | break; | |
357b5a1f | 5080 | |
b649c04e | 5081 | case VEC_MERGE: |
04e579b6 | 5082 | gcc_assert (GET_MODE (op0) == mode); |
5083 | gcc_assert (GET_MODE (op1) == mode); | |
5084 | gcc_assert (VECTOR_MODE_P (mode)); | |
b649c04e | 5085 | op2 = avoid_constant_pool_reference (op2); |
971ba038 | 5086 | if (CONST_INT_P (op2)) |
b649c04e | 5087 | { |
5088 | int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode)); | |
5089 | unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); | |
22ee9f9f | 5090 | int mask = (1 << n_elts) - 1; |
b649c04e | 5091 | |
a7e82922 | 5092 | if (!(INTVAL (op2) & mask)) |
5093 | return op1; | |
5094 | if ((INTVAL (op2) & mask) == mask) | |
5095 | return op0; | |
5096 | ||
5097 | op0 = avoid_constant_pool_reference (op0); | |
5098 | op1 = avoid_constant_pool_reference (op1); | |
5099 | if (GET_CODE (op0) == CONST_VECTOR | |
5100 | && GET_CODE (op1) == CONST_VECTOR) | |
5101 | { | |
5102 | rtvec v = rtvec_alloc (n_elts); | |
5103 | unsigned int i; | |
5104 | ||
5105 | for (i = 0; i < n_elts; i++) | |
5106 | RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i) | |
5107 | ? CONST_VECTOR_ELT (op0, i) | |
5108 | : CONST_VECTOR_ELT (op1, i)); | |
5109 | return gen_rtx_CONST_VECTOR (mode, v); | |
5110 | } | |
b649c04e | 5111 | } |
5112 | break; | |
af21a202 | 5113 | |
5114 | default: | |
04e579b6 | 5115 | gcc_unreachable (); |
af21a202 | 5116 | } |
5117 | ||
5118 | return 0; | |
5119 | } | |
5120 | ||
b563b483 | 5121 | /* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_FIXED |
5122 | or CONST_VECTOR, | |
5123 | returning another CONST_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR. | |
64ab453f | 5124 | |
791172c5 | 5125 | Works by unpacking OP into a collection of 8-bit values |
5126 | represented as a little-endian array of 'unsigned char', selecting by BYTE, | |
5127 | and then repacking them again for OUTERMODE. */ | |
64ab453f | 5128 | |
791172c5 | 5129 | static rtx |
48e1416a | 5130 | simplify_immed_subreg (enum machine_mode outermode, rtx op, |
791172c5 | 5131 | enum machine_mode innermode, unsigned int byte) |
5132 | { | |
5133 | /* We support up to 512-bit values (for V8DFmode). */ | |
5134 | enum { | |
5135 | max_bitsize = 512, | |
5136 | value_bit = 8, | |
5137 | value_mask = (1 << value_bit) - 1 | |
5138 | }; | |
5139 | unsigned char value[max_bitsize / value_bit]; | |
5140 | int value_start; | |
5141 | int i; | |
5142 | int elem; | |
5143 | ||
5144 | int num_elem; | |
5145 | rtx * elems; | |
5146 | int elem_bitsize; | |
5147 | rtx result_s; | |
5148 | rtvec result_v = NULL; | |
5149 | enum mode_class outer_class; | |
5150 | enum machine_mode outer_submode; | |
5151 | ||
5152 | /* Some ports misuse CCmode. */ | |
971ba038 | 5153 | if (GET_MODE_CLASS (outermode) == MODE_CC && CONST_INT_P (op)) |
09f800b9 | 5154 | return op; |
5155 | ||
53d0faa8 | 5156 | /* We have no way to represent a complex constant at the rtl level. */ |
5157 | if (COMPLEX_MODE_P (outermode)) | |
5158 | return NULL_RTX; | |
5159 | ||
791172c5 | 5160 | /* Unpack the value. */ |
5161 | ||
ead34f59 | 5162 | if (GET_CODE (op) == CONST_VECTOR) |
5163 | { | |
791172c5 | 5164 | num_elem = CONST_VECTOR_NUNITS (op); |
5165 | elems = &CONST_VECTOR_ELT (op, 0); | |
5166 | elem_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (innermode)); | |
5167 | } | |
5168 | else | |
5169 | { | |
5170 | num_elem = 1; | |
5171 | elems = &op; | |
5172 | elem_bitsize = max_bitsize; | |
5173 | } | |
04e579b6 | 5174 | /* If this asserts, it is too complicated; reducing value_bit may help. */ |
5175 | gcc_assert (BITS_PER_UNIT % value_bit == 0); | |
5176 | /* I don't know how to handle endianness of sub-units. */ | |
5177 | gcc_assert (elem_bitsize % BITS_PER_UNIT == 0); | |
48e1416a | 5178 | |
791172c5 | 5179 | for (elem = 0; elem < num_elem; elem++) |
5180 | { | |
5181 | unsigned char * vp; | |
5182 | rtx el = elems[elem]; | |
48e1416a | 5183 | |
791172c5 | 5184 | /* Vectors are kept in target memory order. (This is probably |
5185 | a mistake.) */ | |
5186 | { | |
5187 | unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; | |
02d7807a | 5188 | unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) |
791172c5 | 5189 | / BITS_PER_UNIT); |
5190 | unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
5191 | unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
5192 | unsigned bytele = (subword_byte % UNITS_PER_WORD | |
5193 | + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
5194 | vp = value + (bytele * BITS_PER_UNIT) / value_bit; | |
5195 | } | |
48e1416a | 5196 | |
791172c5 | 5197 | switch (GET_CODE (el)) |
20407c42 | 5198 | { |
791172c5 | 5199 | case CONST_INT: |
5200 | for (i = 0; | |
48e1416a | 5201 | i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; |
791172c5 | 5202 | i += value_bit) |
5203 | *vp++ = INTVAL (el) >> i; | |
5204 | /* CONST_INTs are always logically sign-extended. */ | |
5205 | for (; i < elem_bitsize; i += value_bit) | |
5206 | *vp++ = INTVAL (el) < 0 ? -1 : 0; | |
5207 | break; | |
48e1416a | 5208 | |
791172c5 | 5209 | case CONST_DOUBLE: |
5210 | if (GET_MODE (el) == VOIDmode) | |
5211 | { | |
db20fb47 | 5212 | unsigned char extend = 0; |
791172c5 | 5213 | /* If this triggers, someone should have generated a |
5214 | CONST_INT instead. */ | |
04e579b6 | 5215 | gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT); |
ead34f59 | 5216 | |
791172c5 | 5217 | for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) |
5218 | *vp++ = CONST_DOUBLE_LOW (el) >> i; | |
5219 | while (i < HOST_BITS_PER_WIDE_INT * 2 && i < elem_bitsize) | |
5220 | { | |
f24bf586 | 5221 | *vp++ |
5222 | = CONST_DOUBLE_HIGH (el) >> (i - HOST_BITS_PER_WIDE_INT); | |
791172c5 | 5223 | i += value_bit; |
5224 | } | |
db20fb47 | 5225 | |
5226 | if (CONST_DOUBLE_HIGH (el) >> (HOST_BITS_PER_WIDE_INT - 1)) | |
5227 | extend = -1; | |
1088b1d1 | 5228 | for (; i < elem_bitsize; i += value_bit) |
db20fb47 | 5229 | *vp++ = extend; |
791172c5 | 5230 | } |
04e579b6 | 5231 | else |
20407c42 | 5232 | { |
791172c5 | 5233 | long tmp[max_bitsize / 32]; |
5234 | int bitsize = GET_MODE_BITSIZE (GET_MODE (el)); | |
04e579b6 | 5235 | |
cee7491d | 5236 | gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (el))); |
04e579b6 | 5237 | gcc_assert (bitsize <= elem_bitsize); |
5238 | gcc_assert (bitsize % value_bit == 0); | |
791172c5 | 5239 | |
5240 | real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el), | |
5241 | GET_MODE (el)); | |
5242 | ||
5243 | /* real_to_target produces its result in words affected by | |
5244 | FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, | |
5245 | and use WORDS_BIG_ENDIAN instead; see the documentation | |
5246 | of SUBREG in rtl.texi. */ | |
5247 | for (i = 0; i < bitsize; i += value_bit) | |
ee4124f3 | 5248 | { |
791172c5 | 5249 | int ibase; |
5250 | if (WORDS_BIG_ENDIAN) | |
5251 | ibase = bitsize - 1 - i; | |
5252 | else | |
5253 | ibase = i; | |
5254 | *vp++ = tmp[ibase / 32] >> i % 32; | |
ee4124f3 | 5255 | } |
48e1416a | 5256 | |
791172c5 | 5257 | /* It shouldn't matter what's done here, so fill it with |
5258 | zero. */ | |
5259 | for (; i < elem_bitsize; i += value_bit) | |
5260 | *vp++ = 0; | |
20407c42 | 5261 | } |
791172c5 | 5262 | break; |
b563b483 | 5263 | |
5264 | case CONST_FIXED: | |
5265 | if (elem_bitsize <= HOST_BITS_PER_WIDE_INT) | |
5266 | { | |
5267 | for (i = 0; i < elem_bitsize; i += value_bit) | |
5268 | *vp++ = CONST_FIXED_VALUE_LOW (el) >> i; | |
5269 | } | |
5270 | else | |
5271 | { | |
5272 | for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit) | |
5273 | *vp++ = CONST_FIXED_VALUE_LOW (el) >> i; | |
5274 | for (; i < 2 * HOST_BITS_PER_WIDE_INT && i < elem_bitsize; | |
5275 | i += value_bit) | |
5276 | *vp++ = CONST_FIXED_VALUE_HIGH (el) | |
5277 | >> (i - HOST_BITS_PER_WIDE_INT); | |
5278 | for (; i < elem_bitsize; i += value_bit) | |
5279 | *vp++ = 0; | |
5280 | } | |
5281 | break; | |
48e1416a | 5282 | |
791172c5 | 5283 | default: |
04e579b6 | 5284 | gcc_unreachable (); |
ee4124f3 | 5285 | } |
ead34f59 | 5286 | } |
5287 | ||
791172c5 | 5288 | /* Now, pick the right byte to start with. */ |
5289 | /* Renumber BYTE so that the least-significant byte is byte 0. A special | |
5290 | case is paradoxical SUBREGs, which shouldn't be adjusted since they | |
5291 | will already have offset 0. */ | |
5292 | if (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode)) | |
64ab453f | 5293 | { |
02d7807a | 5294 | unsigned ibyte = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode) |
791172c5 | 5295 | - byte); |
5296 | unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
5297 | unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
5298 | byte = (subword_byte % UNITS_PER_WORD | |
5299 | + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
5300 | } | |
64ab453f | 5301 | |
791172c5 | 5302 | /* BYTE should still be inside OP. (Note that BYTE is unsigned, |
5303 | so if it's become negative it will instead be very large.) */ | |
04e579b6 | 5304 | gcc_assert (byte < GET_MODE_SIZE (innermode)); |
4867a033 | 5305 | |
791172c5 | 5306 | /* Convert from bytes to chunks of size value_bit. */ |
5307 | value_start = byte * (BITS_PER_UNIT / value_bit); | |
64ab453f | 5308 | |
791172c5 | 5309 | /* Re-pack the value. */ |
48e1416a | 5310 | |
791172c5 | 5311 | if (VECTOR_MODE_P (outermode)) |
5312 | { | |
5313 | num_elem = GET_MODE_NUNITS (outermode); | |
5314 | result_v = rtvec_alloc (num_elem); | |
5315 | elems = &RTVEC_ELT (result_v, 0); | |
5316 | outer_submode = GET_MODE_INNER (outermode); | |
5317 | } | |
5318 | else | |
5319 | { | |
5320 | num_elem = 1; | |
5321 | elems = &result_s; | |
5322 | outer_submode = outermode; | |
5323 | } | |
64ab453f | 5324 | |
791172c5 | 5325 | outer_class = GET_MODE_CLASS (outer_submode); |
5326 | elem_bitsize = GET_MODE_BITSIZE (outer_submode); | |
c736a837 | 5327 | |
04e579b6 | 5328 | gcc_assert (elem_bitsize % value_bit == 0); |
5329 | gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize); | |
c736a837 | 5330 | |
791172c5 | 5331 | for (elem = 0; elem < num_elem; elem++) |
5332 | { | |
5333 | unsigned char *vp; | |
48e1416a | 5334 | |
791172c5 | 5335 | /* Vectors are stored in target memory order. (This is probably |
5336 | a mistake.) */ | |
5337 | { | |
5338 | unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT; | |
02d7807a | 5339 | unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize) |
791172c5 | 5340 | / BITS_PER_UNIT); |
5341 | unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte; | |
5342 | unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte; | |
5343 | unsigned bytele = (subword_byte % UNITS_PER_WORD | |
5344 | + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD); | |
5345 | vp = value + value_start + (bytele * BITS_PER_UNIT) / value_bit; | |
5346 | } | |
5347 | ||
5348 | switch (outer_class) | |
64ab453f | 5349 | { |
791172c5 | 5350 | case MODE_INT: |
5351 | case MODE_PARTIAL_INT: | |
5352 | { | |
5353 | unsigned HOST_WIDE_INT hi = 0, lo = 0; | |
5354 | ||
5355 | for (i = 0; | |
5356 | i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; | |
5357 | i += value_bit) | |
23423d0e | 5358 | lo |= (unsigned HOST_WIDE_INT)(*vp++ & value_mask) << i; |
791172c5 | 5359 | for (; i < elem_bitsize; i += value_bit) |
23423d0e | 5360 | hi |= (unsigned HOST_WIDE_INT)(*vp++ & value_mask) |
5361 | << (i - HOST_BITS_PER_WIDE_INT); | |
48e1416a | 5362 | |
791172c5 | 5363 | /* immed_double_const doesn't call trunc_int_for_mode. I don't |
5364 | know why. */ | |
5365 | if (elem_bitsize <= HOST_BITS_PER_WIDE_INT) | |
5366 | elems[elem] = gen_int_mode (lo, outer_submode); | |
6e266ae6 | 5367 | else if (elem_bitsize <= 2 * HOST_BITS_PER_WIDE_INT) |
791172c5 | 5368 | elems[elem] = immed_double_const (lo, hi, outer_submode); |
6e266ae6 | 5369 | else |
5370 | return NULL_RTX; | |
791172c5 | 5371 | } |
5372 | break; | |
48e1416a | 5373 | |
791172c5 | 5374 | case MODE_FLOAT: |
069b07bf | 5375 | case MODE_DECIMAL_FLOAT: |
791172c5 | 5376 | { |
5377 | REAL_VALUE_TYPE r; | |
5378 | long tmp[max_bitsize / 32]; | |
48e1416a | 5379 | |
791172c5 | 5380 | /* real_from_target wants its input in words affected by |
5381 | FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, | |
5382 | and use WORDS_BIG_ENDIAN instead; see the documentation | |
5383 | of SUBREG in rtl.texi. */ | |
5384 | for (i = 0; i < max_bitsize / 32; i++) | |
5385 | tmp[i] = 0; | |
5386 | for (i = 0; i < elem_bitsize; i += value_bit) | |
5387 | { | |
5388 | int ibase; | |
5389 | if (WORDS_BIG_ENDIAN) | |
5390 | ibase = elem_bitsize - 1 - i; | |
5391 | else | |
5392 | ibase = i; | |
e67a84f3 | 5393 | tmp[ibase / 32] |= (*vp++ & value_mask) << i % 32; |
791172c5 | 5394 | } |
64ab453f | 5395 | |
791172c5 | 5396 | real_from_target (&r, tmp, outer_submode); |
5397 | elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode); | |
5398 | } | |
5399 | break; | |
b563b483 | 5400 | |
5401 | case MODE_FRACT: | |
5402 | case MODE_UFRACT: | |
5403 | case MODE_ACCUM: | |
5404 | case MODE_UACCUM: | |
5405 | { | |
5406 | FIXED_VALUE_TYPE f; | |
5407 | f.data.low = 0; | |
5408 | f.data.high = 0; | |
5409 | f.mode = outer_submode; | |
5410 | ||
5411 | for (i = 0; | |
5412 | i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize; | |
5413 | i += value_bit) | |
23423d0e | 5414 | f.data.low |= (unsigned HOST_WIDE_INT)(*vp++ & value_mask) << i; |
b563b483 | 5415 | for (; i < elem_bitsize; i += value_bit) |
23423d0e | 5416 | f.data.high |= ((unsigned HOST_WIDE_INT)(*vp++ & value_mask) |
b563b483 | 5417 | << (i - HOST_BITS_PER_WIDE_INT)); |
5418 | ||
5419 | elems[elem] = CONST_FIXED_FROM_FIXED_VALUE (f, outer_submode); | |
5420 | } | |
5421 | break; | |
48e1416a | 5422 | |
791172c5 | 5423 | default: |
04e579b6 | 5424 | gcc_unreachable (); |
791172c5 | 5425 | } |
5426 | } | |
5427 | if (VECTOR_MODE_P (outermode)) | |
5428 | return gen_rtx_CONST_VECTOR (outermode, result_v); | |
5429 | else | |
5430 | return result_s; | |
5431 | } | |
64ab453f | 5432 | |
791172c5 | 5433 | /* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE) |
5434 | Return 0 if no simplifications are possible. */ | |
5435 | rtx | |
5436 | simplify_subreg (enum machine_mode outermode, rtx op, | |
5437 | enum machine_mode innermode, unsigned int byte) | |
5438 | { | |
5439 | /* Little bit of sanity checking. */ | |
04e579b6 | 5440 | gcc_assert (innermode != VOIDmode); |
5441 | gcc_assert (outermode != VOIDmode); | |
5442 | gcc_assert (innermode != BLKmode); | |
5443 | gcc_assert (outermode != BLKmode); | |
64ab453f | 5444 | |
04e579b6 | 5445 | gcc_assert (GET_MODE (op) == innermode |
5446 | || GET_MODE (op) == VOIDmode); | |
64ab453f | 5447 | |
04e579b6 | 5448 | gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0); |
5449 | gcc_assert (byte < GET_MODE_SIZE (innermode)); | |
64ab453f | 5450 | |
791172c5 | 5451 | if (outermode == innermode && !byte) |
5452 | return op; | |
64ab453f | 5453 | |
971ba038 | 5454 | if (CONST_INT_P (op) |
791172c5 | 5455 | || GET_CODE (op) == CONST_DOUBLE |
b563b483 | 5456 | || GET_CODE (op) == CONST_FIXED |
791172c5 | 5457 | || GET_CODE (op) == CONST_VECTOR) |
5458 | return simplify_immed_subreg (outermode, op, innermode, byte); | |
64ab453f | 5459 | |
5460 | /* Changing mode twice with SUBREG => just change it once, | |
5461 | or not at all if changing back op starting mode. */ | |
5462 | if (GET_CODE (op) == SUBREG) | |
5463 | { | |
5464 | enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); | |
47c066cb | 5465 | int final_offset = byte + SUBREG_BYTE (op); |
1ae4d088 | 5466 | rtx newx; |
64ab453f | 5467 | |
5468 | if (outermode == innermostmode | |
5469 | && byte == 0 && SUBREG_BYTE (op) == 0) | |
5470 | return SUBREG_REG (op); | |
5471 | ||
47c066cb | 5472 | /* The SUBREG_BYTE represents offset, as if the value were stored |
5473 | in memory. Irritating exception is paradoxical subreg, where | |
5474 | we define SUBREG_BYTE to be 0. On big endian machines, this | |
1be87b72 | 5475 | value should be negative. For a moment, undo this exception. */ |
47c066cb | 5476 | if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) |
64ab453f | 5477 | { |
47c066cb | 5478 | int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); |
5479 | if (WORDS_BIG_ENDIAN) | |
5480 | final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; | |
5481 | if (BYTES_BIG_ENDIAN) | |
5482 | final_offset += difference % UNITS_PER_WORD; | |
5483 | } | |
5484 | if (SUBREG_BYTE (op) == 0 | |
5485 | && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) | |
5486 | { | |
5487 | int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); | |
5488 | if (WORDS_BIG_ENDIAN) | |
5489 | final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; | |
5490 | if (BYTES_BIG_ENDIAN) | |
5491 | final_offset += difference % UNITS_PER_WORD; | |
5492 | } | |
5493 | ||
5494 | /* See whether resulting subreg will be paradoxical. */ | |
f996f8fd | 5495 | if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode)) |
47c066cb | 5496 | { |
5497 | /* In nonparadoxical subregs we can't handle negative offsets. */ | |
5498 | if (final_offset < 0) | |
5499 | return NULL_RTX; | |
5500 | /* Bail out in case resulting subreg would be incorrect. */ | |
5501 | if (final_offset % GET_MODE_SIZE (outermode) | |
97b330ca | 5502 | || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode)) |
5503 | return NULL_RTX; | |
47c066cb | 5504 | } |
5505 | else | |
5506 | { | |
5507 | int offset = 0; | |
5508 | int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode)); | |
5509 | ||
5510 | /* In paradoxical subreg, see if we are still looking on lower part. | |
5511 | If so, our SUBREG_BYTE will be 0. */ | |
5512 | if (WORDS_BIG_ENDIAN) | |
5513 | offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; | |
5514 | if (BYTES_BIG_ENDIAN) | |
5515 | offset += difference % UNITS_PER_WORD; | |
5516 | if (offset == final_offset) | |
5517 | final_offset = 0; | |
64ab453f | 5518 | else |
97b330ca | 5519 | return NULL_RTX; |
64ab453f | 5520 | } |
5521 | ||
917bbcab | 5522 | /* Recurse for further possible simplifications. */ |
2166bbaa | 5523 | newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode, |
5524 | final_offset); | |
1ae4d088 | 5525 | if (newx) |
5526 | return newx; | |
2166bbaa | 5527 | if (validate_subreg (outermode, innermostmode, |
5528 | SUBREG_REG (op), final_offset)) | |
ad76ccf5 | 5529 | { |
5530 | newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset); | |
5531 | if (SUBREG_PROMOTED_VAR_P (op) | |
5532 | && SUBREG_PROMOTED_UNSIGNED_P (op) >= 0 | |
5533 | && GET_MODE_CLASS (outermode) == MODE_INT | |
5534 | && IN_RANGE (GET_MODE_SIZE (outermode), | |
5535 | GET_MODE_SIZE (innermode), | |
5536 | GET_MODE_SIZE (innermostmode)) | |
5537 | && subreg_lowpart_p (newx)) | |
5538 | { | |
5539 | SUBREG_PROMOTED_VAR_P (newx) = 1; | |
5540 | SUBREG_PROMOTED_UNSIGNED_SET | |
5541 | (newx, SUBREG_PROMOTED_UNSIGNED_P (op)); | |
5542 | } | |
5543 | return newx; | |
5544 | } | |
2166bbaa | 5545 | return NULL_RTX; |
64ab453f | 5546 | } |
5547 | ||
2ec9725b | 5548 | /* Merge implicit and explicit truncations. */ |
5549 | ||
5550 | if (GET_CODE (op) == TRUNCATE | |
5551 | && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (innermode) | |
5552 | && subreg_lowpart_offset (outermode, innermode) == byte) | |
5553 | return simplify_gen_unary (TRUNCATE, outermode, XEXP (op, 0), | |
5554 | GET_MODE (XEXP (op, 0))); | |
5555 | ||
64ab453f | 5556 | /* SUBREG of a hard register => just change the register number |
5557 | and/or mode. If the hard register is not valid in that mode, | |
5558 | suppress this simplification. If the hard register is the stack, | |
5559 | frame, or argument pointer, leave this as a SUBREG. */ | |
5560 | ||
5992d16a | 5561 | if (REG_P (op) && HARD_REGISTER_P (op)) |
64ab453f | 5562 | { |
5992d16a | 5563 | unsigned int regno, final_regno; |
5564 | ||
5565 | regno = REGNO (op); | |
5566 | final_regno = simplify_subreg_regno (regno, innermode, byte, outermode); | |
5567 | if (HARD_REGISTER_NUM_P (final_regno)) | |
06b3c9f7 | 5568 | { |
9a8a3ff4 | 5569 | rtx x; |
5570 | int final_offset = byte; | |
5571 | ||
5572 | /* Adjust offset for paradoxical subregs. */ | |
5573 | if (byte == 0 | |
5574 | && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) | |
5575 | { | |
5576 | int difference = (GET_MODE_SIZE (innermode) | |
5577 | - GET_MODE_SIZE (outermode)); | |
5578 | if (WORDS_BIG_ENDIAN) | |
5579 | final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; | |
5580 | if (BYTES_BIG_ENDIAN) | |
5581 | final_offset += difference % UNITS_PER_WORD; | |
5582 | } | |
5583 | ||
5584 | x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); | |
06b3c9f7 | 5585 | |
5586 | /* Propagate original regno. We don't have any way to specify | |
de132707 | 5587 | the offset inside original regno, so do so only for lowpart. |
06b3c9f7 | 5588 | The information is used only by alias analysis that can not |
5589 | grog partial register anyway. */ | |
5590 | ||
5591 | if (subreg_lowpart_offset (outermode, innermode) == byte) | |
5592 | ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op); | |
5593 | return x; | |
5594 | } | |
64ab453f | 5595 | } |
5596 | ||
5597 | /* If we have a SUBREG of a register that we are replacing and we are | |
5598 | replacing it with a MEM, make a new MEM and try replacing the | |
5599 | SUBREG with it. Don't do this if the MEM has a mode-dependent address | |
5600 | or if we would be widening it. */ | |
5601 | ||
e16ceb8e | 5602 | if (MEM_P (op) |
64ab453f | 5603 | && ! mode_dependent_address_p (XEXP (op, 0)) |
ced2face | 5604 | /* Allow splitting of volatile memory references in case we don't |
5605 | have instruction to move the whole thing. */ | |
5606 | && (! MEM_VOLATILE_P (op) | |
ad99e708 | 5607 | || ! have_insn_for (SET, innermode)) |
64ab453f | 5608 | && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op))) |
e4e86ec5 | 5609 | return adjust_address_nv (op, outermode, byte); |
09f800b9 | 5610 | |
5611 | /* Handle complex values represented as CONCAT | |
5612 | of real and imaginary part. */ | |
5613 | if (GET_CODE (op) == CONCAT) | |
5614 | { | |
f28bdbe8 | 5615 | unsigned int part_size, final_offset; |
2b701a08 | 5616 | rtx part, res; |
5617 | ||
f28bdbe8 | 5618 | part_size = GET_MODE_UNIT_SIZE (GET_MODE (XEXP (op, 0))); |
5619 | if (byte < part_size) | |
5620 | { | |
5621 | part = XEXP (op, 0); | |
5622 | final_offset = byte; | |
5623 | } | |
5624 | else | |
5625 | { | |
5626 | part = XEXP (op, 1); | |
5627 | final_offset = byte - part_size; | |
5628 | } | |
5629 | ||
5630 | if (final_offset + GET_MODE_SIZE (outermode) > part_size) | |
2b701a08 | 5631 | return NULL_RTX; |
09f800b9 | 5632 | |
ddf7cbcf | 5633 | res = simplify_subreg (outermode, part, GET_MODE (part), final_offset); |
5634 | if (res) | |
5635 | return res; | |
2166bbaa | 5636 | if (validate_subreg (outermode, GET_MODE (part), part, final_offset)) |
2b701a08 | 5637 | return gen_rtx_SUBREG (outermode, part, final_offset); |
2166bbaa | 5638 | return NULL_RTX; |
09f800b9 | 5639 | } |
5640 | ||
f36eb1e9 | 5641 | /* Optimize SUBREG truncations of zero and sign extended values. */ |
5642 | if ((GET_CODE (op) == ZERO_EXTEND | |
5643 | || GET_CODE (op) == SIGN_EXTEND) | |
23068d35 | 5644 | && SCALAR_INT_MODE_P (innermode) |
ded805e6 | 5645 | && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)) |
f36eb1e9 | 5646 | { |
5647 | unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); | |
5648 | ||
5649 | /* If we're requesting the lowpart of a zero or sign extension, | |
5650 | there are three possibilities. If the outermode is the same | |
5651 | as the origmode, we can omit both the extension and the subreg. | |
5652 | If the outermode is not larger than the origmode, we can apply | |
5653 | the truncation without the extension. Finally, if the outermode | |
5654 | is larger than the origmode, but both are integer modes, we | |
5655 | can just extend to the appropriate mode. */ | |
5656 | if (bitpos == 0) | |
5657 | { | |
5658 | enum machine_mode origmode = GET_MODE (XEXP (op, 0)); | |
5659 | if (outermode == origmode) | |
5660 | return XEXP (op, 0); | |
ded805e6 | 5661 | if (GET_MODE_PRECISION (outermode) <= GET_MODE_PRECISION (origmode)) |
deb45e60 | 5662 | return simplify_gen_subreg (outermode, XEXP (op, 0), origmode, |
5663 | subreg_lowpart_offset (outermode, | |
5664 | origmode)); | |
f36eb1e9 | 5665 | if (SCALAR_INT_MODE_P (outermode)) |
5666 | return simplify_gen_unary (GET_CODE (op), outermode, | |
5667 | XEXP (op, 0), origmode); | |
5668 | } | |
5669 | ||
5670 | /* A SUBREG resulting from a zero extension may fold to zero if | |
5671 | it extracts higher bits that the ZERO_EXTEND's source bits. */ | |
5672 | if (GET_CODE (op) == ZERO_EXTEND | |
ded805e6 | 5673 | && bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))) |
f36eb1e9 | 5674 | return CONST0_RTX (outermode); |
5675 | } | |
5676 | ||
5a1be574 | 5677 | /* Simplify (subreg:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C), 0) into |
5678 | to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and | |
5679 | the outer subreg is effectively a truncation to the original mode. */ | |
5680 | if ((GET_CODE (op) == LSHIFTRT | |
5681 | || GET_CODE (op) == ASHIFTRT) | |
5682 | && SCALAR_INT_MODE_P (outermode) | |
23068d35 | 5683 | && SCALAR_INT_MODE_P (innermode) |
5a1be574 | 5684 | /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE |
5685 | to avoid the possibility that an outer LSHIFTRT shifts by more | |
5686 | than the sign extension's sign_bit_copies and introduces zeros | |
5687 | into the high bits of the result. */ | |
ded805e6 | 5688 | && (2 * GET_MODE_PRECISION (outermode)) <= GET_MODE_PRECISION (innermode) |
971ba038 | 5689 | && CONST_INT_P (XEXP (op, 1)) |
5a1be574 | 5690 | && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND |
5691 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode | |
ded805e6 | 5692 | && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) |
5a1be574 | 5693 | && subreg_lsb_1 (outermode, innermode, byte) == 0) |
5694 | return simplify_gen_binary (ASHIFTRT, outermode, | |
5695 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); | |
5696 | ||
5697 | /* Likewise (subreg:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C), 0) into | |
5698 | to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and | |
5699 | the outer subreg is effectively a truncation to the original mode. */ | |
5700 | if ((GET_CODE (op) == LSHIFTRT | |
5701 | || GET_CODE (op) == ASHIFTRT) | |
5702 | && SCALAR_INT_MODE_P (outermode) | |
23068d35 | 5703 | && SCALAR_INT_MODE_P (innermode) |
ded805e6 | 5704 | && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode) |
971ba038 | 5705 | && CONST_INT_P (XEXP (op, 1)) |
5a1be574 | 5706 | && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND |
5707 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode | |
ded805e6 | 5708 | && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) |
5a1be574 | 5709 | && subreg_lsb_1 (outermode, innermode, byte) == 0) |
5710 | return simplify_gen_binary (LSHIFTRT, outermode, | |
5711 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); | |
5712 | ||
5713 | /* Likewise (subreg:QI (ashift:SI (zero_extend:SI (x:QI)) C), 0) into | |
5714 | to (ashift:QI (x:QI) C), where C is a suitable small constant and | |
5715 | the outer subreg is effectively a truncation to the original mode. */ | |
5716 | if (GET_CODE (op) == ASHIFT | |
5717 | && SCALAR_INT_MODE_P (outermode) | |
23068d35 | 5718 | && SCALAR_INT_MODE_P (innermode) |
ded805e6 | 5719 | && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode) |
971ba038 | 5720 | && CONST_INT_P (XEXP (op, 1)) |
5a1be574 | 5721 | && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND |
5722 | || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) | |
5723 | && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode | |
ded805e6 | 5724 | && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) |
5a1be574 | 5725 | && subreg_lsb_1 (outermode, innermode, byte) == 0) |
5726 | return simplify_gen_binary (ASHIFT, outermode, | |
5727 | XEXP (XEXP (op, 0), 0), XEXP (op, 1)); | |
5728 | ||
8178351b | 5729 | /* Recognize a word extraction from a multi-word subreg. */ |
5730 | if ((GET_CODE (op) == LSHIFTRT | |
5731 | || GET_CODE (op) == ASHIFTRT) | |
23068d35 | 5732 | && SCALAR_INT_MODE_P (innermode) |
ded805e6 | 5733 | && GET_MODE_PRECISION (outermode) >= BITS_PER_WORD |
5734 | && GET_MODE_PRECISION (innermode) >= (2 * GET_MODE_PRECISION (outermode)) | |
971ba038 | 5735 | && CONST_INT_P (XEXP (op, 1)) |
ded805e6 | 5736 | && (INTVAL (XEXP (op, 1)) & (GET_MODE_PRECISION (outermode) - 1)) == 0 |
59d15e1f | 5737 | && INTVAL (XEXP (op, 1)) >= 0 |
ded805e6 | 5738 | && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (innermode) |
8178351b | 5739 | && byte == subreg_lowpart_offset (outermode, innermode)) |
5740 | { | |
5741 | int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; | |
5742 | return simplify_gen_subreg (outermode, XEXP (op, 0), innermode, | |
5743 | (WORDS_BIG_ENDIAN | |
59d15e1f | 5744 | ? byte - shifted_bytes |
5745 | : byte + shifted_bytes)); | |
8178351b | 5746 | } |
5747 | ||
abb1ab9c | 5748 | /* If we have a lowpart SUBREG of a right shift of MEM, make a new MEM |
5749 | and try replacing the SUBREG and shift with it. Don't do this if | |
5750 | the MEM has a mode-dependent address or if we would be widening it. */ | |
5751 | ||
5752 | if ((GET_CODE (op) == LSHIFTRT | |
5753 | || GET_CODE (op) == ASHIFTRT) | |
23068d35 | 5754 | && SCALAR_INT_MODE_P (innermode) |
abb1ab9c | 5755 | && MEM_P (XEXP (op, 0)) |
5756 | && CONST_INT_P (XEXP (op, 1)) | |
5757 | && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (GET_MODE (op)) | |
5758 | && (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (outermode)) == 0 | |
5759 | && INTVAL (XEXP (op, 1)) > 0 | |
5760 | && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (innermode) | |
5761 | && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0)) | |
5762 | && ! MEM_VOLATILE_P (XEXP (op, 0)) | |
5763 | && byte == subreg_lowpart_offset (outermode, innermode) | |
5764 | && (GET_MODE_SIZE (outermode) >= UNITS_PER_WORD | |
5765 | || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)) | |
5766 | { | |
5767 | int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; | |
5768 | return adjust_address_nv (XEXP (op, 0), outermode, | |
5769 | (WORDS_BIG_ENDIAN | |
5770 | ? byte - shifted_bytes | |
5771 | : byte + shifted_bytes)); | |
5772 | } | |
5773 | ||
64ab453f | 5774 | return NULL_RTX; |
5775 | } | |
791172c5 | 5776 | |
f760707b | 5777 | /* Make a SUBREG operation or equivalent if it folds. */ |
5778 | ||
5779 | rtx | |
60b8c5b3 | 5780 | simplify_gen_subreg (enum machine_mode outermode, rtx op, |
5781 | enum machine_mode innermode, unsigned int byte) | |
f760707b | 5782 | { |
1ae4d088 | 5783 | rtx newx; |
f760707b | 5784 | |
1ae4d088 | 5785 | newx = simplify_subreg (outermode, op, innermode, byte); |
5786 | if (newx) | |
5787 | return newx; | |
f760707b | 5788 | |
2b701a08 | 5789 | if (GET_CODE (op) == SUBREG |
5790 | || GET_CODE (op) == CONCAT | |
5791 | || GET_MODE (op) == VOIDmode) | |
f760707b | 5792 | return NULL_RTX; |
5793 | ||
2166bbaa | 5794 | if (validate_subreg (outermode, innermode, op, byte)) |
5795 | return gen_rtx_SUBREG (outermode, op, byte); | |
5796 | ||
5797 | return NULL_RTX; | |
f760707b | 5798 | } |
2166bbaa | 5799 | |
af21a202 | 5800 | /* Simplify X, an rtx expression. |
5801 | ||
5802 | Return the simplified expression or NULL if no simplifications | |
5803 | were possible. | |
5804 | ||
5805 | This is the preferred entry point into the simplification routines; | |
5806 | however, we still allow passes to call the more specific routines. | |
5807 | ||
de132707 | 5808 | Right now GCC has three (yes, three) major bodies of RTL simplification |
af21a202 | 5809 | code that need to be unified. |
5810 | ||
5811 | 1. fold_rtx in cse.c. This code uses various CSE specific | |
5812 | information to aid in RTL simplification. | |
5813 | ||
5814 | 2. simplify_rtx in combine.c. Similar to fold_rtx, except that | |
5815 | it uses combine specific information to aid in RTL | |
5816 | simplification. | |
5817 | ||
5818 | 3. The routines in this file. | |
5819 | ||
5820 | ||
5821 | Long term we want to only have one body of simplification code; to | |
5822 | get to that state I recommend the following steps: | |
5823 | ||
5824 | 1. Pour over fold_rtx & simplify_rtx and move any simplifications | |
5825 | which are not pass dependent state into these routines. | |
5826 | ||
5827 | 2. As code is moved by #1, change fold_rtx & simplify_rtx to | |
5828 | use this routine whenever possible. | |
5829 | ||
5830 | 3. Allow for pass dependent state to be provided to these | |
5831 | routines and add simplifications based on the pass dependent | |
5832 | state. Remove code from cse.c & combine.c that becomes | |
5833 | redundant/dead. | |
5834 | ||
5835 | It will take time, but ultimately the compiler will be easier to | |
5836 | maintain and improve. It's totally silly that when we add a | |
5837 | simplification that it needs to be added to 4 places (3 for RTL | |
5838 | simplification and 1 for tree simplification. */ | |
40734805 | 5839 | |
af21a202 | 5840 | rtx |
9f627b1a | 5841 | simplify_rtx (const_rtx x) |
af21a202 | 5842 | { |
9f627b1a | 5843 | const enum rtx_code code = GET_CODE (x); |
5844 | const enum machine_mode mode = GET_MODE (x); | |
af21a202 | 5845 | |
5846 | switch (GET_RTX_CLASS (code)) | |
5847 | { | |
6720e96c | 5848 | case RTX_UNARY: |
af21a202 | 5849 | return simplify_unary_operation (code, mode, |
5850 | XEXP (x, 0), GET_MODE (XEXP (x, 0))); | |
6720e96c | 5851 | case RTX_COMM_ARITH: |
84842e6a | 5852 | if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) |
3c309555 | 5853 | return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0)); |
196e03f1 | 5854 | |
ca1fae79 | 5855 | /* Fall through.... */ |
196e03f1 | 5856 | |
6720e96c | 5857 | case RTX_BIN_ARITH: |
af21a202 | 5858 | return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); |
5859 | ||
6720e96c | 5860 | case RTX_TERNARY: |
5861 | case RTX_BITFIELD_OPS: | |
af21a202 | 5862 | return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)), |
53cb61a7 | 5863 | XEXP (x, 0), XEXP (x, 1), |
5864 | XEXP (x, 2)); | |
af21a202 | 5865 | |
6720e96c | 5866 | case RTX_COMPARE: |
5867 | case RTX_COMM_COMPARE: | |
ac503e50 | 5868 | return simplify_relational_operation (code, mode, |
5869 | ((GET_MODE (XEXP (x, 0)) | |
5870 | != VOIDmode) | |
5871 | ? GET_MODE (XEXP (x, 0)) | |
5872 | : GET_MODE (XEXP (x, 1))), | |
5873 | XEXP (x, 0), | |
5874 | XEXP (x, 1)); | |
fccafeb4 | 5875 | |
6720e96c | 5876 | case RTX_EXTRA: |
f760707b | 5877 | if (code == SUBREG) |
068ca2c8 | 5878 | return simplify_subreg (mode, SUBREG_REG (x), |
5879 | GET_MODE (SUBREG_REG (x)), | |
5880 | SUBREG_BYTE (x)); | |
fccafeb4 | 5881 | break; |
5882 | ||
6720e96c | 5883 | case RTX_OBJ: |
fccafeb4 | 5884 | if (code == LO_SUM) |
5885 | { | |
5886 | /* Convert (lo_sum (high FOO) FOO) to FOO. */ | |
5887 | if (GET_CODE (XEXP (x, 0)) == HIGH | |
5888 | && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) | |
5889 | return XEXP (x, 1); | |
5890 | } | |
5891 | break; | |
5892 | ||
af21a202 | 5893 | default: |
fccafeb4 | 5894 | break; |
af21a202 | 5895 | } |
fccafeb4 | 5896 | return NULL; |
af21a202 | 5897 | } |