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