OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [dojump.c] - Blame information for rev 800

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.