OSDN Git Service

2010-05-13 Martin Jambor <mjambor@suse.cz>
[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, 2008, 2009, 2010
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 #include "output.h"
39
40 static bool prefer_and_bit_test (enum machine_mode, int);
41 static void do_jump_by_parts_greater (tree, tree, int, rtx, rtx, int);
42 static void do_jump_by_parts_equality (tree, tree, rtx, rtx, int);
43 static void do_compare_and_jump (tree, tree, enum rtx_code, enum rtx_code, rtx,
44                                  rtx, int);
45
46 /* Invert probability if there is any.  -1 stands for unknown.  */
47
48 static inline int
49 inv (int prob)
50 {
51   return prob == -1 ? -1 : REG_BR_PROB_BASE - prob;
52 }
53
54 /* At the start of a function, record that we have no previously-pushed
55    arguments waiting to be popped.  */
56
57 void
58 init_pending_stack_adjust (void)
59 {
60   pending_stack_adjust = 0;
61 }
62
63 /* Discard any pending stack adjustment.  This avoid relying on the
64    RTL optimizers to remove useless adjustments when we know the
65    stack pointer value is dead.  */
66 void
67 discard_pending_stack_adjust (void)
68 {
69   stack_pointer_delta -= pending_stack_adjust;
70   pending_stack_adjust = 0;
71 }
72
73 /* When exiting from function, if safe, clear out any pending stack adjust
74    so the adjustment won't get done.
75
76    Note, if the current function calls alloca, then it must have a
77    frame pointer regardless of the value of flag_omit_frame_pointer.  */
78
79 void
80 clear_pending_stack_adjust (void)
81 {
82   if (optimize > 0
83       && (! flag_omit_frame_pointer || cfun->calls_alloca)
84       && EXIT_IGNORE_STACK)
85     discard_pending_stack_adjust ();
86 }
87
88 /* Pop any previously-pushed arguments that have not been popped yet.  */
89
90 void
91 do_pending_stack_adjust (void)
92 {
93   if (inhibit_defer_pop == 0)
94     {
95       if (pending_stack_adjust != 0)
96         adjust_stack (GEN_INT (pending_stack_adjust));
97       pending_stack_adjust = 0;
98     }
99 }
100 \f
101 /* Expand conditional expressions.  */
102
103 /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
104    LABEL is an rtx of code CODE_LABEL, in this function and all the
105    functions here.  */
106
107 void
108 jumpifnot (tree exp, rtx label, int prob)
109 {
110   do_jump (exp, label, NULL_RTX, inv (prob));
111 }
112
113 void
114 jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx label, int prob)
115 {
116   do_jump_1 (code, op0, op1, label, NULL_RTX, inv (prob));
117 }
118
119 /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
120
121 void
122 jumpif (tree exp, rtx label, int prob)
123 {
124   do_jump (exp, NULL_RTX, label, prob);
125 }
126
127 void
128 jumpif_1 (enum tree_code code, tree op0, tree op1, rtx label, int prob)
129 {
130   do_jump_1 (code, op0, op1, NULL_RTX, label, prob);
131 }
132
133 /* Used internally by prefer_and_bit_test.  */
134
135 static GTY(()) rtx and_reg;
136 static GTY(()) rtx and_test;
137 static GTY(()) rtx shift_test;
138
139 /* Compare the relative costs of "(X & (1 << BITNUM))" and "(X >> BITNUM) & 1",
140    where X is an arbitrary register of mode MODE.  Return true if the former
141    is preferred.  */
142
143 static bool
144 prefer_and_bit_test (enum machine_mode mode, int bitnum)
145 {
146   if (and_test == 0)
147     {
148       /* Set up rtxes for the two variations.  Use NULL as a placeholder
149          for the BITNUM-based constants.  */
150       and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER);
151       and_test = gen_rtx_AND (mode, and_reg, NULL);
152       shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL),
153                                 const1_rtx);
154     }
155   else
156     {
157       /* Change the mode of the previously-created rtxes.  */
158       PUT_MODE (and_reg, mode);
159       PUT_MODE (and_test, mode);
160       PUT_MODE (shift_test, mode);
161       PUT_MODE (XEXP (shift_test, 0), mode);
162     }
163
164   /* Fill in the integers.  */
165   XEXP (and_test, 1)
166     = immed_double_int_const (double_int_setbit (double_int_zero, bitnum),
167                                                  mode);
168   XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
169
170   return (rtx_cost (and_test, IF_THEN_ELSE, optimize_insn_for_speed_p ())
171           <= rtx_cost (shift_test, IF_THEN_ELSE, optimize_insn_for_speed_p ()));
172 }
173
174 /* Subroutine of do_jump, dealing with exploded comparisons of the type
175    OP0 CODE OP1 .  IF_FALSE_LABEL and IF_TRUE_LABEL like in do_jump.
176    PROB is probability of jump to if_true_label, or -1 if unknown.  */
177
178 void
179 do_jump_1 (enum tree_code code, tree op0, tree op1,
180            rtx if_false_label, rtx if_true_label, int prob)
181 {
182   enum machine_mode mode;
183   rtx drop_through_label = 0;
184
185   switch (code)
186     {
187     case EQ_EXPR:
188       {
189         tree inner_type = TREE_TYPE (op0);
190
191         gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
192                     != MODE_COMPLEX_FLOAT);
193         gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
194                     != MODE_COMPLEX_INT);
195
196         if (integer_zerop (op1))
197           do_jump (op0, if_true_label, if_false_label, inv (prob));
198         else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
199                  && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
200           do_jump_by_parts_equality (op0, op1, if_false_label, if_true_label,
201                                      prob);
202         else
203           do_compare_and_jump (op0, op1, EQ, EQ, if_false_label, if_true_label,
204                                prob);
205         break;
206       }
207
208     case NE_EXPR:
209       {
210         tree inner_type = TREE_TYPE (op0);
211
212         gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
213                     != MODE_COMPLEX_FLOAT);
214         gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
215                     != MODE_COMPLEX_INT);
216
217         if (integer_zerop (op1))
218           do_jump (op0, if_false_label, if_true_label, prob);
219         else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
220            && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
221           do_jump_by_parts_equality (op0, op1, if_true_label, if_false_label,
222                                      inv (prob));
223         else
224           do_compare_and_jump (op0, op1, NE, NE, if_false_label, if_true_label,
225                                prob);
226         break;
227       }
228
229     case LT_EXPR:
230       mode = TYPE_MODE (TREE_TYPE (op0));
231       if (GET_MODE_CLASS (mode) == MODE_INT
232           && ! can_compare_p (LT, mode, ccp_jump))
233         do_jump_by_parts_greater (op0, op1, 1, if_false_label, if_true_label,
234                                   prob);
235       else
236         do_compare_and_jump (op0, op1, LT, LTU, if_false_label, if_true_label,
237                              prob);
238       break;
239
240     case LE_EXPR:
241       mode = TYPE_MODE (TREE_TYPE (op0));
242       if (GET_MODE_CLASS (mode) == MODE_INT
243           && ! can_compare_p (LE, mode, ccp_jump))
244         do_jump_by_parts_greater (op0, op1, 0, if_true_label, if_false_label,
245                                   inv (prob));
246       else
247         do_compare_and_jump (op0, op1, LE, LEU, if_false_label, if_true_label,
248                              prob);
249       break;
250
251     case GT_EXPR:
252       mode = TYPE_MODE (TREE_TYPE (op0));
253       if (GET_MODE_CLASS (mode) == MODE_INT
254           && ! can_compare_p (GT, mode, ccp_jump))
255         do_jump_by_parts_greater (op0, op1, 0, if_false_label, if_true_label,
256                                   prob);
257       else
258         do_compare_and_jump (op0, op1, GT, GTU, if_false_label, if_true_label,
259                              prob);
260       break;
261
262     case GE_EXPR:
263       mode = TYPE_MODE (TREE_TYPE (op0));
264       if (GET_MODE_CLASS (mode) == MODE_INT
265           && ! can_compare_p (GE, mode, ccp_jump))
266         do_jump_by_parts_greater (op0, op1, 1, if_true_label, if_false_label,
267                                   inv (prob));
268       else
269         do_compare_and_jump (op0, op1, GE, GEU, if_false_label, if_true_label,
270                              prob);
271       break;
272
273     case ORDERED_EXPR:
274       do_compare_and_jump (op0, op1, ORDERED, ORDERED,
275                            if_false_label, if_true_label, prob);
276       break;
277
278     case UNORDERED_EXPR:
279       do_compare_and_jump (op0, op1, UNORDERED, UNORDERED,
280                            if_false_label, if_true_label, prob);
281       break;
282
283     case UNLT_EXPR:
284       do_compare_and_jump (op0, op1, UNLT, UNLT, if_false_label, if_true_label,
285                            prob);
286       break;
287
288     case UNLE_EXPR:
289       do_compare_and_jump (op0, op1, UNLE, UNLE, if_false_label, if_true_label,
290                            prob);
291       break;
292
293     case UNGT_EXPR:
294       do_compare_and_jump (op0, op1, UNGT, UNGT, if_false_label, if_true_label,
295                            prob);
296       break;
297
298     case UNGE_EXPR:
299       do_compare_and_jump (op0, op1, UNGE, UNGE, if_false_label, if_true_label,
300                            prob);
301       break;
302
303     case UNEQ_EXPR:
304       do_compare_and_jump (op0, op1, UNEQ, UNEQ, if_false_label, if_true_label,
305                            prob);
306       break;
307
308     case LTGT_EXPR:
309       do_compare_and_jump (op0, op1, LTGT, LTGT, if_false_label, if_true_label,
310                            prob);
311       break;
312
313     case TRUTH_ANDIF_EXPR:
314       if (if_false_label == NULL_RTX)
315         {
316           drop_through_label = gen_label_rtx ();
317           do_jump (op0, drop_through_label, NULL_RTX, prob);
318           do_jump (op1, NULL_RTX, if_true_label, prob);
319         }
320       else
321         {
322           do_jump (op0, if_false_label, NULL_RTX, prob);
323           do_jump (op1, if_false_label, if_true_label, prob);
324         }
325       break;
326
327     case TRUTH_ORIF_EXPR:
328       if (if_true_label == NULL_RTX)
329         {
330           drop_through_label = gen_label_rtx ();
331           do_jump (op0, NULL_RTX, drop_through_label, prob);
332           do_jump (op1, if_false_label, NULL_RTX, prob);
333         }
334       else
335         {
336           do_jump (op0, NULL_RTX, if_true_label, prob);
337           do_jump (op1, if_false_label, if_true_label, prob);
338         }
339       break;
340
341     default:
342       gcc_unreachable ();
343     }
344
345   if (drop_through_label)
346     {
347       do_pending_stack_adjust ();
348       emit_label (drop_through_label);
349     }
350 }
351
352 /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
353    the result is zero, or IF_TRUE_LABEL if the result is one.
354    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
355    meaning fall through in that case.
356
357    do_jump always does any pending stack adjust except when it does not
358    actually perform a jump.  An example where there is no jump
359    is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
360
361    PROB is probability of jump to if_true_label, or -1 if unknown.  */
362
363 void
364 do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
365 {
366   enum tree_code code = TREE_CODE (exp);
367   rtx temp;
368   int i;
369   tree type;
370   enum machine_mode mode;
371   rtx drop_through_label = 0;
372
373   switch (code)
374     {
375     case ERROR_MARK:
376       break;
377
378     case INTEGER_CST:
379       temp = integer_zerop (exp) ? if_false_label : if_true_label;
380       if (temp)
381         emit_jump (temp);
382       break;
383
384 #if 0
385       /* This is not true with #pragma weak  */
386     case ADDR_EXPR:
387       /* The address of something can never be zero.  */
388       if (if_true_label)
389         emit_jump (if_true_label);
390       break;
391 #endif
392
393     case NOP_EXPR:
394       if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
395           || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
396           || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
397           || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
398         goto normal;
399     case CONVERT_EXPR:
400       /* If we are narrowing the operand, we have to do the compare in the
401          narrower mode.  */
402       if ((TYPE_PRECISION (TREE_TYPE (exp))
403            < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
404         goto normal;
405     case NON_LVALUE_EXPR:
406     case ABS_EXPR:
407     case NEGATE_EXPR:
408     case LROTATE_EXPR:
409     case RROTATE_EXPR:
410       /* These cannot change zero->nonzero or vice versa.  */
411       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label, prob);
412       break;
413
414     case TRUTH_NOT_EXPR:
415       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label,
416                inv (prob));
417       break;
418
419     case COND_EXPR:
420       {
421         rtx label1 = gen_label_rtx ();
422         if (!if_true_label || !if_false_label)
423           {
424             drop_through_label = gen_label_rtx ();
425             if (!if_true_label)
426               if_true_label = drop_through_label;
427             if (!if_false_label)
428               if_false_label = drop_through_label;
429           }
430
431         do_pending_stack_adjust ();
432         do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX, -1);
433         do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
434         emit_label (label1);
435         do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
436         break;
437       }
438
439     case COMPOUND_EXPR:
440       /* Lowered by gimplify.c.  */
441       gcc_unreachable ();
442
443     case COMPONENT_REF:
444     case BIT_FIELD_REF:
445     case ARRAY_REF:
446     case ARRAY_RANGE_REF:
447       {
448         HOST_WIDE_INT bitsize, bitpos;
449         int unsignedp;
450         enum machine_mode mode;
451         tree type;
452         tree offset;
453         int volatilep = 0;
454
455         /* Get description of this reference.  We don't actually care
456            about the underlying object here.  */
457         get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
458                              &unsignedp, &volatilep, false);
459
460         type = lang_hooks.types.type_for_size (bitsize, unsignedp);
461         if (! SLOW_BYTE_ACCESS
462             && type != 0 && bitsize >= 0
463             && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
464             && have_insn_for (COMPARE, TYPE_MODE (type)))
465           {
466             do_jump (fold_convert (type, exp), if_false_label, if_true_label,
467                      prob);
468             break;
469           }
470         goto normal;
471       }
472
473     case MINUS_EXPR:
474       /* Nonzero iff operands of minus differ.  */
475       code = NE_EXPR;
476
477       /* FALLTHRU */
478     case EQ_EXPR:
479     case NE_EXPR:
480     case LT_EXPR:
481     case LE_EXPR:
482     case GT_EXPR:
483     case GE_EXPR:
484     case ORDERED_EXPR:
485     case UNORDERED_EXPR:
486     case UNLT_EXPR:
487     case UNLE_EXPR:
488     case UNGT_EXPR:
489     case UNGE_EXPR:
490     case UNEQ_EXPR:
491     case LTGT_EXPR:
492     case TRUTH_ANDIF_EXPR:
493     case TRUTH_ORIF_EXPR:
494     other_code:
495       do_jump_1 (code, TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
496                  if_false_label, if_true_label, prob);
497       break;
498
499     case BIT_AND_EXPR:
500       /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
501          See if the former is preferred for jump tests and restore it
502          if so.  */
503       if (integer_onep (TREE_OPERAND (exp, 1)))
504         {
505           tree exp0 = TREE_OPERAND (exp, 0);
506           rtx set_label, clr_label;
507           int setclr_prob = prob;
508
509           /* Strip narrowing integral type conversions.  */
510           while (CONVERT_EXPR_P (exp0)
511                  && TREE_OPERAND (exp0, 0) != error_mark_node
512                  && TYPE_PRECISION (TREE_TYPE (exp0))
513                     <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
514             exp0 = TREE_OPERAND (exp0, 0);
515
516           /* "exp0 ^ 1" inverts the sense of the single bit test.  */
517           if (TREE_CODE (exp0) == BIT_XOR_EXPR
518               && integer_onep (TREE_OPERAND (exp0, 1)))
519             {
520               exp0 = TREE_OPERAND (exp0, 0);
521               clr_label = if_true_label;
522               set_label = if_false_label;
523               setclr_prob = inv (prob);
524             }
525           else
526             {
527               clr_label = if_false_label;
528               set_label = if_true_label;
529             }
530
531           if (TREE_CODE (exp0) == RSHIFT_EXPR)
532             {
533               tree arg = TREE_OPERAND (exp0, 0);
534               tree shift = TREE_OPERAND (exp0, 1);
535               tree argtype = TREE_TYPE (arg);
536               if (TREE_CODE (shift) == INTEGER_CST
537                   && compare_tree_int (shift, 0) >= 0
538                   && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
539                   && prefer_and_bit_test (TYPE_MODE (argtype),
540                                           TREE_INT_CST_LOW (shift)))
541                 {
542                   unsigned HOST_WIDE_INT mask
543                     = (unsigned HOST_WIDE_INT) 1 << TREE_INT_CST_LOW (shift);
544                   do_jump (build2 (BIT_AND_EXPR, argtype, arg,
545                                    build_int_cstu (argtype, mask)),
546                            clr_label, set_label, setclr_prob);
547                   break;
548                 }
549             }
550         }
551
552       /* If we are AND'ing with a small constant, do this comparison in the
553          smallest type that fits.  If the machine doesn't have comparisons
554          that small, it will be converted back to the wider comparison.
555          This helps if we are testing the sign bit of a narrower object.
556          combine can't do this for us because it can't know whether a
557          ZERO_EXTRACT or a compare in a smaller mode exists, but we do.  */
558
559       if (! SLOW_BYTE_ACCESS
560           && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
561           && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
562           && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
563           && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
564           && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
565           && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
566           && have_insn_for (COMPARE, TYPE_MODE (type)))
567         {
568           do_jump (fold_convert (type, exp), if_false_label, if_true_label,
569                    prob);
570           break;
571         }
572
573       if (TYPE_PRECISION (TREE_TYPE (exp)) > 1
574           || TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
575         goto normal;
576
577       /* Boolean comparisons can be compiled as TRUTH_AND_EXPR.  */
578
579     case TRUTH_AND_EXPR:
580       /* High branch cost, expand as the bitwise AND of the conditions.
581          Do the same if the RHS has side effects, because we're effectively
582          turning a TRUTH_AND_EXPR into a TRUTH_ANDIF_EXPR.  */
583       if (BRANCH_COST (optimize_insn_for_speed_p (),
584                        false) >= 4
585           || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
586         goto normal;
587       code = TRUTH_ANDIF_EXPR;
588       goto other_code;
589
590     case BIT_IOR_EXPR:
591     case TRUTH_OR_EXPR:
592       /* High branch cost, expand as the bitwise OR of the conditions.
593          Do the same if the RHS has side effects, because we're effectively
594          turning a TRUTH_OR_EXPR into a TRUTH_ORIF_EXPR.  */
595       if (BRANCH_COST (optimize_insn_for_speed_p (), false) >= 4
596           || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
597         goto normal;
598       code = TRUTH_ORIF_EXPR;
599       goto other_code;
600
601       /* Fall through and generate the normal code.  */
602     default:
603     normal:
604       temp = expand_normal (exp);
605       do_pending_stack_adjust ();
606       /* The RTL optimizers prefer comparisons against pseudos.  */
607       if (GET_CODE (temp) == SUBREG)
608         {
609           /* Compare promoted variables in their promoted mode.  */
610           if (SUBREG_PROMOTED_VAR_P (temp)
611               && REG_P (XEXP (temp, 0)))
612             temp = XEXP (temp, 0);
613           else
614             temp = copy_to_reg (temp);
615         }
616       do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
617                                NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
618                                GET_MODE (temp), NULL_RTX,
619                                if_false_label, if_true_label, prob);
620     }
621
622   if (drop_through_label)
623     {
624       do_pending_stack_adjust ();
625       emit_label (drop_through_label);
626     }
627 }
628 \f
629 /* Compare OP0 with OP1, word at a time, in mode MODE.
630    UNSIGNEDP says to do unsigned comparison.
631    Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise.  */
632
633 static void
634 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
635                               rtx op1, rtx if_false_label, rtx if_true_label,
636                               int prob)
637 {
638   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
639   rtx drop_through_label = 0;
640   int i;
641
642   if (! if_true_label || ! if_false_label)
643     drop_through_label = gen_label_rtx ();
644   if (! if_true_label)
645     if_true_label = drop_through_label;
646   if (! if_false_label)
647     if_false_label = drop_through_label;
648
649   /* Compare a word at a time, high order first.  */
650   for (i = 0; i < nwords; i++)
651     {
652       rtx op0_word, op1_word;
653
654       if (WORDS_BIG_ENDIAN)
655         {
656           op0_word = operand_subword_force (op0, i, mode);
657           op1_word = operand_subword_force (op1, i, mode);
658         }
659       else
660         {
661           op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
662           op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
663         }
664
665       /* All but high-order word must be compared as unsigned.  */
666       do_compare_rtx_and_jump (op0_word, op1_word, GT,
667                                (unsignedp || i > 0), word_mode, NULL_RTX,
668                                NULL_RTX, if_true_label, prob);
669
670       /* Consider lower words only if these are equal.  */
671       do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
672                                NULL_RTX, NULL_RTX, if_false_label,
673                                inv (prob));
674     }
675
676   if (if_false_label)
677     emit_jump (if_false_label);
678   if (drop_through_label)
679     emit_label (drop_through_label);
680 }
681
682 /* Given a comparison expression EXP for values too wide to be compared
683    with one insn, test the comparison and jump to the appropriate label.
684    The code of EXP is ignored; we always test GT if SWAP is 0,
685    and LT if SWAP is 1.  */
686
687 static void
688 do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
689                           rtx if_false_label, rtx if_true_label, int prob)
690 {
691   rtx op0 = expand_normal (swap ? treeop1 : treeop0);
692   rtx op1 = expand_normal (swap ? treeop0 : treeop1);
693   enum machine_mode mode = TYPE_MODE (TREE_TYPE (treeop0));
694   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
695
696   do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
697                                 if_true_label, prob);
698 }
699 \f
700 /* Jump according to whether OP0 is 0.  We assume that OP0 has an integer
701    mode, MODE, that is too wide for the available compare insns.  Either
702    Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX
703    to indicate drop through.  */
704
705 static void
706 do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
707                            rtx if_false_label, rtx if_true_label, int prob)
708 {
709   int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
710   rtx part;
711   int i;
712   rtx drop_through_label = 0;
713
714   /* The fastest way of doing this comparison on almost any machine is to
715      "or" all the words and compare the result.  If all have to be loaded
716      from memory and this is a very wide item, it's possible this may
717      be slower, but that's highly unlikely.  */
718
719   part = gen_reg_rtx (word_mode);
720   emit_move_insn (part, operand_subword_force (op0, 0, mode));
721   for (i = 1; i < nwords && part != 0; i++)
722     part = expand_binop (word_mode, ior_optab, part,
723                          operand_subword_force (op0, i, mode),
724                          part, 1, OPTAB_WIDEN);
725
726   if (part != 0)
727     {
728       do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
729                                NULL_RTX, if_false_label, if_true_label, prob);
730       return;
731     }
732
733   /* If we couldn't do the "or" simply, do this with a series of compares.  */
734   if (! if_false_label)
735     drop_through_label = if_false_label = gen_label_rtx ();
736
737   for (i = 0; i < nwords; i++)
738     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
739                              const0_rtx, EQ, 1, word_mode, NULL_RTX,
740                              if_false_label, NULL_RTX, prob);
741
742   if (if_true_label)
743     emit_jump (if_true_label);
744
745   if (drop_through_label)
746     emit_label (drop_through_label);
747 }
748
749 /* Test for the equality of two RTX expressions OP0 and OP1 in mode MODE,
750    where MODE is an integer mode too wide to be compared with one insn.
751    Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX
752    to indicate drop through.  */
753
754 static void
755 do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
756                                rtx if_false_label, rtx if_true_label, int prob)
757 {
758   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
759   rtx drop_through_label = 0;
760   int i;
761
762   if (op1 == const0_rtx)
763     {
764       do_jump_by_parts_zero_rtx (mode, op0, if_false_label, if_true_label,
765                                  prob);
766       return;
767     }
768   else if (op0 == const0_rtx)
769     {
770       do_jump_by_parts_zero_rtx (mode, op1, if_false_label, if_true_label,
771                                  prob);
772       return;
773     }
774
775   if (! if_false_label)
776     drop_through_label = if_false_label = gen_label_rtx ();
777
778   for (i = 0; i < nwords; i++)
779     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
780                              operand_subword_force (op1, i, mode),
781                              EQ, 0, word_mode, NULL_RTX,
782                              if_false_label, NULL_RTX, prob);
783
784   if (if_true_label)
785     emit_jump (if_true_label);
786   if (drop_through_label)
787     emit_label (drop_through_label);
788 }
789
790 /* Given an EQ_EXPR expression EXP for values too wide to be compared
791    with one insn, test the comparison and jump to the appropriate label.  */
792
793 static void
794 do_jump_by_parts_equality (tree treeop0, tree treeop1, rtx if_false_label,
795                            rtx if_true_label, int prob)
796 {
797   rtx op0 = expand_normal (treeop0);
798   rtx op1 = expand_normal (treeop1);
799   enum machine_mode mode = TYPE_MODE (TREE_TYPE (treeop0));
800   do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
801                                  if_true_label, prob);
802 }
803 \f
804 /* Split a comparison into two others, the second of which has the other
805    "orderedness".  The first is always ORDERED or UNORDERED if MODE
806    does not honor NaNs (which means that it can be skipped in that case;
807    see do_compare_rtx_and_jump).
808
809    The two conditions are written in *CODE1 and *CODE2.  Return true if
810    the conditions must be ANDed, false if they must be ORed.  */
811
812 bool
813 split_comparison (enum rtx_code code, enum machine_mode mode,
814                   enum rtx_code *code1, enum rtx_code *code2)
815 {
816   switch (code)
817     {
818     case LT:
819       *code1 = ORDERED;
820       *code2 = UNLT;
821       return true;
822     case LE:
823       *code1 = ORDERED;
824       *code2 = UNLE;
825       return true;
826     case GT:
827       *code1 = ORDERED;
828       *code2 = UNGT;
829       return true;
830     case GE:
831       *code1 = ORDERED;
832       *code2 = UNGE;
833       return true;
834     case EQ:
835       *code1 = ORDERED;
836       *code2 = UNEQ;
837       return true;
838     case NE:
839       *code1 = UNORDERED;
840       *code2 = LTGT;
841       return false;
842     case UNLT:
843       *code1 = UNORDERED;
844       *code2 = LT;
845       return false;
846     case UNLE:
847       *code1 = UNORDERED;
848       *code2 = LE;
849       return false;
850     case UNGT:
851       *code1 = UNORDERED;
852       *code2 = GT;
853       return false;
854     case UNGE:
855       *code1 = UNORDERED;
856       *code2 = GE;
857       return false;
858     case UNEQ:
859       *code1 = UNORDERED;
860       *code2 = EQ;
861       return false;
862     case LTGT:
863       /* Do not turn a trapping comparison into a non-trapping one.  */
864       if (HONOR_SNANS (mode))
865         {
866           *code1 = LT;
867           *code2 = GT;
868           return false;
869         }
870       else
871         {
872           *code1 = ORDERED;
873           *code2 = NE;
874           return true;
875         }
876     default:
877       gcc_unreachable ();
878     }
879 }
880
881
882 /* Like do_compare_and_jump but expects the values to compare as two rtx's.
883    The decision as to signed or unsigned comparison must be made by the caller.
884
885    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
886    compared.  */
887
888 void
889 do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
890                          enum machine_mode mode, rtx size, rtx if_false_label,
891                          rtx if_true_label, int prob)
892 {
893   rtx tem;
894   rtx dummy_label = NULL_RTX;
895   rtx last;
896
897   /* Reverse the comparison if that is safe and we want to jump if it is
898      false.  Also convert to the reverse comparison if the target can
899      implement it.  */
900   if ((! if_true_label
901        || ! can_compare_p (code, mode, ccp_jump))
902       && (! FLOAT_MODE_P (mode)
903           || code == ORDERED || code == UNORDERED
904           || (! HONOR_NANS (mode) && (code == LTGT || code == UNEQ))
905           || (! HONOR_SNANS (mode) && (code == EQ || code == NE))))
906     {
907       enum rtx_code rcode;
908       if (FLOAT_MODE_P (mode))
909         rcode = reverse_condition_maybe_unordered (code);
910       else
911         rcode = reverse_condition (code);
912
913       /* Canonicalize to UNORDERED for the libcall.  */
914       if (can_compare_p (rcode, mode, ccp_jump)
915           || (code == ORDERED && ! can_compare_p (ORDERED, mode, ccp_jump)))
916         {
917           tem = if_true_label;
918           if_true_label = if_false_label;
919           if_false_label = tem;
920           code = rcode;
921           prob = inv (prob);
922         }
923     }
924
925   /* If one operand is constant, make it the second one.  Only do this
926      if the other operand is not constant as well.  */
927
928   if (swap_commutative_operands_p (op0, op1))
929     {
930       tem = op0;
931       op0 = op1;
932       op1 = tem;
933       code = swap_condition (code);
934     }
935
936   do_pending_stack_adjust ();
937
938   code = unsignedp ? unsigned_condition (code) : code;
939   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
940                                                  op0, op1)))
941     {
942       if (CONSTANT_P (tem))
943         {
944           rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
945                       ? if_false_label : if_true_label;
946           if (label)
947             emit_jump (label);
948           return;
949         }
950
951       code = GET_CODE (tem);
952       mode = GET_MODE (tem);
953       op0 = XEXP (tem, 0);
954       op1 = XEXP (tem, 1);
955       unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
956     }
957
958   if (! if_true_label)
959     dummy_label = if_true_label = gen_label_rtx ();
960
961   if (GET_MODE_CLASS (mode) == MODE_INT
962       && ! can_compare_p (code, mode, ccp_jump))
963     {
964       switch (code)
965         {
966         case LTU:
967           do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
968                                         if_false_label, if_true_label, prob);
969           break;
970
971         case LEU:
972           do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
973                                         if_true_label, if_false_label,
974                                         inv (prob));
975           break;
976
977         case GTU:
978           do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
979                                         if_false_label, if_true_label, prob);
980           break;
981
982         case GEU:
983           do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
984                                         if_true_label, if_false_label,
985                                         inv (prob));
986           break;
987
988         case LT:
989           do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
990                                         if_false_label, if_true_label, prob);
991           break;
992
993         case LE:
994           do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
995                                         if_true_label, if_false_label,
996                                         inv (prob));
997           break;
998
999         case GT:
1000           do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
1001                                         if_false_label, if_true_label, prob);
1002           break;
1003
1004         case GE:
1005           do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
1006                                         if_true_label, if_false_label,
1007                                         inv (prob));
1008           break;
1009
1010         case EQ:
1011           do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
1012                                          if_true_label, prob);
1013           break;
1014
1015         case NE:
1016           do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
1017                                          if_false_label, inv (prob));
1018           break;
1019
1020         default:
1021           gcc_unreachable ();
1022         }
1023     }
1024   else
1025     {
1026       if (GET_MODE_CLASS (mode) == MODE_FLOAT
1027           && ! can_compare_p (code, mode, ccp_jump)
1028           && can_compare_p (swap_condition (code), mode, ccp_jump))
1029         {
1030           rtx tmp;
1031           code = swap_condition (code);
1032           tmp = op0;
1033           op0 = op1;
1034           op1 = tmp;
1035         }
1036
1037       else if (GET_MODE_CLASS (mode) == MODE_FLOAT
1038                && ! can_compare_p (code, mode, ccp_jump)
1039
1040                /* Never split ORDERED and UNORDERED.  These must be implemented.  */
1041                && (code != ORDERED && code != UNORDERED)
1042
1043                /* Split a floating-point comparison if we can jump on other
1044                   conditions...  */
1045                && (have_insn_for (COMPARE, mode)
1046
1047                    /* ... or if there is no libcall for it.  */
1048                    || code_to_optab[code] == NULL))
1049         {
1050           enum rtx_code first_code;
1051           bool and_them = split_comparison (code, mode, &first_code, &code);
1052
1053           /* If there are no NaNs, the first comparison should always fall
1054              through.  */
1055           if (!HONOR_NANS (mode))
1056             gcc_assert (first_code == (and_them ? ORDERED : UNORDERED));
1057
1058           else
1059             {
1060               if (and_them)
1061                 {
1062                   rtx dest_label;
1063                   /* If we only jump if true, just bypass the second jump.  */
1064                   if (! if_false_label)
1065                     {
1066                       if (! dummy_label)
1067                         dummy_label = gen_label_rtx ();
1068                       dest_label = dummy_label;
1069                     }
1070                   else
1071                     dest_label = if_false_label;
1072                   do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
1073                                            size, dest_label, NULL_RTX, prob);
1074                 }
1075               else
1076                 do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
1077                                          size, NULL_RTX, if_true_label, prob);
1078             }
1079         }
1080
1081       last = get_last_insn ();
1082       emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
1083                                if_true_label);
1084       if (prob != -1 && profile_status != PROFILE_ABSENT)
1085         {
1086           for (last = NEXT_INSN (last);
1087                last && NEXT_INSN (last);
1088                last = NEXT_INSN (last))
1089             if (JUMP_P (last))
1090               break;
1091           if (!last
1092               || !JUMP_P (last)
1093               || NEXT_INSN (last)
1094               || !any_condjump_p (last))
1095             {
1096               if (dump_file)
1097                 fprintf (dump_file, "Failed to add probability note\n");
1098             }
1099           else
1100             {
1101               gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
1102               add_reg_note (last, REG_BR_PROB, GEN_INT (prob));
1103             }
1104         }
1105     }
1106
1107   if (if_false_label)
1108     emit_jump (if_false_label);
1109   if (dummy_label)
1110     emit_label (dummy_label);
1111 }
1112
1113 /* Generate code for a comparison expression EXP (including code to compute
1114    the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
1115    IF_TRUE_LABEL.  One of the labels can be NULL_RTX, in which case the
1116    generated code will drop through.
1117    SIGNED_CODE should be the rtx operation for this comparison for
1118    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
1119
1120    We force a stack adjustment unless there are currently
1121    things pushed on the stack that aren't yet used.  */
1122
1123 static void
1124 do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
1125                      enum rtx_code unsigned_code, rtx if_false_label,
1126                      rtx if_true_label, int prob)
1127 {
1128   rtx op0, op1;
1129   tree type;
1130   enum machine_mode mode;
1131   int unsignedp;
1132   enum rtx_code code;
1133
1134   /* Don't crash if the comparison was erroneous.  */
1135   op0 = expand_normal (treeop0);
1136   if (TREE_CODE (treeop0) == ERROR_MARK)
1137     return;
1138
1139   op1 = expand_normal (treeop1);
1140   if (TREE_CODE (treeop1) == ERROR_MARK)
1141     return;
1142
1143   type = TREE_TYPE (treeop0);
1144   mode = TYPE_MODE (type);
1145   if (TREE_CODE (treeop0) == INTEGER_CST
1146       && (TREE_CODE (treeop1) != INTEGER_CST
1147           || (GET_MODE_BITSIZE (mode)
1148               > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (treeop1))))))
1149     {
1150       /* op0 might have been replaced by promoted constant, in which
1151          case the type of second argument should be used.  */
1152       type = TREE_TYPE (treeop1);
1153       mode = TYPE_MODE (type);
1154     }
1155   unsignedp = TYPE_UNSIGNED (type);
1156   code = unsignedp ? unsigned_code : signed_code;
1157
1158 #ifdef HAVE_canonicalize_funcptr_for_compare
1159   /* If function pointers need to be "canonicalized" before they can
1160      be reliably compared, then canonicalize them.
1161      Only do this if *both* sides of the comparison are function pointers.
1162      If one side isn't, we want a noncanonicalized comparison.  See PR
1163      middle-end/17564.  */
1164   if (HAVE_canonicalize_funcptr_for_compare
1165       && TREE_CODE (TREE_TYPE (treeop0)) == POINTER_TYPE
1166       && TREE_CODE (TREE_TYPE (TREE_TYPE (treeop0)))
1167           == FUNCTION_TYPE
1168       && TREE_CODE (TREE_TYPE (treeop1)) == POINTER_TYPE
1169       && TREE_CODE (TREE_TYPE (TREE_TYPE (treeop1)))
1170           == FUNCTION_TYPE)
1171     {
1172       rtx new_op0 = gen_reg_rtx (mode);
1173       rtx new_op1 = gen_reg_rtx (mode);
1174
1175       emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
1176       op0 = new_op0;
1177
1178       emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
1179       op1 = new_op1;
1180     }
1181 #endif
1182
1183   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
1184                            ((mode == BLKmode)
1185                             ? expr_size (treeop0) : NULL_RTX),
1186                            if_false_label, if_true_label, prob);
1187 }
1188
1189 #include "gt-dojump.h"