OSDN Git Service

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