OSDN Git Service

2009-06-28 Paolo Bonzini <bonzini@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
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     }
968
969   if (if_false_label)
970     emit_jump (if_false_label);
971   if (dummy_label)
972     emit_label (dummy_label);
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
985 static void
986 do_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)
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.  */
997   op0 = expand_normal (TREE_OPERAND (exp, 0));
998   if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
999     return;
1000
1001   op1 = expand_normal (TREE_OPERAND (exp, 1));
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     }
1018   unsignedp = TYPE_UNSIGNED (type);
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
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
1026      middle-end/17564.  */
1027   if (HAVE_canonicalize_funcptr_for_compare
1028       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
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)
1034     {
1035       rtx new_op0 = gen_reg_rtx (mode);
1036       rtx new_op1 = gen_reg_rtx (mode);
1037
1038       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
1039       op0 = new_op0;
1040
1041       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
1042       op1 = new_op1;
1043     }
1044 #endif
1045
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 }
1051
1052 #include "gt-dojump.h"