OSDN Git Service

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