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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [dojump.c] - Blame information for rev 310

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

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

powered by: WebSVN 2.1.0

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