OSDN Git Service

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