OSDN Git Service

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