OSDN Git Service

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