OSDN Git Service

* dojump.c (do_jump <unordered_bcc>): Do not recursively call
[pf3gnuchains/gcc-fork.git] / gcc / dojump.c
1 /* Convert tree expression to rtl instructions, for GNU compiler.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "flags.h"
29 #include "function.h"
30 #include "insn-config.h"
31 #include "insn-attr.h"
32 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
33 #include "expr.h"
34 #include "optabs.h"
35 #include "langhooks.h"
36 #include "ggc.h"
37
38 static bool prefer_and_bit_test (enum machine_mode, int);
39 static void do_jump_by_parts_greater (tree, int, rtx, rtx);
40 static void do_jump_by_parts_equality (tree, rtx, rtx);
41 static void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx,
42                                  rtx);
43
44 /* At the start of a function, record that we have no previously-pushed
45    arguments waiting to be popped.  */
46
47 void
48 init_pending_stack_adjust (void)
49 {
50   pending_stack_adjust = 0;
51 }
52
53 /* When exiting from function, if safe, clear out any pending stack adjust
54    so the adjustment won't get done.
55
56    Note, if the current function calls alloca, then it must have a
57    frame pointer regardless of the value of flag_omit_frame_pointer.  */
58
59 void
60 clear_pending_stack_adjust (void)
61 {
62   if (optimize > 0
63       && (! flag_omit_frame_pointer || current_function_calls_alloca)
64       && EXIT_IGNORE_STACK
65       && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
66       && ! flag_inline_functions)
67     {
68       stack_pointer_delta -= pending_stack_adjust,
69       pending_stack_adjust = 0;
70     }
71 }
72
73 /* Pop any previously-pushed arguments that have not been popped yet.  */
74
75 void
76 do_pending_stack_adjust (void)
77 {
78   if (inhibit_defer_pop == 0)
79     {
80       if (pending_stack_adjust != 0)
81         adjust_stack (GEN_INT (pending_stack_adjust));
82       pending_stack_adjust = 0;
83     }
84 }
85 \f
86 /* Expand conditional expressions.  */
87
88 /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
89    LABEL is an rtx of code CODE_LABEL, in this function and all the
90    functions here.  */
91
92 void
93 jumpifnot (tree exp, rtx label)
94 {
95   do_jump (exp, label, NULL_RTX);
96 }
97
98 /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
99
100 void
101 jumpif (tree exp, rtx label)
102 {
103   do_jump (exp, NULL_RTX, label);
104 }
105
106 /* Used internally by prefer_and_bit_test.  */
107
108 static GTY(()) rtx and_reg;
109 static GTY(()) rtx and_test;
110 static GTY(()) rtx shift_test;
111
112 /* Compare the relative costs of "(X & (1 << BITNUM))" and "(X >> BITNUM) & 1",
113    where X is an arbitrary register of mode MODE.  Return true if the former
114    is preferred.  */
115
116 static bool
117 prefer_and_bit_test (enum machine_mode mode, int bitnum)
118 {
119   if (and_test == 0)
120     {
121       /* Set up rtxes for the two variations.  Use NULL as a placeholder
122          for the BITNUM-based constants.  */
123       and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER);
124       and_test = gen_rtx_AND (mode, and_reg, NULL);
125       shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL),
126                                 const1_rtx);
127     }
128   else
129     {
130       /* Change the mode of the previously-created rtxes.  */
131       PUT_MODE (and_reg, mode);
132       PUT_MODE (and_test, mode);
133       PUT_MODE (shift_test, mode);
134       PUT_MODE (XEXP (shift_test, 0), mode);
135     }
136
137   /* Fill in the integers.  */
138   XEXP (and_test, 1) = GEN_INT ((unsigned HOST_WIDE_INT) 1 << bitnum);
139   XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
140
141   return (rtx_cost (and_test, IF_THEN_ELSE)
142           <= rtx_cost (shift_test, IF_THEN_ELSE));
143 }
144
145 /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
146    the result is zero, or IF_TRUE_LABEL if the result is one.
147    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
148    meaning fall through in that case.
149
150    do_jump always does any pending stack adjust except when it does not
151    actually perform a jump.  An example where there is no jump
152    is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.  */
153
154 void
155 do_jump (tree exp, rtx if_false_label, rtx if_true_label)
156 {
157   enum tree_code code = TREE_CODE (exp);
158   rtx temp;
159   int i;
160   tree type;
161   enum machine_mode mode;
162
163   switch (code)
164     {
165     case ERROR_MARK:
166       break;
167
168     case INTEGER_CST:
169       temp = integer_zerop (exp) ? if_false_label : if_true_label;
170       if (temp)
171         emit_jump (temp);
172       break;
173
174 #if 0
175       /* This is not true with #pragma weak  */
176     case ADDR_EXPR:
177       /* The address of something can never be zero.  */
178       if (if_true_label)
179         emit_jump (if_true_label);
180       break;
181 #endif
182
183     case NOP_EXPR:
184       if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
185           || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
186           || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
187           || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
188         goto normal;
189     case CONVERT_EXPR:
190       /* If we are narrowing the operand, we have to do the compare in the
191          narrower mode.  */
192       if ((TYPE_PRECISION (TREE_TYPE (exp))
193            < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
194         goto normal;
195     case NON_LVALUE_EXPR:
196     case ABS_EXPR:
197     case NEGATE_EXPR:
198     case LROTATE_EXPR:
199     case RROTATE_EXPR:
200       /* These cannot change zero->nonzero or vice versa.  */
201       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
202       break;
203
204     case MINUS_EXPR:
205       /* Nonzero iff operands of minus differ.  */
206       do_compare_and_jump (build2 (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       /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
214          See if the former is preferred for jump tests and restore it
215          if so.  */
216       if (TREE_CODE (TREE_OPERAND (exp, 0)) == RSHIFT_EXPR
217           && integer_onep (TREE_OPERAND (exp, 1)))
218         {
219           tree arg = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
220           tree shift = TREE_OPERAND (TREE_OPERAND (exp, 0), 1);
221           tree one = TREE_OPERAND (exp, 1);
222           tree argtype = TREE_TYPE (arg);
223           if (TREE_CODE (shift) == INTEGER_CST
224               && compare_tree_int (shift, 0) > 0
225               && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
226               && prefer_and_bit_test (TYPE_MODE (argtype),
227                                       TREE_INT_CST_LOW (shift)))
228             {
229               do_jump (build2 (BIT_AND_EXPR, argtype, arg,
230                                fold (build2 (LSHIFT_EXPR, argtype,
231                                              one, shift))),
232                        if_false_label, if_true_label);
233               break;
234             }
235         }
236
237       /* If we are AND'ing with a small constant, do this comparison in the
238          smallest type that fits.  If the machine doesn't have comparisons
239          that small, it will be converted back to the wider comparison.
240          This helps if we are testing the sign bit of a narrower object.
241          combine can't do this for us because it can't know whether a
242          ZERO_EXTRACT or a compare in a smaller mode exists, but we do.  */
243
244       if (! SLOW_BYTE_ACCESS
245           && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
246           && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
247           && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
248           && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
249           && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
250           && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
251           && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
252               != CODE_FOR_nothing))
253         {
254           do_jump (convert (type, exp), if_false_label, if_true_label);
255           break;
256         }
257       goto normal;
258
259     case TRUTH_NOT_EXPR:
260       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
261       break;
262
263     case TRUTH_ANDIF_EXPR:
264     case TRUTH_ORIF_EXPR:
265     case COMPOUND_EXPR:
266     case COND_EXPR:
267       /* Lowered by gimplify.c.  */
268       abort ();
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 EQ_EXPR:
301       {
302         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
303
304         if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
305             || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
306           abort ();
307         else if (integer_zerop (TREE_OPERAND (exp, 1)))
308           do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
309         else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
310                  && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
311           do_jump_by_parts_equality (exp, if_false_label, if_true_label);
312         else
313           do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
314         break;
315       }
316
317     case NE_EXPR:
318       {
319         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
320
321         if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
322             || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
323           abort ();
324         else if (integer_zerop (TREE_OPERAND (exp, 1)))
325           do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
326         else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
327            && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
328           do_jump_by_parts_equality (exp, if_true_label, if_false_label);
329         else
330           do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
331         break;
332       }
333
334     case LT_EXPR:
335       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
336       if (GET_MODE_CLASS (mode) == MODE_INT
337           && ! can_compare_p (LT, mode, ccp_jump))
338         do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
339       else
340         do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
341       break;
342
343     case LE_EXPR:
344       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
345       if (GET_MODE_CLASS (mode) == MODE_INT
346           && ! can_compare_p (LE, mode, ccp_jump))
347         do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
348       else
349         do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
350       break;
351
352     case GT_EXPR:
353       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
354       if (GET_MODE_CLASS (mode) == MODE_INT
355           && ! can_compare_p (GT, mode, ccp_jump))
356         do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
357       else
358         do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
359       break;
360
361     case GE_EXPR:
362       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
363       if (GET_MODE_CLASS (mode) == MODE_INT
364           && ! can_compare_p (GE, mode, ccp_jump))
365         do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
366       else
367         do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
368       break;
369
370     case UNORDERED_EXPR:
371     case ORDERED_EXPR:
372       {
373         enum rtx_code cmp, rcmp;
374         int do_rev;
375
376         if (code == UNORDERED_EXPR)
377           cmp = UNORDERED, rcmp = ORDERED;
378         else
379           cmp = ORDERED, rcmp = UNORDERED;
380         mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
381
382         do_rev = 0;
383         if (! can_compare_p (cmp, mode, ccp_jump)
384             && (can_compare_p (rcmp, mode, ccp_jump)
385           /* If the target doesn't provide either UNORDERED or ORDERED
386              comparisons, canonicalize on UNORDERED for the library.  */
387           || rcmp == UNORDERED))
388           do_rev = 1;
389
390         if (! do_rev)
391           do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
392         else
393           do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
394       }
395       break;
396
397     {
398       enum rtx_code rcode1;
399       enum tree_code tcode1, tcode2;
400
401       case UNLT_EXPR:
402         rcode1 = UNLT;
403         tcode1 = UNORDERED_EXPR;
404         tcode2 = LT_EXPR;
405         goto unordered_bcc;
406       case UNLE_EXPR:
407         rcode1 = UNLE;
408         tcode1 = UNORDERED_EXPR;
409         tcode2 = LE_EXPR;
410         goto unordered_bcc;
411       case UNGT_EXPR:
412         rcode1 = UNGT;
413         tcode1 = UNORDERED_EXPR;
414         tcode2 = GT_EXPR;
415         goto unordered_bcc;
416       case UNGE_EXPR:
417         rcode1 = UNGE;
418         tcode1 = UNORDERED_EXPR;
419         tcode2 = GE_EXPR;
420         goto unordered_bcc;
421       case UNEQ_EXPR:
422         rcode1 = UNEQ;
423         tcode1 = UNORDERED_EXPR;
424         tcode2 = EQ_EXPR;
425         goto unordered_bcc;
426       case LTGT_EXPR:
427         /* It is ok for LTGT_EXPR to trap when the result is unordered,
428            so expand to (a < b) || (a > b).  */
429         rcode1 = LTGT;
430         tcode1 = LT_EXPR;
431         tcode2 = GT_EXPR;
432         goto unordered_bcc;
433
434       unordered_bcc:
435         mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
436         if (can_compare_p (rcode1, mode, ccp_jump))
437           do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
438                                if_true_label);
439         else
440           {
441             tree op0 = save_expr (TREE_OPERAND (exp, 0));
442             tree op1 = save_expr (TREE_OPERAND (exp, 1));
443             tree cmp0, cmp1;
444             rtx drop_through_label = 0;
445
446             /* If the target doesn't support combined unordered
447                compares, decompose into two comparisons.  */
448             if (if_true_label == 0)
449               drop_through_label = if_true_label = gen_label_rtx ();
450               
451             cmp0 = fold (build2 (tcode1, TREE_TYPE (exp), op0, op1));
452             cmp1 = fold (build2 (tcode2, TREE_TYPE (exp), op0, op1));
453             do_jump (cmp0, 0, if_true_label);
454             do_jump (cmp1, if_false_label, if_true_label);
455
456             if (drop_through_label)
457               {
458                 do_pending_stack_adjust ();
459                 emit_label (drop_through_label);
460               }
461           }
462       }
463       break;
464
465       /* Special case:
466           __builtin_expect (<test>, 0)  and
467           __builtin_expect (<test>, 1)
468
469          We need to do this here, so that <test> is not converted to a SCC
470          operation on machines that use condition code registers and COMPARE
471          like the PowerPC, and then the jump is done based on whether the SCC
472          operation produced a 1 or 0.  */
473     case CALL_EXPR:
474       /* Check for a built-in function.  */
475       {
476         tree fndecl = get_callee_fndecl (exp);
477         tree arglist = TREE_OPERAND (exp, 1);
478
479         if (fndecl
480             && DECL_BUILT_IN (fndecl)
481             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
482             && arglist != NULL_TREE
483             && TREE_CHAIN (arglist) != NULL_TREE)
484           {
485             rtx seq = expand_builtin_expect_jump (exp, if_false_label,
486                                                   if_true_label);
487
488             if (seq != NULL_RTX)
489               {
490                 emit_insn (seq);
491                 return;
492               }
493           }
494       }
495       /* Fall through and generate the normal code.  */
496
497     default:
498     normal:
499       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
500       do_pending_stack_adjust ();
501
502       if (GET_CODE (temp) == CONST_INT
503           || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
504           || GET_CODE (temp) == LABEL_REF)
505         {
506           rtx target = temp == const0_rtx ? if_false_label : if_true_label;
507           if (target)
508             emit_jump (target);
509         }
510       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
511                && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
512         /* Note swapping the labels gives us not-equal.  */
513         do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
514       else if (GET_MODE (temp) != VOIDmode)
515         {
516           /* The RTL optimizers prefer comparisons against pseudos.  */
517           if (GET_CODE (temp) == SUBREG)
518             {
519               /* Compare promoted variables in their promoted mode.  */
520               if (SUBREG_PROMOTED_VAR_P (temp)
521                   && REG_P (XEXP (temp, 0)))
522                 temp = XEXP (temp, 0);
523               else
524                 temp = copy_to_reg (temp);
525             }
526           do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
527                                    NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
528                                    GET_MODE (temp), NULL_RTX,
529                                    if_false_label, if_true_label);
530         }
531       else
532         abort ();
533     }
534 }
535 \f
536 /* Given a comparison expression EXP for values too wide to be compared
537    with one insn, test the comparison and jump to the appropriate label.
538    The code of EXP is ignored; we always test GT if SWAP is 0,
539    and LT if SWAP is 1.  */
540
541 static void
542 do_jump_by_parts_greater (tree exp, int swap, rtx if_false_label,
543                           rtx if_true_label)
544 {
545   rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
546   rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
547   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
548   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
549
550   do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
551                                 if_true_label);
552 }
553
554 /* Compare OP0 with OP1, word at a time, in mode MODE.
555    UNSIGNEDP says to do unsigned comparison.
556    Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise.  */
557
558 void
559 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
560                               rtx op1, rtx if_false_label, rtx if_true_label)
561 {
562   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
563   rtx drop_through_label = 0;
564   int i;
565
566   if (! if_true_label || ! if_false_label)
567     drop_through_label = gen_label_rtx ();
568   if (! if_true_label)
569     if_true_label = drop_through_label;
570   if (! if_false_label)
571     if_false_label = drop_through_label;
572
573   /* Compare a word at a time, high order first.  */
574   for (i = 0; i < nwords; i++)
575     {
576       rtx op0_word, op1_word;
577
578       if (WORDS_BIG_ENDIAN)
579         {
580           op0_word = operand_subword_force (op0, i, mode);
581           op1_word = operand_subword_force (op1, i, mode);
582         }
583       else
584         {
585           op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
586           op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
587         }
588
589       /* All but high-order word must be compared as unsigned.  */
590       do_compare_rtx_and_jump (op0_word, op1_word, GT,
591                                (unsignedp || i > 0), word_mode, NULL_RTX,
592                                NULL_RTX, if_true_label);
593
594       /* Consider lower words only if these are equal.  */
595       do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
596                                NULL_RTX, NULL_RTX, if_false_label);
597     }
598
599   if (if_false_label)
600     emit_jump (if_false_label);
601   if (drop_through_label)
602     emit_label (drop_through_label);
603 }
604
605 /* Given an EQ_EXPR expression EXP for values too wide to be compared
606    with one insn, test the comparison and jump to the appropriate label.  */
607
608 static void
609 do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label)
610 {
611   rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
612   rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
613   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
614   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
615   int i;
616   rtx drop_through_label = 0;
617
618   if (! if_false_label)
619     drop_through_label = if_false_label = gen_label_rtx ();
620
621   for (i = 0; i < nwords; i++)
622     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
623                              operand_subword_force (op1, i, mode),
624                              EQ, TYPE_UNSIGNED (TREE_TYPE (exp)),
625                              word_mode, NULL_RTX, if_false_label, NULL_RTX);
626
627   if (if_true_label)
628     emit_jump (if_true_label);
629   if (drop_through_label)
630     emit_label (drop_through_label);
631 }
632 \f
633 /* Jump according to whether OP0 is 0.
634    We assume that OP0 has an integer mode that is too wide
635    for the available compare insns.  */
636
637 void
638 do_jump_by_parts_equality_rtx (rtx op0, rtx if_false_label, rtx if_true_label)
639 {
640   int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
641   rtx part;
642   int i;
643   rtx drop_through_label = 0;
644
645   /* The fastest way of doing this comparison on almost any machine is to
646      "or" all the words and compare the result.  If all have to be loaded
647      from memory and this is a very wide item, it's possible this may
648      be slower, but that's highly unlikely.  */
649
650   part = gen_reg_rtx (word_mode);
651   emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
652   for (i = 1; i < nwords && part != 0; i++)
653     part = expand_binop (word_mode, ior_optab, part,
654                          operand_subword_force (op0, i, GET_MODE (op0)),
655                          part, 1, OPTAB_WIDEN);
656
657   if (part != 0)
658     {
659       do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
660                                NULL_RTX, if_false_label, if_true_label);
661
662       return;
663     }
664
665   /* If we couldn't do the "or" simply, do this with a series of compares.  */
666   if (! if_false_label)
667     drop_through_label = if_false_label = gen_label_rtx ();
668
669   for (i = 0; i < nwords; i++)
670     do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
671                              const0_rtx, EQ, 1, word_mode, NULL_RTX,
672                              if_false_label, NULL_RTX);
673
674   if (if_true_label)
675     emit_jump (if_true_label);
676
677   if (drop_through_label)
678     emit_label (drop_through_label);
679 }
680 \f
681 /* Generate code for a comparison of OP0 and OP1 with rtx code CODE.
682    (including code to compute the values to be compared)
683    and set (CC0) according to the result.
684    The decision as to signed or unsigned comparison must be made by the caller.
685
686    We force a stack adjustment unless there are currently
687    things pushed on the stack that aren't yet used.
688
689    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
690    compared.  */
691
692 rtx
693 compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
694                   enum machine_mode mode, rtx size)
695 {
696   rtx tem;
697
698   /* If one operand is constant, make it the second one.  Only do this
699      if the other operand is not constant as well.  */
700
701   if (swap_commutative_operands_p (op0, op1))
702     {
703       tem = op0;
704       op0 = op1;
705       op1 = tem;
706       code = swap_condition (code);
707     }
708
709   if (flag_force_mem)
710     {
711       op0 = force_not_mem (op0);
712       op1 = force_not_mem (op1);
713     }
714
715   do_pending_stack_adjust ();
716
717   code = unsignedp ? unsigned_condition (code) : code;
718   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
719                                                  op0, op1)))
720     {
721       if (CONSTANT_P (tem))
722         return tem;
723
724       code = GET_CODE (tem);
725       mode = GET_MODE (tem);
726       op0 = XEXP (tem, 0);
727       op1 = XEXP (tem, 1);
728       unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
729     }
730
731   emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
732
733 #if HAVE_cc0
734   return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
735 #else
736   return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
737 #endif
738 }
739
740 /* Like do_compare_and_jump but expects the values to compare as two rtx's.
741    The decision as to signed or unsigned comparison must be made by the caller.
742
743    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
744    compared.  */
745
746 void
747 do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
748                          enum machine_mode mode, rtx size, rtx if_false_label,
749                          rtx if_true_label)
750 {
751   rtx tem;
752   int dummy_true_label = 0;
753
754   /* Reverse the comparison if that is safe and we want to jump if it is
755      false.  */
756   if (! if_true_label && ! FLOAT_MODE_P (mode))
757     {
758       if_true_label = if_false_label;
759       if_false_label = 0;
760       code = reverse_condition (code);
761     }
762
763   /* If one operand is constant, make it the second one.  Only do this
764      if the other operand is not constant as well.  */
765
766   if (swap_commutative_operands_p (op0, op1))
767     {
768       tem = op0;
769       op0 = op1;
770       op1 = tem;
771       code = swap_condition (code);
772     }
773
774   if (flag_force_mem)
775     {
776       op0 = force_not_mem (op0);
777       op1 = force_not_mem (op1);
778     }
779
780   do_pending_stack_adjust ();
781
782   code = unsignedp ? unsigned_condition (code) : code;
783   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
784                                                  op0, op1)))
785     {
786       if (CONSTANT_P (tem))
787         {
788           rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
789                       ? if_false_label : if_true_label;
790           if (label)
791             emit_jump (label);
792           return;
793         }
794
795       code = GET_CODE (tem);
796       mode = GET_MODE (tem);
797       op0 = XEXP (tem, 0);
798       op1 = XEXP (tem, 1);
799       unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
800     }
801
802   if (! if_true_label)
803     {
804       dummy_true_label = 1;
805       if_true_label = gen_label_rtx ();
806     }
807
808   emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
809                            if_true_label);
810
811   if (if_false_label)
812     emit_jump (if_false_label);
813   if (dummy_true_label)
814     emit_label (if_true_label);
815 }
816
817 /* Generate code for a comparison expression EXP (including code to compute
818    the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
819    IF_TRUE_LABEL.  One of the labels can be NULL_RTX, in which case the
820    generated code will drop through.
821    SIGNED_CODE should be the rtx operation for this comparison for
822    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
823
824    We force a stack adjustment unless there are currently
825    things pushed on the stack that aren't yet used.  */
826
827 static void
828 do_compare_and_jump (tree exp, enum rtx_code signed_code,
829                      enum rtx_code unsigned_code, rtx if_false_label,
830                      rtx if_true_label)
831 {
832   rtx op0, op1;
833   tree type;
834   enum machine_mode mode;
835   int unsignedp;
836   enum rtx_code code;
837
838   /* Don't crash if the comparison was erroneous.  */
839   op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
840   if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
841     return;
842
843   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
844   if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
845     return;
846
847   type = TREE_TYPE (TREE_OPERAND (exp, 0));
848   mode = TYPE_MODE (type);
849   if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
850       && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
851           || (GET_MODE_BITSIZE (mode)
852               > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
853                                                                       1)))))))
854     {
855       /* op0 might have been replaced by promoted constant, in which
856          case the type of second argument should be used.  */
857       type = TREE_TYPE (TREE_OPERAND (exp, 1));
858       mode = TYPE_MODE (type);
859     }
860   unsignedp = TYPE_UNSIGNED (type);
861   code = unsignedp ? unsigned_code : signed_code;
862
863 #ifdef HAVE_canonicalize_funcptr_for_compare
864   /* If function pointers need to be "canonicalized" before they can
865      be reliably compared, then canonicalize them.  */
866   if (HAVE_canonicalize_funcptr_for_compare
867       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
868       && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
869           == FUNCTION_TYPE))
870     {
871       rtx new_op0 = gen_reg_rtx (mode);
872
873       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
874       op0 = new_op0;
875     }
876
877   if (HAVE_canonicalize_funcptr_for_compare
878       && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
879       && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
880           == FUNCTION_TYPE))
881     {
882       rtx new_op1 = gen_reg_rtx (mode);
883
884       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
885       op1 = new_op1;
886     }
887 #endif
888
889   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
890                            ((mode == BLKmode)
891                             ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
892                            if_false_label, if_true_label);
893 }
894
895 #include "gt-dojump.h"