]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dojump.c
* simplify-rtx.c (simplify_subreg): Combine SUBREG and TRUNCATE.
[thirdparty/gcc.git] / gcc / dojump.c
CommitLineData
1cff8964
AE
1/* Convert tree expression to rtl instructions, for GNU compiler.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
feb04780 3 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
1cff8964
AE
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
366ccddb
KC
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA. */
1cff8964
AE
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "rtl.h"
27#include "tree.h"
28#include "flags.h"
29#include "function.h"
30#include "insn-config.h"
31#include "insn-attr.h"
32/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
33#include "expr.h"
34#include "optabs.h"
35#include "langhooks.h"
dbf833ee 36#include "ggc.h"
1cff8964 37
dbf833ee 38static bool prefer_and_bit_test (enum machine_mode, int);
7080f735
AJ
39static void do_jump_by_parts_greater (tree, int, rtx, rtx);
40static void do_jump_by_parts_equality (tree, rtx, rtx);
41static void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx,
42 rtx);
1cff8964
AE
43
44/* At the start of a function, record that we have no previously-pushed
45 arguments waiting to be popped. */
46
47void
7080f735 48init_pending_stack_adjust (void)
1cff8964
AE
49{
50 pending_stack_adjust = 0;
51}
52
a494ed43
EB
53/* Discard any pending stack adjustment. This avoid relying on the
54 RTL optimizers to remove useless adjustments when we know the
55 stack pointer value is dead. */
56void discard_pending_stack_adjust (void)
57{
58 stack_pointer_delta -= pending_stack_adjust;
59 pending_stack_adjust = 0;
60}
61
1cff8964
AE
62/* When exiting from function, if safe, clear out any pending stack adjust
63 so the adjustment won't get done.
64
65 Note, if the current function calls alloca, then it must have a
66 frame pointer regardless of the value of flag_omit_frame_pointer. */
67
68void
7080f735 69clear_pending_stack_adjust (void)
1cff8964 70{
1cff8964
AE
71 if (optimize > 0
72 && (! flag_omit_frame_pointer || current_function_calls_alloca)
73 && EXIT_IGNORE_STACK
39afeb1a 74 && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline))
a494ed43 75 discard_pending_stack_adjust ();
1cff8964
AE
76}
77
78/* Pop any previously-pushed arguments that have not been popped yet. */
79
80void
7080f735 81do_pending_stack_adjust (void)
1cff8964
AE
82{
83 if (inhibit_defer_pop == 0)
84 {
85 if (pending_stack_adjust != 0)
86 adjust_stack (GEN_INT (pending_stack_adjust));
87 pending_stack_adjust = 0;
88 }
89}
90\f
91/* Expand conditional expressions. */
92
93/* Generate code to evaluate EXP and jump to LABEL if the value is zero.
94 LABEL is an rtx of code CODE_LABEL, in this function and all the
95 functions here. */
96
97void
7080f735 98jumpifnot (tree exp, rtx label)
1cff8964
AE
99{
100 do_jump (exp, label, NULL_RTX);
101}
102
103/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
104
105void
7080f735 106jumpif (tree exp, rtx label)
1cff8964
AE
107{
108 do_jump (exp, NULL_RTX, label);
109}
110
dbf833ee
RS
111/* Used internally by prefer_and_bit_test. */
112
113static GTY(()) rtx and_reg;
114static GTY(()) rtx and_test;
115static GTY(()) rtx shift_test;
116
117/* Compare the relative costs of "(X & (1 << BITNUM))" and "(X >> BITNUM) & 1",
118 where X is an arbitrary register of mode MODE. Return true if the former
119 is preferred. */
120
121static bool
122prefer_and_bit_test (enum machine_mode mode, int bitnum)
123{
124 if (and_test == 0)
125 {
126 /* Set up rtxes for the two variations. Use NULL as a placeholder
127 for the BITNUM-based constants. */
128 and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER);
129 and_test = gen_rtx_AND (mode, and_reg, NULL);
130 shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL),
131 const1_rtx);
132 }
133 else
134 {
135 /* Change the mode of the previously-created rtxes. */
136 PUT_MODE (and_reg, mode);
137 PUT_MODE (and_test, mode);
138 PUT_MODE (shift_test, mode);
139 PUT_MODE (XEXP (shift_test, 0), mode);
140 }
141
142 /* Fill in the integers. */
0f005f33 143 XEXP (and_test, 1) = GEN_INT ((unsigned HOST_WIDE_INT) 1 << bitnum);
dbf833ee
RS
144 XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
145
146 return (rtx_cost (and_test, IF_THEN_ELSE)
147 <= rtx_cost (shift_test, IF_THEN_ELSE));
148}
149
1cff8964
AE
150/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
151 the result is zero, or IF_TRUE_LABEL if the result is one.
152 Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
153 meaning fall through in that case.
154
155 do_jump always does any pending stack adjust except when it does not
156 actually perform a jump. An example where there is no jump
6aaf3dde 157 is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null. */
1cff8964
AE
158
159void
7080f735 160do_jump (tree exp, rtx if_false_label, rtx if_true_label)
1cff8964
AE
161{
162 enum tree_code code = TREE_CODE (exp);
1cff8964
AE
163 rtx temp;
164 int i;
165 tree type;
166 enum machine_mode mode;
8ea9d0c7 167 rtx drop_through_label = 0;
1cff8964 168
1cff8964
AE
169 switch (code)
170 {
171 case ERROR_MARK:
172 break;
173
174 case INTEGER_CST:
175 temp = integer_zerop (exp) ? if_false_label : if_true_label;
176 if (temp)
177 emit_jump (temp);
178 break;
179
180#if 0
181 /* This is not true with #pragma weak */
182 case ADDR_EXPR:
183 /* The address of something can never be zero. */
184 if (if_true_label)
185 emit_jump (if_true_label);
186 break;
187#endif
188
189 case NOP_EXPR:
190 if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
191 || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
192 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
193 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
194 goto normal;
195 case CONVERT_EXPR:
196 /* If we are narrowing the operand, we have to do the compare in the
197 narrower mode. */
198 if ((TYPE_PRECISION (TREE_TYPE (exp))
199 < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
200 goto normal;
201 case NON_LVALUE_EXPR:
1cff8964
AE
202 case ABS_EXPR:
203 case NEGATE_EXPR:
204 case LROTATE_EXPR:
205 case RROTATE_EXPR:
206 /* These cannot change zero->nonzero or vice versa. */
207 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
208 break;
209
1cff8964 210 case BIT_AND_EXPR:
dbf833ee
RS
211 /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
212 See if the former is preferred for jump tests and restore it
213 if so. */
3e5bcef3 214 if (integer_onep (TREE_OPERAND (exp, 1)))
dbf833ee 215 {
3e5bcef3
RS
216 tree exp0 = TREE_OPERAND (exp, 0);
217 rtx set_label, clr_label;
218
219 /* Strip narrowing integral type conversions. */
220 while ((TREE_CODE (exp0) == NOP_EXPR
221 || TREE_CODE (exp0) == CONVERT_EXPR
222 || TREE_CODE (exp0) == NON_LVALUE_EXPR)
223 && TREE_OPERAND (exp0, 0) != error_mark_node
224 && TYPE_PRECISION (TREE_TYPE (exp0))
225 <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
226 exp0 = TREE_OPERAND (exp0, 0);
227
228 /* "exp0 ^ 1" inverts the sense of the single bit test. */
229 if (TREE_CODE (exp0) == BIT_XOR_EXPR
230 && integer_onep (TREE_OPERAND (exp0, 1)))
dbf833ee 231 {
3e5bcef3
RS
232 exp0 = TREE_OPERAND (exp0, 0);
233 clr_label = if_true_label;
234 set_label = if_false_label;
235 }
236 else
237 {
238 clr_label = if_false_label;
239 set_label = if_true_label;
240 }
241
242 if (TREE_CODE (exp0) == RSHIFT_EXPR)
243 {
244 tree arg = TREE_OPERAND (exp0, 0);
245 tree shift = TREE_OPERAND (exp0, 1);
246 tree argtype = TREE_TYPE (arg);
247 if (TREE_CODE (shift) == INTEGER_CST
248 && compare_tree_int (shift, 0) >= 0
249 && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
250 && prefer_and_bit_test (TYPE_MODE (argtype),
251 TREE_INT_CST_LOW (shift)))
252 {
253 HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
254 << TREE_INT_CST_LOW (shift);
255 do_jump (build2 (BIT_AND_EXPR, argtype, arg,
256 build_int_cst_type (argtype, mask)),
257 clr_label, set_label);
258 break;
259 }
dbf833ee
RS
260 }
261 }
262
1cff8964
AE
263 /* If we are AND'ing with a small constant, do this comparison in the
264 smallest type that fits. If the machine doesn't have comparisons
265 that small, it will be converted back to the wider comparison.
266 This helps if we are testing the sign bit of a narrower object.
267 combine can't do this for us because it can't know whether a
268 ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */
269
270 if (! SLOW_BYTE_ACCESS
271 && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
272 && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
273 && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
274 && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
ae2bcd98 275 && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
1cff8964
AE
276 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
277 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
278 != CODE_FOR_nothing))
279 {
280 do_jump (convert (type, exp), if_false_label, if_true_label);
281 break;
282 }
283 goto normal;
284
285 case TRUTH_NOT_EXPR:
286 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
287 break;
288
8ea9d0c7
PB
289 case COND_EXPR:
290 {
291 rtx label1 = gen_label_rtx ();
292 if (!if_true_label || !if_false_label)
293 {
294 drop_through_label = gen_label_rtx ();
295 if (!if_true_label)
296 if_true_label = drop_through_label;
297 if (!if_false_label)
298 if_false_label = drop_through_label;
299 }
300
301 do_pending_stack_adjust ();
302 do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
303 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
304 emit_label (label1);
305 do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label);
306 break;
307 }
308
1cff8964 309 case TRUTH_ANDIF_EXPR:
1cff8964 310 case TRUTH_ORIF_EXPR:
1cff8964 311 case COMPOUND_EXPR:
7c27e184 312 /* Lowered by gimplify.c. */
ced3f397 313 gcc_unreachable ();
1cff8964
AE
314
315 case COMPONENT_REF:
316 case BIT_FIELD_REF:
317 case ARRAY_REF:
318 case ARRAY_RANGE_REF:
319 {
320 HOST_WIDE_INT bitsize, bitpos;
321 int unsignedp;
322 enum machine_mode mode;
323 tree type;
324 tree offset;
325 int volatilep = 0;
326
327 /* Get description of this reference. We don't actually care
328 about the underlying object here. */
329 get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
2614034e 330 &unsignedp, &volatilep, false);
1cff8964 331
ae2bcd98 332 type = lang_hooks.types.type_for_size (bitsize, unsignedp);
1cff8964
AE
333 if (! SLOW_BYTE_ACCESS
334 && type != 0 && bitsize >= 0
335 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
336 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
59068a89 337 != CODE_FOR_nothing))
1cff8964
AE
338 {
339 do_jump (convert (type, exp), if_false_label, if_true_label);
340 break;
341 }
342 goto normal;
343 }
344
1cff8964
AE
345 case EQ_EXPR:
346 {
347 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
348
ced3f397
NS
349 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
350 != MODE_COMPLEX_FLOAT);
351 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
352 != MODE_COMPLEX_INT);
353
354 if (integer_zerop (TREE_OPERAND (exp, 1)))
1cff8964 355 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
1cff8964
AE
356 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
357 && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
358 do_jump_by_parts_equality (exp, if_false_label, if_true_label);
359 else
360 do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
361 break;
362 }
363
0b04d281
DE
364 case MINUS_EXPR:
365 /* Nonzero iff operands of minus differ. */
366 exp = build2 (NE_EXPR, TREE_TYPE (exp),
367 TREE_OPERAND (exp, 0),
368 TREE_OPERAND (exp, 1));
369 /* FALLTHRU */
1cff8964
AE
370 case NE_EXPR:
371 {
372 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
373
ced3f397
NS
374 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
375 != MODE_COMPLEX_FLOAT);
376 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
377 != MODE_COMPLEX_INT);
378
379 if (integer_zerop (TREE_OPERAND (exp, 1)))
1cff8964 380 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
1cff8964
AE
381 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
382 && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
383 do_jump_by_parts_equality (exp, if_true_label, if_false_label);
384 else
385 do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
386 break;
387 }
388
389 case LT_EXPR:
390 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
391 if (GET_MODE_CLASS (mode) == MODE_INT
392 && ! can_compare_p (LT, mode, ccp_jump))
393 do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
394 else
395 do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
396 break;
397
398 case LE_EXPR:
399 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
400 if (GET_MODE_CLASS (mode) == MODE_INT
401 && ! can_compare_p (LE, mode, ccp_jump))
402 do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
403 else
404 do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
405 break;
406
407 case GT_EXPR:
408 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
409 if (GET_MODE_CLASS (mode) == MODE_INT
410 && ! can_compare_p (GT, mode, ccp_jump))
411 do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
412 else
413 do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
414 break;
415
416 case GE_EXPR:
417 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
418 if (GET_MODE_CLASS (mode) == MODE_INT
419 && ! can_compare_p (GE, mode, ccp_jump))
420 do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
421 else
422 do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
423 break;
424
425 case UNORDERED_EXPR:
426 case ORDERED_EXPR:
427 {
428 enum rtx_code cmp, rcmp;
429 int do_rev;
430
431 if (code == UNORDERED_EXPR)
432 cmp = UNORDERED, rcmp = ORDERED;
433 else
434 cmp = ORDERED, rcmp = UNORDERED;
435 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
436
437 do_rev = 0;
438 if (! can_compare_p (cmp, mode, ccp_jump)
439 && (can_compare_p (rcmp, mode, ccp_jump)
440 /* If the target doesn't provide either UNORDERED or ORDERED
441 comparisons, canonicalize on UNORDERED for the library. */
442 || rcmp == UNORDERED))
443 do_rev = 1;
444
445 if (! do_rev)
446 do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
447 else
448 do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
449 }
450 break;
451
452 {
453 enum rtx_code rcode1;
14bbffa1 454 enum tree_code tcode1, tcode2;
1cff8964
AE
455
456 case UNLT_EXPR:
457 rcode1 = UNLT;
14bbffa1 458 tcode1 = UNORDERED_EXPR;
1cff8964
AE
459 tcode2 = LT_EXPR;
460 goto unordered_bcc;
461 case UNLE_EXPR:
462 rcode1 = UNLE;
14bbffa1 463 tcode1 = UNORDERED_EXPR;
1cff8964
AE
464 tcode2 = LE_EXPR;
465 goto unordered_bcc;
466 case UNGT_EXPR:
467 rcode1 = UNGT;
14bbffa1 468 tcode1 = UNORDERED_EXPR;
1cff8964
AE
469 tcode2 = GT_EXPR;
470 goto unordered_bcc;
471 case UNGE_EXPR:
472 rcode1 = UNGE;
14bbffa1 473 tcode1 = UNORDERED_EXPR;
1cff8964
AE
474 tcode2 = GE_EXPR;
475 goto unordered_bcc;
476 case UNEQ_EXPR:
477 rcode1 = UNEQ;
14bbffa1 478 tcode1 = UNORDERED_EXPR;
1cff8964
AE
479 tcode2 = EQ_EXPR;
480 goto unordered_bcc;
d1a7edaf
PB
481 case LTGT_EXPR:
482 /* It is ok for LTGT_EXPR to trap when the result is unordered,
483 so expand to (a < b) || (a > b). */
484 rcode1 = LTGT;
485 tcode1 = LT_EXPR;
486 tcode2 = GT_EXPR;
487 goto unordered_bcc;
1cff8964
AE
488
489 unordered_bcc:
490 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
491 if (can_compare_p (rcode1, mode, ccp_jump))
492 do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
493 if_true_label);
494 else
495 {
496 tree op0 = save_expr (TREE_OPERAND (exp, 0));
497 tree op1 = save_expr (TREE_OPERAND (exp, 1));
498 tree cmp0, cmp1;
499
500 /* If the target doesn't support combined unordered
d1a7edaf 501 compares, decompose into two comparisons. */
6aaf3dde
ZW
502 if (if_true_label == 0)
503 drop_through_label = if_true_label = gen_label_rtx ();
504
4845b383
KH
505 cmp0 = fold_build2 (tcode1, TREE_TYPE (exp), op0, op1);
506 cmp1 = fold_build2 (tcode2, TREE_TYPE (exp), op0, op1);
6aaf3dde
ZW
507 do_jump (cmp0, 0, if_true_label);
508 do_jump (cmp1, if_false_label, if_true_label);
1cff8964
AE
509 }
510 }
511 break;
512
d1f36c51 513 case TRUTH_AND_EXPR:
97191ef9
PB
514 /* High branch cost, expand as the bitwise AND of the conditions.
515 Do the same if the RHS has side effects, because we're effectively
516 turning a TRUTH_AND_EXPR into a TRUTH_ANDIF_EXPR. */
517 if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
d1f36c51
PB
518 goto normal;
519
520 if (if_false_label == NULL_RTX)
521 {
522 drop_through_label = gen_label_rtx ();
523 do_jump (TREE_OPERAND (exp, 0), drop_through_label, NULL_RTX);
524 do_jump (TREE_OPERAND (exp, 1), NULL_RTX, if_true_label);
525 }
526 else
527 {
528 do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
529 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
530 }
531 break;
532
533 case TRUTH_OR_EXPR:
97191ef9
PB
534 /* High branch cost, expand as the bitwise OR of the conditions.
535 Do the same if the RHS has side effects, because we're effectively
536 turning a TRUTH_OR_EXPR into a TRUTH_ORIF_EXPR. */
537 if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
d1f36c51
PB
538 goto normal;
539
540 if (if_true_label == NULL_RTX)
541 {
542 drop_through_label = gen_label_rtx ();
543 do_jump (TREE_OPERAND (exp, 0), NULL_RTX, drop_through_label);
544 do_jump (TREE_OPERAND (exp, 1), if_false_label, NULL_RTX);
545 }
546 else
547 {
548 do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
549 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
550 }
551 break;
552
1cff8964
AE
553 /* Special case:
554 __builtin_expect (<test>, 0) and
555 __builtin_expect (<test>, 1)
556
557 We need to do this here, so that <test> is not converted to a SCC
558 operation on machines that use condition code registers and COMPARE
559 like the PowerPC, and then the jump is done based on whether the SCC
560 operation produced a 1 or 0. */
561 case CALL_EXPR:
562 /* Check for a built-in function. */
2f503025
JM
563 {
564 tree fndecl = get_callee_fndecl (exp);
565 tree arglist = TREE_OPERAND (exp, 1);
566
567 if (fndecl
8c96cd51 568 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2f503025
JM
569 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
570 && arglist != NULL_TREE
571 && TREE_CHAIN (arglist) != NULL_TREE)
572 {
573 rtx seq = expand_builtin_expect_jump (exp, if_false_label,
574 if_true_label);
575
576 if (seq != NULL_RTX)
577 {
578 emit_insn (seq);
579 return;
580 }
581 }
582 }
d1f36c51 583
938d968e 584 /* Fall through and generate the normal code. */
1cff8964
AE
585 default:
586 normal:
84217346 587 temp = expand_normal (exp);
1cff8964 588 do_pending_stack_adjust ();
feb04780
RS
589 /* The RTL optimizers prefer comparisons against pseudos. */
590 if (GET_CODE (temp) == SUBREG)
9311f3f6 591 {
feb04780
RS
592 /* Compare promoted variables in their promoted mode. */
593 if (SUBREG_PROMOTED_VAR_P (temp)
594 && REG_P (XEXP (temp, 0)))
595 temp = XEXP (temp, 0);
596 else
597 temp = copy_to_reg (temp);
9311f3f6 598 }
feb04780
RS
599 do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
600 NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
601 GET_MODE (temp), NULL_RTX,
602 if_false_label, if_true_label);
1cff8964 603 }
8ea9d0c7
PB
604
605 if (drop_through_label)
606 {
607 do_pending_stack_adjust ();
608 emit_label (drop_through_label);
609 }
1cff8964
AE
610}
611\f
1cff8964
AE
612/* Compare OP0 with OP1, word at a time, in mode MODE.
613 UNSIGNEDP says to do unsigned comparison.
614 Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise. */
615
3bf78d3b 616static void
7080f735
AJ
617do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
618 rtx op1, rtx if_false_label, rtx if_true_label)
1cff8964
AE
619{
620 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
621 rtx drop_through_label = 0;
622 int i;
623
624 if (! if_true_label || ! if_false_label)
625 drop_through_label = gen_label_rtx ();
626 if (! if_true_label)
627 if_true_label = drop_through_label;
628 if (! if_false_label)
629 if_false_label = drop_through_label;
630
631 /* Compare a word at a time, high order first. */
632 for (i = 0; i < nwords; i++)
633 {
634 rtx op0_word, op1_word;
635
636 if (WORDS_BIG_ENDIAN)
637 {
638 op0_word = operand_subword_force (op0, i, mode);
639 op1_word = operand_subword_force (op1, i, mode);
640 }
641 else
642 {
643 op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
644 op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
645 }
646
647 /* All but high-order word must be compared as unsigned. */
648 do_compare_rtx_and_jump (op0_word, op1_word, GT,
649 (unsignedp || i > 0), word_mode, NULL_RTX,
650 NULL_RTX, if_true_label);
651
652 /* Consider lower words only if these are equal. */
653 do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
654 NULL_RTX, NULL_RTX, if_false_label);
655 }
656
657 if (if_false_label)
658 emit_jump (if_false_label);
659 if (drop_through_label)
660 emit_label (drop_through_label);
661}
3bf78d3b
RS
662
663/* Given a comparison expression EXP for values too wide to be compared
664 with one insn, test the comparison and jump to the appropriate label.
665 The code of EXP is ignored; we always test GT if SWAP is 0,
666 and LT if SWAP is 1. */
667
668static void
669do_jump_by_parts_greater (tree exp, int swap, rtx if_false_label,
670 rtx if_true_label)
671{
672 rtx op0 = expand_normal (TREE_OPERAND (exp, swap));
673 rtx op1 = expand_normal (TREE_OPERAND (exp, !swap));
674 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
675 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
676
677 do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
678 if_true_label);
679}
1cff8964 680\f
feb04780
RS
681/* Jump according to whether OP0 is 0. We assume that OP0 has an integer
682 mode, MODE, that is too wide for the available compare insns. Either
683 Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX
684 to indicate drop through. */
1cff8964 685
feb04780
RS
686static void
687do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
688 rtx if_false_label, rtx if_true_label)
1cff8964 689{
feb04780 690 int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
1cff8964
AE
691 rtx part;
692 int i;
693 rtx drop_through_label = 0;
694
695 /* The fastest way of doing this comparison on almost any machine is to
696 "or" all the words and compare the result. If all have to be loaded
697 from memory and this is a very wide item, it's possible this may
698 be slower, but that's highly unlikely. */
699
700 part = gen_reg_rtx (word_mode);
701 emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
702 for (i = 1; i < nwords && part != 0; i++)
703 part = expand_binop (word_mode, ior_optab, part,
704 operand_subword_force (op0, i, GET_MODE (op0)),
705 part, 1, OPTAB_WIDEN);
706
707 if (part != 0)
708 {
709 do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
710 NULL_RTX, if_false_label, if_true_label);
711
712 return;
713 }
714
715 /* If we couldn't do the "or" simply, do this with a series of compares. */
716 if (! if_false_label)
717 drop_through_label = if_false_label = gen_label_rtx ();
718
719 for (i = 0; i < nwords; i++)
720 do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
721 const0_rtx, EQ, 1, word_mode, NULL_RTX,
722 if_false_label, NULL_RTX);
723
724 if (if_true_label)
725 emit_jump (if_true_label);
726
727 if (drop_through_label)
728 emit_label (drop_through_label);
729}
feb04780
RS
730
731/* Test for the equality of two RTX expressions OP0 and OP1 in mode MODE,
732 where MODE is an integer mode too wide to be compared with one insn.
733 Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX
734 to indicate drop through. */
735
736static void
737do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
738 rtx if_false_label, rtx if_true_label)
739{
740 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
741 rtx drop_through_label = 0;
742 int i;
743
744 if (op1 == const0_rtx)
745 {
746 do_jump_by_parts_zero_rtx (mode, op0, if_false_label, if_true_label);
747 return;
748 }
749 else if (op0 == const0_rtx)
750 {
751 do_jump_by_parts_zero_rtx (mode, op1, if_false_label, if_true_label);
752 return;
753 }
754
755 if (! if_false_label)
756 drop_through_label = if_false_label = gen_label_rtx ();
757
758 for (i = 0; i < nwords; i++)
759 do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
760 operand_subword_force (op1, i, mode),
761 EQ, 0, word_mode, NULL_RTX,
762 if_false_label, NULL_RTX);
763
764 if (if_true_label)
765 emit_jump (if_true_label);
766 if (drop_through_label)
767 emit_label (drop_through_label);
768}
769
770/* Given an EQ_EXPR expression EXP for values too wide to be compared
771 with one insn, test the comparison and jump to the appropriate label. */
772
773static void
774do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label)
775{
776 rtx op0 = expand_normal (TREE_OPERAND (exp, 0));
777 rtx op1 = expand_normal (TREE_OPERAND (exp, 1));
778 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
779 do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
780 if_true_label);
781}
1cff8964
AE
782\f
783/* Generate code for a comparison of OP0 and OP1 with rtx code CODE.
6da285d2
RS
784 MODE is the machine mode of the comparison, not of the result.
785 (including code to compute the values to be compared) and set CC0
786 according to the result. The decision as to signed or unsigned
787 comparison must be made by the caller.
1cff8964
AE
788
789 We force a stack adjustment unless there are currently
790 things pushed on the stack that aren't yet used.
791
792 If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
793 compared. */
794
795rtx
7080f735
AJ
796compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
797 enum machine_mode mode, rtx size)
1cff8964 798{
1cff8964
AE
799 rtx tem;
800
801 /* If one operand is constant, make it the second one. Only do this
802 if the other operand is not constant as well. */
803
804 if (swap_commutative_operands_p (op0, op1))
805 {
806 tem = op0;
807 op0 = op1;
808 op1 = tem;
809 code = swap_condition (code);
810 }
811
1cff8964
AE
812 do_pending_stack_adjust ();
813
c6fb08ad 814 code = unsignedp ? unsigned_condition (code) : code;
6da285d2
RS
815 tem = simplify_relational_operation (code, VOIDmode, mode, op0, op1);
816 if (tem)
1cff8964 817 {
c6fb08ad
PB
818 if (CONSTANT_P (tem))
819 return tem;
820
6da285d2
RS
821 if (COMPARISON_P (tem))
822 {
823 code = GET_CODE (tem);
824 op0 = XEXP (tem, 0);
825 op1 = XEXP (tem, 1);
826 mode = GET_MODE (op0);
827 unsignedp = (code == GTU || code == LTU
828 || code == GEU || code == LEU);
829 }
1cff8964 830 }
1cff8964
AE
831
832 emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
833
834#if HAVE_cc0
835 return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
836#else
837 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
838#endif
839}
840
841/* Like do_compare_and_jump but expects the values to compare as two rtx's.
842 The decision as to signed or unsigned comparison must be made by the caller.
843
844 If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
845 compared. */
846
847void
7080f735
AJ
848do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
849 enum machine_mode mode, rtx size, rtx if_false_label,
850 rtx if_true_label)
1cff8964 851{
1cff8964
AE
852 rtx tem;
853 int dummy_true_label = 0;
854
855 /* Reverse the comparison if that is safe and we want to jump if it is
856 false. */
857 if (! if_true_label && ! FLOAT_MODE_P (mode))
858 {
859 if_true_label = if_false_label;
860 if_false_label = 0;
861 code = reverse_condition (code);
862 }
863
864 /* If one operand is constant, make it the second one. Only do this
865 if the other operand is not constant as well. */
866
867 if (swap_commutative_operands_p (op0, op1))
868 {
869 tem = op0;
870 op0 = op1;
871 op1 = tem;
872 code = swap_condition (code);
873 }
874
1cff8964
AE
875 do_pending_stack_adjust ();
876
c6fb08ad
PB
877 code = unsignedp ? unsigned_condition (code) : code;
878 if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
879 op0, op1)))
1cff8964 880 {
c6fb08ad
PB
881 if (CONSTANT_P (tem))
882 {
883 rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
884 ? if_false_label : if_true_label;
885 if (label)
886 emit_jump (label);
887 return;
888 }
1cff8964 889
c6fb08ad
PB
890 code = GET_CODE (tem);
891 mode = GET_MODE (tem);
892 op0 = XEXP (tem, 0);
893 op1 = XEXP (tem, 1);
894 unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
1cff8964 895 }
1cff8964 896
feb04780 897
1cff8964
AE
898 if (! if_true_label)
899 {
900 dummy_true_label = 1;
901 if_true_label = gen_label_rtx ();
902 }
903
feb04780
RS
904 if (GET_MODE_CLASS (mode) == MODE_INT
905 && ! can_compare_p (code, mode, ccp_jump))
906 {
907 switch (code)
908 {
909 case LTU:
910 do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
911 if_false_label, if_true_label);
912 break;
913
914 case LEU:
915 do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
916 if_true_label, if_false_label);
917 break;
918
919 case LT:
920 do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
921 if_false_label, if_true_label);
922 break;
923
1dc5d842
RS
924 case LE:
925 do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
926 if_true_label, if_false_label);
927 break;
928
feb04780
RS
929 case GT:
930 do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
931 if_false_label, if_true_label);
932 break;
933
934 case GE:
935 do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
936 if_true_label, if_false_label);
937 break;
938
939 case EQ:
940 do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
941 if_true_label);
942 break;
943
944 case NE:
945 do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
946 if_false_label);
947 break;
948
949 default:
950 gcc_unreachable ();
951 }
952 }
953 else
954 emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
955 if_true_label);
1cff8964
AE
956
957 if (if_false_label)
958 emit_jump (if_false_label);
959 if (dummy_true_label)
960 emit_label (if_true_label);
961}
962
963/* Generate code for a comparison expression EXP (including code to compute
964 the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
965 IF_TRUE_LABEL. One of the labels can be NULL_RTX, in which case the
966 generated code will drop through.
967 SIGNED_CODE should be the rtx operation for this comparison for
968 signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
969
970 We force a stack adjustment unless there are currently
971 things pushed on the stack that aren't yet used. */
972
973static void
7080f735
AJ
974do_compare_and_jump (tree exp, enum rtx_code signed_code,
975 enum rtx_code unsigned_code, rtx if_false_label,
976 rtx if_true_label)
1cff8964
AE
977{
978 rtx op0, op1;
979 tree type;
980 enum machine_mode mode;
981 int unsignedp;
982 enum rtx_code code;
983
984 /* Don't crash if the comparison was erroneous. */
84217346 985 op0 = expand_normal (TREE_OPERAND (exp, 0));
1cff8964
AE
986 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
987 return;
988
84217346 989 op1 = expand_normal (TREE_OPERAND (exp, 1));
1cff8964
AE
990 if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
991 return;
992
993 type = TREE_TYPE (TREE_OPERAND (exp, 0));
994 mode = TYPE_MODE (type);
995 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
996 && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
997 || (GET_MODE_BITSIZE (mode)
998 > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
999 1)))))))
1000 {
1001 /* op0 might have been replaced by promoted constant, in which
1002 case the type of second argument should be used. */
1003 type = TREE_TYPE (TREE_OPERAND (exp, 1));
1004 mode = TYPE_MODE (type);
1005 }
8df83eae 1006 unsignedp = TYPE_UNSIGNED (type);
1cff8964
AE
1007 code = unsignedp ? unsigned_code : signed_code;
1008
1009#ifdef HAVE_canonicalize_funcptr_for_compare
1010 /* If function pointers need to be "canonicalized" before they can
b8c26d70
NN
1011 be reliably compared, then canonicalize them.
1012 Only do this if *both* sides of the comparison are function pointers.
1013 If one side isn't, we want a noncanonicalized comparison. See PR
6c6cfbfd 1014 middle-end/17564. */
1cff8964
AE
1015 if (HAVE_canonicalize_funcptr_for_compare
1016 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
b8c26d70
NN
1017 && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1018 == FUNCTION_TYPE
1019 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
1020 && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
1021 == FUNCTION_TYPE)
1cff8964
AE
1022 {
1023 rtx new_op0 = gen_reg_rtx (mode);
b8c26d70 1024 rtx new_op1 = gen_reg_rtx (mode);
1cff8964
AE
1025
1026 emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
1027 op0 = new_op0;
1cff8964
AE
1028
1029 emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
1030 op1 = new_op1;
1031 }
1032#endif
1033
1cff8964
AE
1034 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
1035 ((mode == BLKmode)
1036 ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
1037 if_false_label, if_true_label);
1038}
dbf833ee
RS
1039
1040#include "gt-dojump.h"