OSDN Git Service

2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / dojump.c
1 /* Convert tree expression to rtl instructions, for GNU compiler.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
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
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
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"
36 #include "ggc.h"
37 #include "basic-block.h"
38
39 static bool prefer_and_bit_test (enum machine_mode, int);
40 static void do_jump_by_parts_greater (tree, int, rtx, rtx);
41 static void do_jump_by_parts_equality (tree, rtx, rtx);
42 static void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx,
43                                  rtx);
44
45 /* At the start of a function, record that we have no previously-pushed
46    arguments waiting to be popped.  */
47
48 void
49 init_pending_stack_adjust (void)
50 {
51   pending_stack_adjust = 0;
52 }
53
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.  */
57 void
58 discard_pending_stack_adjust (void)
59 {
60   stack_pointer_delta -= pending_stack_adjust;
61   pending_stack_adjust = 0;
62 }
63
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
70 void
71 clear_pending_stack_adjust (void)
72 {
73   if (optimize > 0
74       && (! flag_omit_frame_pointer || cfun->calls_alloca)
75       && EXIT_IGNORE_STACK)
76     discard_pending_stack_adjust ();
77 }
78
79 /* Pop any previously-pushed arguments that have not been popped yet.  */
80
81 void
82 do_pending_stack_adjust (void)
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
98 void
99 jumpifnot (tree exp, rtx label)
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
106 void
107 jumpif (tree exp, rtx label)
108 {
109   do_jump (exp, NULL_RTX, label);
110 }
111
112 /* Used internally by prefer_and_bit_test.  */
113
114 static GTY(()) rtx and_reg;
115 static GTY(()) rtx and_test;
116 static 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
122 static bool
123 prefer_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.  */
144   XEXP (and_test, 1)
145     = immed_double_const ((unsigned HOST_WIDE_INT) 1 << bitnum, 0, mode);
146   XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
147
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 ()));
150 }
151
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
159    is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.  */
160
161 void
162 do_jump (tree exp, rtx if_false_label, rtx if_true_label)
163 {
164   enum tree_code code = TREE_CODE (exp);
165   rtx temp;
166   int i;
167   tree type;
168   enum machine_mode mode;
169   rtx drop_through_label = 0;
170
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:
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
212     case TRUTH_NOT_EXPR:
213       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
214       break;
215
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
236     case COMPOUND_EXPR:
237       /* Lowered by gimplify.c.  */
238       gcc_unreachable ();
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,
255                              &unsignedp, &volatilep, false);
256
257         type = lang_hooks.types.type_for_size (bitsize, unsignedp);
258         if (! SLOW_BYTE_ACCESS
259             && type != 0 && bitsize >= 0
260             && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
261             && have_insn_for (COMPARE, TYPE_MODE (type)))
262           {
263             do_jump (fold_convert (type, exp), if_false_label, if_true_label);
264             break;
265           }
266         goto normal;
267       }
268
269     case EQ_EXPR:
270       {
271         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
272
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)))
279           do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
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
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 */
294     case NE_EXPR:
295       {
296         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
297
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)))
304           do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
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
349     case ORDERED_EXPR:
350       do_compare_and_jump (exp, ORDERED, ORDERED,
351                            if_false_label, if_true_label);
352       break;
353
354     case UNORDERED_EXPR:
355       do_compare_and_jump (exp, UNORDERED, UNORDERED,
356                            if_false_label, if_true_label);
357       break;
358
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);
381       break;
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                 {
424                   unsigned HOST_WIDE_INT mask
425                     = (unsigned HOST_WIDE_INT) 1 << TREE_INT_CST_LOW (shift);
426                   do_jump (build2 (BIT_AND_EXPR, argtype, arg,
427                                    build_int_cst_wide_type (argtype, mask, 0)),
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))
448           && have_insn_for (COMPARE, TYPE_MODE (type)))
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.  */
459
460     case TRUTH_AND_EXPR:
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.  */
464       if (BRANCH_COST (optimize_insn_for_speed_p (),
465                        false) >= 4
466           || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
467         goto normal;
468
469     case TRUTH_ANDIF_EXPR:
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
483     case BIT_IOR_EXPR:
484     case TRUTH_OR_EXPR:
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.  */
488       if (BRANCH_COST (optimize_insn_for_speed_p (), false)>= 4
489           || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
490         goto normal;
491
492     case TRUTH_ORIF_EXPR:
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
506       /* Fall through and generate the normal code.  */
507     default:
508     normal:
509       temp = expand_normal (exp);
510       do_pending_stack_adjust ();
511       /* The RTL optimizers prefer comparisons against pseudos.  */
512       if (GET_CODE (temp) == SUBREG)
513         {
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);
520         }
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);
525     }
526
527   if (drop_through_label)
528     {
529       do_pending_stack_adjust ();
530       emit_label (drop_through_label);
531     }
532 }
533 \f
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
538 static void
539 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
540                               rtx op1, rtx if_false_label, rtx if_true_label)
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 }
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
590 static void
591 do_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 }
602 \f
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.  */
607
608 static void
609 do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
610                            rtx if_false_label, rtx if_true_label)
611 {
612   int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
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);
623   emit_move_insn (part, operand_subword_force (op0, 0, mode));
624   for (i = 1; i < nwords && part != 0; i++)
625     part = expand_binop (word_mode, ior_optab, part,
626                          operand_subword_force (op0, i, mode),
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++)
642     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
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 }
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
658 static void
659 do_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
695 static void
696 do_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 }
704 \f
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
713 bool
714 split_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
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
789 void
790 do_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)
793 {
794   rtx tem;
795   rtx dummy_label = NULL_RTX;
796
797   /* Reverse the comparison if that is safe and we want to jump if it is
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))))
806     {
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         }
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
835   do_pending_stack_adjust ();
836
837   code = unsignedp ? unsigned_condition (code) : code;
838   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
839                                                  op0, op1)))
840     {
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         }
849
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);
855     }
856
857   if (! if_true_label)
858     dummy_label = if_true_label = gen_label_rtx ();
859
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
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
885         case LT:
886           do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
887                                         if_false_label, if_true_label);
888           break;
889
890         case LE:
891           do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
892                                         if_true_label, if_false_label);
893           break;
894
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
920     {
921       if (GET_MODE_CLASS (mode) == MODE_FLOAT
922           && ! can_compare_p (code, mode, ccp_jump)
923           && can_compare_p (swap_condition (code), mode, ccp_jump))
924         {
925           rtx tmp;
926           code = swap_condition (code);
927           tmp = op0;
928           op0 = op1;
929           op1 = tmp;
930         }
931
932       else if (GET_MODE_CLASS (mode) == MODE_FLOAT
933                && ! can_compare_p (code, mode, ccp_jump)
934
935                /* Never split ORDERED and UNORDERED.  These must be implemented.  */
936                && (code != ORDERED && code != UNORDERED)
937
938                /* Split a floating-point comparison if we can jump on other
939                   conditions...  */
940                && (have_insn_for (COMPARE, mode)
941
942                    /* ... or if there is no libcall for it.  */
943                    || code_to_optab[code] == NULL))
944         {
945           enum rtx_code first_code;
946           bool and_them = split_comparison (code, mode, &first_code, &code);
947
948           /* If there are no NaNs, the first comparison should always fall
949              through.  */
950           if (!HONOR_NANS (mode))
951             gcc_assert (first_code == (and_them ? ORDERED : UNORDERED));
952
953           else
954             {
955               if (and_them)
956                 {
957                   rtx dest_label;
958                   /* If we only jump if true, just bypass the second jump.  */
959                   if (! if_false_label)
960                     {
961                       if (! dummy_label)
962                         dummy_label = gen_label_rtx ();
963                       dest_label = dummy_label;
964                     }
965                   else
966                     dest_label = if_false_label;
967                   do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
968                                            size, dest_label, NULL_RTX);
969                 }
970               else
971                 do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
972                                          size, NULL_RTX, if_true_label);
973             }
974         }
975
976       emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
977                                if_true_label);
978     }
979
980   if (if_false_label)
981     emit_jump (if_false_label);
982   if (dummy_label)
983     emit_label (dummy_label);
984 }
985
986 /* Generate code for a comparison expression EXP (including code to compute
987    the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
988    IF_TRUE_LABEL.  One of the labels can be NULL_RTX, in which case the
989    generated code will drop through.
990    SIGNED_CODE should be the rtx operation for this comparison for
991    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
992
993    We force a stack adjustment unless there are currently
994    things pushed on the stack that aren't yet used.  */
995
996 static void
997 do_compare_and_jump (tree exp, enum rtx_code signed_code,
998                      enum rtx_code unsigned_code, rtx if_false_label,
999                      rtx if_true_label)
1000 {
1001   rtx op0, op1;
1002   tree type;
1003   enum machine_mode mode;
1004   int unsignedp;
1005   enum rtx_code code;
1006
1007   /* Don't crash if the comparison was erroneous.  */
1008   op0 = expand_normal (TREE_OPERAND (exp, 0));
1009   if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
1010     return;
1011
1012   op1 = expand_normal (TREE_OPERAND (exp, 1));
1013   if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
1014     return;
1015
1016   type = TREE_TYPE (TREE_OPERAND (exp, 0));
1017   mode = TYPE_MODE (type);
1018   if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
1019       && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
1020           || (GET_MODE_BITSIZE (mode)
1021               > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
1022                                                                       1)))))))
1023     {
1024       /* op0 might have been replaced by promoted constant, in which
1025          case the type of second argument should be used.  */
1026       type = TREE_TYPE (TREE_OPERAND (exp, 1));
1027       mode = TYPE_MODE (type);
1028     }
1029   unsignedp = TYPE_UNSIGNED (type);
1030   code = unsignedp ? unsigned_code : signed_code;
1031
1032 #ifdef HAVE_canonicalize_funcptr_for_compare
1033   /* If function pointers need to be "canonicalized" before they can
1034      be reliably compared, then canonicalize them.
1035      Only do this if *both* sides of the comparison are function pointers.
1036      If one side isn't, we want a noncanonicalized comparison.  See PR
1037      middle-end/17564.  */
1038   if (HAVE_canonicalize_funcptr_for_compare
1039       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
1040       && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1041           == FUNCTION_TYPE
1042       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
1043       && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
1044           == FUNCTION_TYPE)
1045     {
1046       rtx new_op0 = gen_reg_rtx (mode);
1047       rtx new_op1 = gen_reg_rtx (mode);
1048
1049       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
1050       op0 = new_op0;
1051
1052       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
1053       op1 = new_op1;
1054     }
1055 #endif
1056
1057   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
1058                            ((mode == BLKmode)
1059                             ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
1060                            if_false_label, if_true_label);
1061 }
1062
1063 #include "gt-dojump.h"