OSDN Git Service

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