OSDN Git Service

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