OSDN Git Service

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