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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [dojump.c] - Blame information for rev 20

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

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

powered by: WebSVN 2.1.0

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