OSDN Git Service

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