OSDN Git Service

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