OSDN Git Service

2004-06-03 Chris Demetriou <cgd@broadcom.com>
[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 tcode1 = UNORDERED_EXPR, 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       case LTGT_EXPR:
551         /* It is ok for LTGT_EXPR to trap when the result is unordered,
552            so expand to (a < b) || (a > b).  */
553         rcode1 = LTGT;
554         tcode1 = LT_EXPR;
555         tcode2 = GT_EXPR;
556         goto unordered_bcc;
557
558       unordered_bcc:
559         mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
560         if (can_compare_p (rcode1, mode, ccp_jump))
561           do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
562                                if_true_label);
563         else
564           {
565             tree op0 = save_expr (TREE_OPERAND (exp, 0));
566             tree op1 = save_expr (TREE_OPERAND (exp, 1));
567             tree cmp0, cmp1;
568
569             /* If the target doesn't support combined unordered
570                compares, decompose into two comparisons.  */
571             cmp0 = fold (build (tcode1, TREE_TYPE (exp), op0, op1));
572             cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
573             exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
574             do_jump (exp, if_false_label, if_true_label);
575           }
576       }
577       break;
578
579       /* Special case:
580           __builtin_expect (<test>, 0)  and
581           __builtin_expect (<test>, 1)
582
583          We need to do this here, so that <test> is not converted to a SCC
584          operation on machines that use condition code registers and COMPARE
585          like the PowerPC, and then the jump is done based on whether the SCC
586          operation produced a 1 or 0.  */
587     case CALL_EXPR:
588       /* Check for a built-in function.  */
589       {
590         tree fndecl = get_callee_fndecl (exp);
591         tree arglist = TREE_OPERAND (exp, 1);
592
593         if (fndecl
594             && DECL_BUILT_IN (fndecl)
595             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
596             && arglist != NULL_TREE
597             && TREE_CHAIN (arglist) != NULL_TREE)
598           {
599             rtx seq = expand_builtin_expect_jump (exp, if_false_label,
600                                                   if_true_label);
601
602             if (seq != NULL_RTX)
603               {
604                 emit_insn (seq);
605                 return;
606               }
607           }
608       }
609       /* Fall through and generate the normal code.  */
610
611     default:
612     normal:
613       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
614 #if 0
615       /* This is not needed any more and causes poor code since it causes
616          comparisons and tests from non-SI objects to have different code
617          sequences.  */
618       /* Copy to register to avoid generating bad insns by cse
619          from (set (mem ...) (arithop))  (set (cc0) (mem ...)).  */
620       if (!cse_not_expected && GET_CODE (temp) == MEM)
621         temp = copy_to_reg (temp);
622 #endif
623       do_pending_stack_adjust ();
624       /* Do any postincrements in the expression that was tested.  */
625       emit_queue ();
626
627       if (GET_CODE (temp) == CONST_INT
628           || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
629           || GET_CODE (temp) == LABEL_REF)
630         {
631           rtx target = temp == const0_rtx ? if_false_label : if_true_label;
632           if (target)
633             emit_jump (target);
634         }
635       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
636                && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
637         /* Note swapping the labels gives us not-equal.  */
638         do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
639       else if (GET_MODE (temp) != VOIDmode)
640         {
641           /* The RTL optimizers prefer comparisons against pseudos.  */
642           if (GET_CODE (temp) == SUBREG)
643             {
644               /* Compare promoted variables in their promoted mode.  */
645               if (SUBREG_PROMOTED_VAR_P (temp)
646                   && GET_CODE (XEXP (temp, 0)) == REG)
647                 temp = XEXP (temp, 0);
648               else
649                 temp = copy_to_reg (temp);
650             }
651           do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
652                                    NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
653                                    GET_MODE (temp), NULL_RTX,
654                                    if_false_label, if_true_label);
655         }
656       else
657         abort ();
658     }
659
660   if (drop_through_label)
661     {
662       /* If do_jump produces code that might be jumped around,
663          do any stack adjusts from that code, before the place
664          where control merges in.  */
665       do_pending_stack_adjust ();
666       emit_label (drop_through_label);
667     }
668 }
669 \f
670 /* Given a comparison expression EXP for values too wide to be compared
671    with one insn, test the comparison and jump to the appropriate label.
672    The code of EXP is ignored; we always test GT if SWAP is 0,
673    and LT if SWAP is 1.  */
674
675 static void
676 do_jump_by_parts_greater (tree exp, int swap, rtx if_false_label,
677                           rtx if_true_label)
678 {
679   rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
680   rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
681   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
682   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
683
684   do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
685                                 if_true_label);
686 }
687
688 /* Compare OP0 with OP1, word at a time, in mode MODE.
689    UNSIGNEDP says to do unsigned comparison.
690    Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise.  */
691
692 void
693 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
694                               rtx op1, rtx if_false_label, rtx if_true_label)
695 {
696   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
697   rtx drop_through_label = 0;
698   int i;
699
700   if (! if_true_label || ! if_false_label)
701     drop_through_label = gen_label_rtx ();
702   if (! if_true_label)
703     if_true_label = drop_through_label;
704   if (! if_false_label)
705     if_false_label = drop_through_label;
706
707   /* Compare a word at a time, high order first.  */
708   for (i = 0; i < nwords; i++)
709     {
710       rtx op0_word, op1_word;
711
712       if (WORDS_BIG_ENDIAN)
713         {
714           op0_word = operand_subword_force (op0, i, mode);
715           op1_word = operand_subword_force (op1, i, mode);
716         }
717       else
718         {
719           op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
720           op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
721         }
722
723       /* All but high-order word must be compared as unsigned.  */
724       do_compare_rtx_and_jump (op0_word, op1_word, GT,
725                                (unsignedp || i > 0), word_mode, NULL_RTX,
726                                NULL_RTX, if_true_label);
727
728       /* Consider lower words only if these are equal.  */
729       do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
730                                NULL_RTX, NULL_RTX, if_false_label);
731     }
732
733   if (if_false_label)
734     emit_jump (if_false_label);
735   if (drop_through_label)
736     emit_label (drop_through_label);
737 }
738
739 /* Given an EQ_EXPR expression EXP for values too wide to be compared
740    with one insn, test the comparison and jump to the appropriate label.  */
741
742 static void
743 do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label)
744 {
745   rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
746   rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
747   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
748   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
749   int i;
750   rtx drop_through_label = 0;
751
752   if (! if_false_label)
753     drop_through_label = if_false_label = gen_label_rtx ();
754
755   for (i = 0; i < nwords; i++)
756     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
757                              operand_subword_force (op1, i, mode),
758                              EQ, TYPE_UNSIGNED (TREE_TYPE (exp)),
759                              word_mode, NULL_RTX, if_false_label, NULL_RTX);
760
761   if (if_true_label)
762     emit_jump (if_true_label);
763   if (drop_through_label)
764     emit_label (drop_through_label);
765 }
766 \f
767 /* Jump according to whether OP0 is 0.
768    We assume that OP0 has an integer mode that is too wide
769    for the available compare insns.  */
770
771 void
772 do_jump_by_parts_equality_rtx (rtx op0, rtx if_false_label, rtx if_true_label)
773 {
774   int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
775   rtx part;
776   int i;
777   rtx drop_through_label = 0;
778
779   /* The fastest way of doing this comparison on almost any machine is to
780      "or" all the words and compare the result.  If all have to be loaded
781      from memory and this is a very wide item, it's possible this may
782      be slower, but that's highly unlikely.  */
783
784   part = gen_reg_rtx (word_mode);
785   emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
786   for (i = 1; i < nwords && part != 0; i++)
787     part = expand_binop (word_mode, ior_optab, part,
788                          operand_subword_force (op0, i, GET_MODE (op0)),
789                          part, 1, OPTAB_WIDEN);
790
791   if (part != 0)
792     {
793       do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
794                                NULL_RTX, if_false_label, if_true_label);
795
796       return;
797     }
798
799   /* If we couldn't do the "or" simply, do this with a series of compares.  */
800   if (! if_false_label)
801     drop_through_label = if_false_label = gen_label_rtx ();
802
803   for (i = 0; i < nwords; i++)
804     do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
805                              const0_rtx, EQ, 1, word_mode, NULL_RTX,
806                              if_false_label, NULL_RTX);
807
808   if (if_true_label)
809     emit_jump (if_true_label);
810
811   if (drop_through_label)
812     emit_label (drop_through_label);
813 }
814 \f
815 /* Generate code for a comparison of OP0 and OP1 with rtx code CODE.
816    (including code to compute the values to be compared)
817    and set (CC0) according to the result.
818    The decision as to signed or unsigned comparison must be made by the caller.
819
820    We force a stack adjustment unless there are currently
821    things pushed on the stack that aren't yet used.
822
823    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
824    compared.  */
825
826 rtx
827 compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
828                   enum machine_mode mode, rtx size)
829 {
830   rtx tem;
831
832   /* If one operand is constant, make it the second one.  Only do this
833      if the other operand is not constant as well.  */
834
835   if (swap_commutative_operands_p (op0, op1))
836     {
837       tem = op0;
838       op0 = op1;
839       op1 = tem;
840       code = swap_condition (code);
841     }
842
843   if (flag_force_mem)
844     {
845       op0 = force_not_mem (op0);
846       op1 = force_not_mem (op1);
847     }
848
849   do_pending_stack_adjust ();
850
851   code = unsignedp ? unsigned_condition (code) : code;
852   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
853                                                  op0, op1)))
854     {
855       if (CONSTANT_P (tem))
856         return tem;
857
858       code = GET_CODE (tem);
859       mode = GET_MODE (tem);
860       op0 = XEXP (tem, 0);
861       op1 = XEXP (tem, 1);
862       unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
863     }
864
865   emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
866
867 #if HAVE_cc0
868   return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
869 #else
870   return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
871 #endif
872 }
873
874 /* Like do_compare_and_jump but expects the values to compare as two rtx's.
875    The decision as to signed or unsigned comparison must be made by the caller.
876
877    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
878    compared.  */
879
880 void
881 do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
882                          enum machine_mode mode, rtx size, rtx if_false_label,
883                          rtx if_true_label)
884 {
885   rtx tem;
886   int dummy_true_label = 0;
887
888   /* Reverse the comparison if that is safe and we want to jump if it is
889      false.  */
890   if (! if_true_label && ! FLOAT_MODE_P (mode))
891     {
892       if_true_label = if_false_label;
893       if_false_label = 0;
894       code = reverse_condition (code);
895     }
896
897   /* If one operand is constant, make it the second one.  Only do this
898      if the other operand is not constant as well.  */
899
900   if (swap_commutative_operands_p (op0, op1))
901     {
902       tem = op0;
903       op0 = op1;
904       op1 = tem;
905       code = swap_condition (code);
906     }
907
908   if (flag_force_mem)
909     {
910       op0 = force_not_mem (op0);
911       op1 = force_not_mem (op1);
912     }
913
914   do_pending_stack_adjust ();
915
916   code = unsignedp ? unsigned_condition (code) : code;
917   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
918                                                  op0, op1)))
919     {
920       if (CONSTANT_P (tem))
921         {
922           rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
923                       ? if_false_label : if_true_label;
924           if (label)
925             emit_jump (label);
926           return;
927         }
928
929       code = GET_CODE (tem);
930       mode = GET_MODE (tem);
931       op0 = XEXP (tem, 0);
932       op1 = XEXP (tem, 1);
933       unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
934     }
935
936   if (! if_true_label)
937     {
938       dummy_true_label = 1;
939       if_true_label = gen_label_rtx ();
940     }
941
942   emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
943                            if_true_label);
944
945   if (if_false_label)
946     emit_jump (if_false_label);
947   if (dummy_true_label)
948     emit_label (if_true_label);
949 }
950
951 /* Generate code for a comparison expression EXP (including code to compute
952    the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
953    IF_TRUE_LABEL.  One of the labels can be NULL_RTX, in which case the
954    generated code will drop through.
955    SIGNED_CODE should be the rtx operation for this comparison for
956    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
957
958    We force a stack adjustment unless there are currently
959    things pushed on the stack that aren't yet used.  */
960
961 static void
962 do_compare_and_jump (tree exp, enum rtx_code signed_code,
963                      enum rtx_code unsigned_code, rtx if_false_label,
964                      rtx if_true_label)
965 {
966   rtx op0, op1;
967   tree type;
968   enum machine_mode mode;
969   int unsignedp;
970   enum rtx_code code;
971
972   /* Don't crash if the comparison was erroneous.  */
973   op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
974   if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
975     return;
976
977   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
978   if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
979     return;
980
981   type = TREE_TYPE (TREE_OPERAND (exp, 0));
982   mode = TYPE_MODE (type);
983   if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
984       && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
985           || (GET_MODE_BITSIZE (mode)
986               > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
987                                                                       1)))))))
988     {
989       /* op0 might have been replaced by promoted constant, in which
990          case the type of second argument should be used.  */
991       type = TREE_TYPE (TREE_OPERAND (exp, 1));
992       mode = TYPE_MODE (type);
993     }
994   unsignedp = TYPE_UNSIGNED (type);
995   code = unsignedp ? unsigned_code : signed_code;
996
997 #ifdef HAVE_canonicalize_funcptr_for_compare
998   /* If function pointers need to be "canonicalized" before they can
999      be reliably compared, then canonicalize them.  */
1000   if (HAVE_canonicalize_funcptr_for_compare
1001       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
1002       && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1003           == FUNCTION_TYPE))
1004     {
1005       rtx new_op0 = gen_reg_rtx (mode);
1006
1007       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
1008       op0 = new_op0;
1009     }
1010
1011   if (HAVE_canonicalize_funcptr_for_compare
1012       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
1013       && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
1014           == FUNCTION_TYPE))
1015     {
1016       rtx new_op1 = gen_reg_rtx (mode);
1017
1018       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
1019       op1 = new_op1;
1020     }
1021 #endif
1022
1023   /* Do any postincrements in the expression that was tested.  */
1024   emit_queue ();
1025
1026   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
1027                            ((mode == BLKmode)
1028                             ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
1029                            if_false_label, if_true_label);
1030 }
1031
1032 #include "gt-dojump.h"