OSDN Git Service

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