OSDN Git Service

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