OSDN Git Service

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