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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 684 jeremybenn
/* Optimize jump instructions, for GNU compiler.
2
   Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3
   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
4
   2011 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
/* This is the pathetic reminder of old fame of the jump-optimization pass
23
   of the compiler.  Now it contains basically a set of utility functions to
24
   operate with jumps.
25
 
26
   Each CODE_LABEL has a count of the times it is used
27
   stored in the LABEL_NUSES internal field, and each JUMP_INSN
28
   has one label that it refers to stored in the
29
   JUMP_LABEL internal field.  With this we can detect labels that
30
   become unused because of the deletion of all the jumps that
31
   formerly used them.  The JUMP_LABEL info is sometimes looked
32
   at by later passes.  For return insns, it contains either a
33
   RETURN or a SIMPLE_RETURN rtx.
34
 
35
   The subroutines redirect_jump and invert_jump are used
36
   from other passes as well.  */
37
 
38
#include "config.h"
39
#include "system.h"
40
#include "coretypes.h"
41
#include "tm.h"
42
#include "rtl.h"
43
#include "tm_p.h"
44
#include "flags.h"
45
#include "hard-reg-set.h"
46
#include "regs.h"
47
#include "insn-config.h"
48
#include "insn-attr.h"
49
#include "recog.h"
50
#include "function.h"
51
#include "basic-block.h"
52
#include "expr.h"
53
#include "except.h"
54
#include "diagnostic-core.h"
55
#include "reload.h"
56
#include "predict.h"
57
#include "timevar.h"
58
#include "tree-pass.h"
59
#include "target.h"
60
 
61
/* Optimize jump y; x: ... y: jumpif... x?
62
   Don't know if it is worth bothering with.  */
63
/* Optimize two cases of conditional jump to conditional jump?
64
   This can never delete any instruction or make anything dead,
65
   or even change what is live at any point.
66
   So perhaps let combiner do it.  */
67
 
68
static void init_label_info (rtx);
69
static void mark_all_labels (rtx);
70
static void mark_jump_label_1 (rtx, rtx, bool, bool);
71
static void mark_jump_label_asm (rtx, rtx);
72
static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
73
static int invert_exp_1 (rtx, rtx);
74
static int returnjump_p_1 (rtx *, void *);
75
 
76
/* Worker for rebuild_jump_labels and rebuild_jump_labels_chain.  */
77
static void
78
rebuild_jump_labels_1 (rtx f, bool count_forced)
79
{
80
  rtx insn;
81
 
82
  timevar_push (TV_REBUILD_JUMP);
83
  init_label_info (f);
84
  mark_all_labels (f);
85
 
86
  /* Keep track of labels used from static data; we don't track them
87
     closely enough to delete them here, so make sure their reference
88
     count doesn't drop to zero.  */
89
 
90
  if (count_forced)
91
    for (insn = forced_labels; insn; insn = XEXP (insn, 1))
92
      if (LABEL_P (XEXP (insn, 0)))
93
        LABEL_NUSES (XEXP (insn, 0))++;
94
  timevar_pop (TV_REBUILD_JUMP);
95
}
96
 
97
/* This function rebuilds the JUMP_LABEL field and REG_LABEL_TARGET
98
   notes in jumping insns and REG_LABEL_OPERAND notes in non-jumping
99
   instructions and jumping insns that have labels as operands
100
   (e.g. cbranchsi4).  */
101
void
102
rebuild_jump_labels (rtx f)
103
{
104
  rebuild_jump_labels_1 (f, true);
105
}
106
 
107
/* This function is like rebuild_jump_labels, but doesn't run over
108
   forced_labels.  It can be used on insn chains that aren't the
109
   main function chain.  */
110
void
111
rebuild_jump_labels_chain (rtx chain)
112
{
113
  rebuild_jump_labels_1 (chain, false);
114
}
115
 
116
/* Some old code expects exactly one BARRIER as the NEXT_INSN of a
117
   non-fallthru insn.  This is not generally true, as multiple barriers
118
   may have crept in, or the BARRIER may be separated from the last
119
   real insn by one or more NOTEs.
120
 
121
   This simple pass moves barriers and removes duplicates so that the
122
   old code is happy.
123
 */
124
unsigned int
125
cleanup_barriers (void)
126
{
127
  rtx insn, next, prev;
128
  for (insn = get_insns (); insn; insn = next)
129
    {
130
      next = NEXT_INSN (insn);
131
      if (BARRIER_P (insn))
132
        {
133
          prev = prev_nonnote_insn (insn);
134
          if (!prev)
135
            continue;
136
          if (BARRIER_P (prev))
137
            delete_insn (insn);
138
          else if (prev != PREV_INSN (insn))
139
            reorder_insns (insn, insn, prev);
140
        }
141
    }
142
  return 0;
143
}
144
 
145
struct rtl_opt_pass pass_cleanup_barriers =
146
{
147
 {
148
  RTL_PASS,
149
  "barriers",                           /* name */
150
  NULL,                                 /* gate */
151
  cleanup_barriers,                     /* execute */
152
  NULL,                                 /* sub */
153
  NULL,                                 /* next */
154
  0,                                    /* static_pass_number */
155
  TV_NONE,                              /* tv_id */
156
  0,                                    /* properties_required */
157
  0,                                    /* properties_provided */
158
  0,                                    /* properties_destroyed */
159
  0,                                    /* todo_flags_start */
160
 
161
 }
162
};
163
 
164
 
165
/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
166
   for remaining targets for JUMP_P.  Delete any REG_LABEL_OPERAND
167
   notes whose labels don't occur in the insn any more.  */
168
 
169
static void
170
init_label_info (rtx f)
171
{
172
  rtx insn;
173
 
174
  for (insn = f; insn; insn = NEXT_INSN (insn))
175
    {
176
      if (LABEL_P (insn))
177
        LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
178
 
179
      /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
180
         sticky and not reset here; that way we won't lose association
181
         with a label when e.g. the source for a target register
182
         disappears out of reach for targets that may use jump-target
183
         registers.  Jump transformations are supposed to transform
184
         any REG_LABEL_TARGET notes.  The target label reference in a
185
         branch may disappear from the branch (and from the
186
         instruction before it) for other reasons, like register
187
         allocation.  */
188
 
189
      if (INSN_P (insn))
190
        {
191
          rtx note, next;
192
 
193
          for (note = REG_NOTES (insn); note; note = next)
194
            {
195
              next = XEXP (note, 1);
196
              if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
197
                  && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
198
                remove_note (insn, note);
199
            }
200
        }
201
    }
202
}
203
 
204
/* A subroutine of mark_all_labels.  Trivially propagate a simple label
205
   load into a jump_insn that uses it.  */
206
 
207
static void
208
maybe_propagate_label_ref (rtx jump_insn, rtx prev_nonjump_insn)
209
{
210
  rtx label_note, pc, pc_src;
211
 
212
  pc = pc_set (jump_insn);
213
  pc_src = pc != NULL ? SET_SRC (pc) : NULL;
214
  label_note = find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
215
 
216
  /* If the previous non-jump insn sets something to a label,
217
     something that this jump insn uses, make that label the primary
218
     target of this insn if we don't yet have any.  That previous
219
     insn must be a single_set and not refer to more than one label.
220
     The jump insn must not refer to other labels as jump targets
221
     and must be a plain (set (pc) ...), maybe in a parallel, and
222
     may refer to the item being set only directly or as one of the
223
     arms in an IF_THEN_ELSE.  */
224
 
225
  if (label_note != NULL && pc_src != NULL)
226
    {
227
      rtx label_set = single_set (prev_nonjump_insn);
228
      rtx label_dest = label_set != NULL ? SET_DEST (label_set) : NULL;
229
 
230
      if (label_set != NULL
231
          /* The source must be the direct LABEL_REF, not a
232
             PLUS, UNSPEC, IF_THEN_ELSE etc.  */
233
          && GET_CODE (SET_SRC (label_set)) == LABEL_REF
234
          && (rtx_equal_p (label_dest, pc_src)
235
              || (GET_CODE (pc_src) == IF_THEN_ELSE
236
                  && (rtx_equal_p (label_dest, XEXP (pc_src, 1))
237
                      || rtx_equal_p (label_dest, XEXP (pc_src, 2))))))
238
        {
239
          /* The CODE_LABEL referred to in the note must be the
240
             CODE_LABEL in the LABEL_REF of the "set".  We can
241
             conveniently use it for the marker function, which
242
             requires a LABEL_REF wrapping.  */
243
          gcc_assert (XEXP (label_note, 0) == XEXP (SET_SRC (label_set), 0));
244
 
245
          mark_jump_label_1 (label_set, jump_insn, false, true);
246
 
247
          gcc_assert (JUMP_LABEL (jump_insn) == XEXP (label_note, 0));
248
        }
249
    }
250
}
251
 
252
/* Mark the label each jump jumps to.
253
   Combine consecutive labels, and count uses of labels.  */
254
 
255
static void
256
mark_all_labels (rtx f)
257
{
258
  rtx insn;
259
 
260
  if (current_ir_type () == IR_RTL_CFGLAYOUT)
261
    {
262
      basic_block bb;
263
      FOR_EACH_BB (bb)
264
        {
265
          /* In cfglayout mode, we don't bother with trivial next-insn
266
             propagation of LABEL_REFs into JUMP_LABEL.  This will be
267
             handled by other optimizers using better algorithms.  */
268
          FOR_BB_INSNS (bb, insn)
269
            {
270
              gcc_assert (! INSN_DELETED_P (insn));
271
              if (NONDEBUG_INSN_P (insn))
272
                mark_jump_label (PATTERN (insn), insn, 0);
273
            }
274
 
275
          /* In cfglayout mode, there may be non-insns between the
276
             basic blocks.  If those non-insns represent tablejump data,
277
             they contain label references that we must record.  */
278
          for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn))
279
            if (INSN_P (insn))
280
              {
281
                gcc_assert (JUMP_TABLE_DATA_P (insn));
282
                mark_jump_label (PATTERN (insn), insn, 0);
283
              }
284
          for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn))
285
            if (INSN_P (insn))
286
              {
287
                gcc_assert (JUMP_TABLE_DATA_P (insn));
288
                mark_jump_label (PATTERN (insn), insn, 0);
289
              }
290
        }
291
    }
292
  else
293
    {
294
      rtx prev_nonjump_insn = NULL;
295
      for (insn = f; insn; insn = NEXT_INSN (insn))
296
        {
297
          if (INSN_DELETED_P (insn))
298
            ;
299
          else if (LABEL_P (insn))
300
            prev_nonjump_insn = NULL;
301
          else if (NONDEBUG_INSN_P (insn))
302
            {
303
              mark_jump_label (PATTERN (insn), insn, 0);
304
              if (JUMP_P (insn))
305
                {
306
                  if (JUMP_LABEL (insn) == NULL && prev_nonjump_insn != NULL)
307
                    maybe_propagate_label_ref (insn, prev_nonjump_insn);
308
                }
309
              else
310
                prev_nonjump_insn = insn;
311
            }
312
        }
313
    }
314
}
315
 
316
/* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code
317
   of reversed comparison if it is possible to do so.  Otherwise return UNKNOWN.
318
   UNKNOWN may be returned in case we are having CC_MODE compare and we don't
319
   know whether it's source is floating point or integer comparison.  Machine
320
   description should define REVERSIBLE_CC_MODE and REVERSE_CONDITION macros
321
   to help this function avoid overhead in these cases.  */
322
enum rtx_code
323
reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
324
                                const_rtx arg1, const_rtx insn)
325
{
326
  enum machine_mode mode;
327
 
328
  /* If this is not actually a comparison, we can't reverse it.  */
329
  if (GET_RTX_CLASS (code) != RTX_COMPARE
330
      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
331
    return UNKNOWN;
332
 
333
  mode = GET_MODE (arg0);
334
  if (mode == VOIDmode)
335
    mode = GET_MODE (arg1);
336
 
337
  /* First see if machine description supplies us way to reverse the
338
     comparison.  Give it priority over everything else to allow
339
     machine description to do tricks.  */
340
  if (GET_MODE_CLASS (mode) == MODE_CC
341
      && REVERSIBLE_CC_MODE (mode))
342
    {
343
#ifdef REVERSE_CONDITION
344
      return REVERSE_CONDITION (code, mode);
345
#else
346
      return reverse_condition (code);
347
#endif
348
    }
349
 
350
  /* Try a few special cases based on the comparison code.  */
351
  switch (code)
352
    {
353
    case GEU:
354
    case GTU:
355
    case LEU:
356
    case LTU:
357
    case NE:
358
    case EQ:
359
      /* It is always safe to reverse EQ and NE, even for the floating
360
         point.  Similarly the unsigned comparisons are never used for
361
         floating point so we can reverse them in the default way.  */
362
      return reverse_condition (code);
363
    case ORDERED:
364
    case UNORDERED:
365
    case LTGT:
366
    case UNEQ:
367
      /* In case we already see unordered comparison, we can be sure to
368
         be dealing with floating point so we don't need any more tests.  */
369
      return reverse_condition_maybe_unordered (code);
370
    case UNLT:
371
    case UNLE:
372
    case UNGT:
373
    case UNGE:
374
      /* We don't have safe way to reverse these yet.  */
375
      return UNKNOWN;
376
    default:
377
      break;
378
    }
379
 
380
  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
381
    {
382
      const_rtx prev;
383
      /* Try to search for the comparison to determine the real mode.
384
         This code is expensive, but with sane machine description it
385
         will be never used, since REVERSIBLE_CC_MODE will return true
386
         in all cases.  */
387
      if (! insn)
388
        return UNKNOWN;
389
 
390
      /* These CONST_CAST's are okay because prev_nonnote_insn just
391
         returns its argument and we assign it to a const_rtx
392
         variable.  */
393
      for (prev = prev_nonnote_insn (CONST_CAST_RTX(insn));
394
           prev != 0 && !LABEL_P (prev);
395
           prev = prev_nonnote_insn (CONST_CAST_RTX(prev)))
396
        {
397
          const_rtx set = set_of (arg0, prev);
398
          if (set && GET_CODE (set) == SET
399
              && rtx_equal_p (SET_DEST (set), arg0))
400
            {
401
              rtx src = SET_SRC (set);
402
 
403
              if (GET_CODE (src) == COMPARE)
404
                {
405
                  rtx comparison = src;
406
                  arg0 = XEXP (src, 0);
407
                  mode = GET_MODE (arg0);
408
                  if (mode == VOIDmode)
409
                    mode = GET_MODE (XEXP (comparison, 1));
410
                  break;
411
                }
412
              /* We can get past reg-reg moves.  This may be useful for model
413
                 of i387 comparisons that first move flag registers around.  */
414
              if (REG_P (src))
415
                {
416
                  arg0 = src;
417
                  continue;
418
                }
419
            }
420
          /* If register is clobbered in some ununderstandable way,
421
             give up.  */
422
          if (set)
423
            return UNKNOWN;
424
        }
425
    }
426
 
427
  /* Test for an integer condition, or a floating-point comparison
428
     in which NaNs can be ignored.  */
429
  if (CONST_INT_P (arg0)
430
      || (GET_MODE (arg0) != VOIDmode
431
          && GET_MODE_CLASS (mode) != MODE_CC
432
          && !HONOR_NANS (mode)))
433
    return reverse_condition (code);
434
 
435
  return UNKNOWN;
436
}
437
 
438
/* A wrapper around the previous function to take COMPARISON as rtx
439
   expression.  This simplifies many callers.  */
440
enum rtx_code
441
reversed_comparison_code (const_rtx comparison, const_rtx insn)
442
{
443
  if (!COMPARISON_P (comparison))
444
    return UNKNOWN;
445
  return reversed_comparison_code_parts (GET_CODE (comparison),
446
                                         XEXP (comparison, 0),
447
                                         XEXP (comparison, 1), insn);
448
}
449
 
450
/* Return comparison with reversed code of EXP.
451
   Return NULL_RTX in case we fail to do the reversal.  */
452
rtx
453
reversed_comparison (const_rtx exp, enum machine_mode mode)
454
{
455
  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
456
  if (reversed_code == UNKNOWN)
457
    return NULL_RTX;
458
  else
459
    return simplify_gen_relational (reversed_code, mode, VOIDmode,
460
                                    XEXP (exp, 0), XEXP (exp, 1));
461
}
462
 
463
 
464
/* Given an rtx-code for a comparison, return the code for the negated
465
   comparison.  If no such code exists, return UNKNOWN.
466
 
467
   WATCH OUT!  reverse_condition is not safe to use on a jump that might
468
   be acting on the results of an IEEE floating point comparison, because
469
   of the special treatment of non-signaling nans in comparisons.
470
   Use reversed_comparison_code instead.  */
471
 
472
enum rtx_code
473
reverse_condition (enum rtx_code code)
474
{
475
  switch (code)
476
    {
477
    case EQ:
478
      return NE;
479
    case NE:
480
      return EQ;
481
    case GT:
482
      return LE;
483
    case GE:
484
      return LT;
485
    case LT:
486
      return GE;
487
    case LE:
488
      return GT;
489
    case GTU:
490
      return LEU;
491
    case GEU:
492
      return LTU;
493
    case LTU:
494
      return GEU;
495
    case LEU:
496
      return GTU;
497
    case UNORDERED:
498
      return ORDERED;
499
    case ORDERED:
500
      return UNORDERED;
501
 
502
    case UNLT:
503
    case UNLE:
504
    case UNGT:
505
    case UNGE:
506
    case UNEQ:
507
    case LTGT:
508
      return UNKNOWN;
509
 
510
    default:
511
      gcc_unreachable ();
512
    }
513
}
514
 
515
/* Similar, but we're allowed to generate unordered comparisons, which
516
   makes it safe for IEEE floating-point.  Of course, we have to recognize
517
   that the target will support them too...  */
518
 
519
enum rtx_code
520
reverse_condition_maybe_unordered (enum rtx_code code)
521
{
522
  switch (code)
523
    {
524
    case EQ:
525
      return NE;
526
    case NE:
527
      return EQ;
528
    case GT:
529
      return UNLE;
530
    case GE:
531
      return UNLT;
532
    case LT:
533
      return UNGE;
534
    case LE:
535
      return UNGT;
536
    case LTGT:
537
      return UNEQ;
538
    case UNORDERED:
539
      return ORDERED;
540
    case ORDERED:
541
      return UNORDERED;
542
    case UNLT:
543
      return GE;
544
    case UNLE:
545
      return GT;
546
    case UNGT:
547
      return LE;
548
    case UNGE:
549
      return LT;
550
    case UNEQ:
551
      return LTGT;
552
 
553
    default:
554
      gcc_unreachable ();
555
    }
556
}
557
 
558
/* Similar, but return the code when two operands of a comparison are swapped.
559
   This IS safe for IEEE floating-point.  */
560
 
561
enum rtx_code
562
swap_condition (enum rtx_code code)
563
{
564
  switch (code)
565
    {
566
    case EQ:
567
    case NE:
568
    case UNORDERED:
569
    case ORDERED:
570
    case UNEQ:
571
    case LTGT:
572
      return code;
573
 
574
    case GT:
575
      return LT;
576
    case GE:
577
      return LE;
578
    case LT:
579
      return GT;
580
    case LE:
581
      return GE;
582
    case GTU:
583
      return LTU;
584
    case GEU:
585
      return LEU;
586
    case LTU:
587
      return GTU;
588
    case LEU:
589
      return GEU;
590
    case UNLT:
591
      return UNGT;
592
    case UNLE:
593
      return UNGE;
594
    case UNGT:
595
      return UNLT;
596
    case UNGE:
597
      return UNLE;
598
 
599
    default:
600
      gcc_unreachable ();
601
    }
602
}
603
 
604
/* Given a comparison CODE, return the corresponding unsigned comparison.
605
   If CODE is an equality comparison or already an unsigned comparison,
606
   CODE is returned.  */
607
 
608
enum rtx_code
609
unsigned_condition (enum rtx_code code)
610
{
611
  switch (code)
612
    {
613
    case EQ:
614
    case NE:
615
    case GTU:
616
    case GEU:
617
    case LTU:
618
    case LEU:
619
      return code;
620
 
621
    case GT:
622
      return GTU;
623
    case GE:
624
      return GEU;
625
    case LT:
626
      return LTU;
627
    case LE:
628
      return LEU;
629
 
630
    default:
631
      gcc_unreachable ();
632
    }
633
}
634
 
635
/* Similarly, return the signed version of a comparison.  */
636
 
637
enum rtx_code
638
signed_condition (enum rtx_code code)
639
{
640
  switch (code)
641
    {
642
    case EQ:
643
    case NE:
644
    case GT:
645
    case GE:
646
    case LT:
647
    case LE:
648
      return code;
649
 
650
    case GTU:
651
      return GT;
652
    case GEU:
653
      return GE;
654
    case LTU:
655
      return LT;
656
    case LEU:
657
      return LE;
658
 
659
    default:
660
      gcc_unreachable ();
661
    }
662
}
663
 
664
/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
665
   truth of CODE1 implies the truth of CODE2.  */
666
 
667
int
668
comparison_dominates_p (enum rtx_code code1, enum rtx_code code2)
669
{
670
  /* UNKNOWN comparison codes can happen as a result of trying to revert
671
     comparison codes.
672
     They can't match anything, so we have to reject them here.  */
673
  if (code1 == UNKNOWN || code2 == UNKNOWN)
674
    return 0;
675
 
676
  if (code1 == code2)
677
    return 1;
678
 
679
  switch (code1)
680
    {
681
    case UNEQ:
682
      if (code2 == UNLE || code2 == UNGE)
683
        return 1;
684
      break;
685
 
686
    case EQ:
687
      if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
688
          || code2 == ORDERED)
689
        return 1;
690
      break;
691
 
692
    case UNLT:
693
      if (code2 == UNLE || code2 == NE)
694
        return 1;
695
      break;
696
 
697
    case LT:
698
      if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
699
        return 1;
700
      break;
701
 
702
    case UNGT:
703
      if (code2 == UNGE || code2 == NE)
704
        return 1;
705
      break;
706
 
707
    case GT:
708
      if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
709
        return 1;
710
      break;
711
 
712
    case GE:
713
    case LE:
714
      if (code2 == ORDERED)
715
        return 1;
716
      break;
717
 
718
    case LTGT:
719
      if (code2 == NE || code2 == ORDERED)
720
        return 1;
721
      break;
722
 
723
    case LTU:
724
      if (code2 == LEU || code2 == NE)
725
        return 1;
726
      break;
727
 
728
    case GTU:
729
      if (code2 == GEU || code2 == NE)
730
        return 1;
731
      break;
732
 
733
    case UNORDERED:
734
      if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
735
          || code2 == UNGE || code2 == UNGT)
736
        return 1;
737
      break;
738
 
739
    default:
740
      break;
741
    }
742
 
743
  return 0;
744
}
745
 
746
/* Return 1 if INSN is an unconditional jump and nothing else.  */
747
 
748
int
749
simplejump_p (const_rtx insn)
750
{
751
  return (JUMP_P (insn)
752
          && GET_CODE (PATTERN (insn)) == SET
753
          && GET_CODE (SET_DEST (PATTERN (insn))) == PC
754
          && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
755
}
756
 
757
/* Return nonzero if INSN is a (possibly) conditional jump
758
   and nothing more.
759
 
760
   Use of this function is deprecated, since we need to support combined
761
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
762
 
763
int
764
condjump_p (const_rtx insn)
765
{
766
  const_rtx x = PATTERN (insn);
767
 
768
  if (GET_CODE (x) != SET
769
      || GET_CODE (SET_DEST (x)) != PC)
770
    return 0;
771
 
772
  x = SET_SRC (x);
773
  if (GET_CODE (x) == LABEL_REF)
774
    return 1;
775
  else
776
    return (GET_CODE (x) == IF_THEN_ELSE
777
            && ((GET_CODE (XEXP (x, 2)) == PC
778
                 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
779
                     || ANY_RETURN_P (XEXP (x, 1))))
780
                || (GET_CODE (XEXP (x, 1)) == PC
781
                    && (GET_CODE (XEXP (x, 2)) == LABEL_REF
782
                        || ANY_RETURN_P (XEXP (x, 2))))));
783
}
784
 
785
/* Return nonzero if INSN is a (possibly) conditional jump inside a
786
   PARALLEL.
787
 
788
   Use this function is deprecated, since we need to support combined
789
   branch and compare insns.  Use any_condjump_p instead whenever possible.  */
790
 
791
int
792
condjump_in_parallel_p (const_rtx insn)
793
{
794
  const_rtx x = PATTERN (insn);
795
 
796
  if (GET_CODE (x) != PARALLEL)
797
    return 0;
798
  else
799
    x = XVECEXP (x, 0, 0);
800
 
801
  if (GET_CODE (x) != SET)
802
    return 0;
803
  if (GET_CODE (SET_DEST (x)) != PC)
804
    return 0;
805
  if (GET_CODE (SET_SRC (x)) == LABEL_REF)
806
    return 1;
807
  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
808
    return 0;
809
  if (XEXP (SET_SRC (x), 2) == pc_rtx
810
      && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
811
          || ANY_RETURN_P (XEXP (SET_SRC (x), 1))))
812
    return 1;
813
  if (XEXP (SET_SRC (x), 1) == pc_rtx
814
      && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
815
          || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
816
    return 1;
817
  return 0;
818
}
819
 
820
/* Return set of PC, otherwise NULL.  */
821
 
822
rtx
823
pc_set (const_rtx insn)
824
{
825
  rtx pat;
826
  if (!JUMP_P (insn))
827
    return NULL_RTX;
828
  pat = PATTERN (insn);
829
 
830
  /* The set is allowed to appear either as the insn pattern or
831
     the first set in a PARALLEL.  */
832
  if (GET_CODE (pat) == PARALLEL)
833
    pat = XVECEXP (pat, 0, 0);
834
  if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
835
    return pat;
836
 
837
  return NULL_RTX;
838
}
839
 
840
/* Return true when insn is an unconditional direct jump,
841
   possibly bundled inside a PARALLEL.  */
842
 
843
int
844
any_uncondjump_p (const_rtx insn)
845
{
846
  const_rtx x = pc_set (insn);
847
  if (!x)
848
    return 0;
849
  if (GET_CODE (SET_SRC (x)) != LABEL_REF)
850
    return 0;
851
  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
852
    return 0;
853
  return 1;
854
}
855
 
856
/* Return true when insn is a conditional jump.  This function works for
857
   instructions containing PC sets in PARALLELs.  The instruction may have
858
   various other effects so before removing the jump you must verify
859
   onlyjump_p.
860
 
861
   Note that unlike condjump_p it returns false for unconditional jumps.  */
862
 
863
int
864
any_condjump_p (const_rtx insn)
865
{
866
  const_rtx x = pc_set (insn);
867
  enum rtx_code a, b;
868
 
869
  if (!x)
870
    return 0;
871
  if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
872
    return 0;
873
 
874
  a = GET_CODE (XEXP (SET_SRC (x), 1));
875
  b = GET_CODE (XEXP (SET_SRC (x), 2));
876
 
877
  return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
878
          || (a == PC
879
              && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
880
}
881
 
882
/* Return the label of a conditional jump.  */
883
 
884
rtx
885
condjump_label (const_rtx insn)
886
{
887
  rtx x = pc_set (insn);
888
 
889
  if (!x)
890
    return NULL_RTX;
891
  x = SET_SRC (x);
892
  if (GET_CODE (x) == LABEL_REF)
893
    return x;
894
  if (GET_CODE (x) != IF_THEN_ELSE)
895
    return NULL_RTX;
896
  if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
897
    return XEXP (x, 1);
898
  if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
899
    return XEXP (x, 2);
900
  return NULL_RTX;
901
}
902
 
903
/* Return true if INSN is a (possibly conditional) return insn.  */
904
 
905
static int
906
returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
907
{
908
  rtx x = *loc;
909
 
910
  if (x == NULL)
911
    return false;
912
 
913
  switch (GET_CODE (x))
914
    {
915
    case RETURN:
916
    case SIMPLE_RETURN:
917
    case EH_RETURN:
918
      return true;
919
 
920
    case SET:
921
      return SET_IS_RETURN_P (x);
922
 
923
    default:
924
      return false;
925
    }
926
}
927
 
928
/* Return TRUE if INSN is a return jump.  */
929
 
930
int
931
returnjump_p (rtx insn)
932
{
933
  if (!JUMP_P (insn))
934
    return 0;
935
  return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
936
}
937
 
938
/* Return true if INSN is a (possibly conditional) return insn.  */
939
 
940
static int
941
eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
942
{
943
  return *loc && GET_CODE (*loc) == EH_RETURN;
944
}
945
 
946
int
947
eh_returnjump_p (rtx insn)
948
{
949
  if (!JUMP_P (insn))
950
    return 0;
951
  return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
952
}
953
 
954
/* Return true if INSN is a jump that only transfers control and
955
   nothing more.  */
956
 
957
int
958
onlyjump_p (const_rtx insn)
959
{
960
  rtx set;
961
 
962
  if (!JUMP_P (insn))
963
    return 0;
964
 
965
  set = single_set (insn);
966
  if (set == NULL)
967
    return 0;
968
  if (GET_CODE (SET_DEST (set)) != PC)
969
    return 0;
970
  if (side_effects_p (SET_SRC (set)))
971
    return 0;
972
 
973
  return 1;
974
}
975
 
976
/* Return true iff INSN is a jump and its JUMP_LABEL is a label, not
977
   NULL or a return.  */
978
bool
979
jump_to_label_p (rtx insn)
980
{
981
  return (JUMP_P (insn)
982
          && JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL (insn)));
983
}
984
 
985
#ifdef HAVE_cc0
986
 
987
/* Return nonzero if X is an RTX that only sets the condition codes
988
   and has no side effects.  */
989
 
990
int
991
only_sets_cc0_p (const_rtx x)
992
{
993
  if (! x)
994
    return 0;
995
 
996
  if (INSN_P (x))
997
    x = PATTERN (x);
998
 
999
  return sets_cc0_p (x) == 1 && ! side_effects_p (x);
1000
}
1001
 
1002
/* Return 1 if X is an RTX that does nothing but set the condition codes
1003
   and CLOBBER or USE registers.
1004
   Return -1 if X does explicitly set the condition codes,
1005
   but also does other things.  */
1006
 
1007
int
1008
sets_cc0_p (const_rtx x)
1009
{
1010
  if (! x)
1011
    return 0;
1012
 
1013
  if (INSN_P (x))
1014
    x = PATTERN (x);
1015
 
1016
  if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
1017
    return 1;
1018
  if (GET_CODE (x) == PARALLEL)
1019
    {
1020
      int i;
1021
      int sets_cc0 = 0;
1022
      int other_things = 0;
1023
      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
1024
        {
1025
          if (GET_CODE (XVECEXP (x, 0, i)) == SET
1026
              && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
1027
            sets_cc0 = 1;
1028
          else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
1029
            other_things = 1;
1030
        }
1031
      return ! sets_cc0 ? 0 : other_things ? -1 : 1;
1032
    }
1033
  return 0;
1034
}
1035
#endif
1036
 
1037
/* Find all CODE_LABELs referred to in X, and increment their use
1038
   counts.  If INSN is a JUMP_INSN and there is at least one
1039
   CODE_LABEL referenced in INSN as a jump target, then store the last
1040
   one in JUMP_LABEL (INSN).  For a tablejump, this must be the label
1041
   for the ADDR_VEC.  Store any other jump targets as REG_LABEL_TARGET
1042
   notes.  If INSN is an INSN or a CALL_INSN or non-target operands of
1043
   a JUMP_INSN, and there is at least one CODE_LABEL referenced in
1044
   INSN, add a REG_LABEL_OPERAND note containing that label to INSN.
1045
   For returnjumps, the JUMP_LABEL will also be set as appropriate.
1046
 
1047
   Note that two labels separated by a loop-beginning note
1048
   must be kept distinct if we have not yet done loop-optimization,
1049
   because the gap between them is where loop-optimize
1050
   will want to move invariant code to.  CROSS_JUMP tells us
1051
   that loop-optimization is done with.  */
1052
 
1053
void
1054
mark_jump_label (rtx x, rtx insn, int in_mem)
1055
{
1056
  rtx asmop = extract_asm_operands (x);
1057
  if (asmop)
1058
    mark_jump_label_asm (asmop, insn);
1059
  else
1060
    mark_jump_label_1 (x, insn, in_mem != 0,
1061
                       (insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
1062
}
1063
 
1064
/* Worker function for mark_jump_label.  IN_MEM is TRUE when X occurs
1065
   within a (MEM ...).  IS_TARGET is TRUE when X is to be treated as a
1066
   jump-target; when the JUMP_LABEL field of INSN should be set or a
1067
   REG_LABEL_TARGET note should be added, not a REG_LABEL_OPERAND
1068
   note.  */
1069
 
1070
static void
1071
mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
1072
{
1073
  RTX_CODE code = GET_CODE (x);
1074
  int i;
1075
  const char *fmt;
1076
 
1077
  switch (code)
1078
    {
1079
    case PC:
1080
    case CC0:
1081
    case REG:
1082
    case CONST_INT:
1083
    case CONST_DOUBLE:
1084
    case CLOBBER:
1085
    case CALL:
1086
      return;
1087
 
1088
    case RETURN:
1089
    case SIMPLE_RETURN:
1090
      if (is_target)
1091
        {
1092
          gcc_assert (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == x);
1093
          JUMP_LABEL (insn) = x;
1094
        }
1095
      return;
1096
 
1097
    case MEM:
1098
      in_mem = true;
1099
      break;
1100
 
1101
    case SEQUENCE:
1102
      for (i = 0; i < XVECLEN (x, 0); i++)
1103
        mark_jump_label (PATTERN (XVECEXP (x, 0, i)),
1104
                         XVECEXP (x, 0, i), 0);
1105
      return;
1106
 
1107
    case SYMBOL_REF:
1108
      if (!in_mem)
1109
        return;
1110
 
1111
      /* If this is a constant-pool reference, see if it is a label.  */
1112
      if (CONSTANT_POOL_ADDRESS_P (x))
1113
        mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
1114
      break;
1115
 
1116
      /* Handle operands in the condition of an if-then-else as for a
1117
         non-jump insn.  */
1118
    case IF_THEN_ELSE:
1119
      if (!is_target)
1120
        break;
1121
      mark_jump_label_1 (XEXP (x, 0), insn, in_mem, false);
1122
      mark_jump_label_1 (XEXP (x, 1), insn, in_mem, true);
1123
      mark_jump_label_1 (XEXP (x, 2), insn, in_mem, true);
1124
      return;
1125
 
1126
    case LABEL_REF:
1127
      {
1128
        rtx label = XEXP (x, 0);
1129
 
1130
        /* Ignore remaining references to unreachable labels that
1131
           have been deleted.  */
1132
        if (NOTE_P (label)
1133
            && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL)
1134
          break;
1135
 
1136
        gcc_assert (LABEL_P (label));
1137
 
1138
        /* Ignore references to labels of containing functions.  */
1139
        if (LABEL_REF_NONLOCAL_P (x))
1140
          break;
1141
 
1142
        XEXP (x, 0) = label;
1143
        if (! insn || ! INSN_DELETED_P (insn))
1144
          ++LABEL_NUSES (label);
1145
 
1146
        if (insn)
1147
          {
1148
            if (is_target
1149
                /* Do not change a previous setting of JUMP_LABEL.  If the
1150
                   JUMP_LABEL slot is occupied by a different label,
1151
                   create a note for this label.  */
1152
                && (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
1153
              JUMP_LABEL (insn) = label;
1154
            else
1155
              {
1156
                enum reg_note kind
1157
                  = is_target ? REG_LABEL_TARGET : REG_LABEL_OPERAND;
1158
 
1159
                /* Add a REG_LABEL_OPERAND or REG_LABEL_TARGET note
1160
                   for LABEL unless there already is one.  All uses of
1161
                   a label, except for the primary target of a jump,
1162
                   must have such a note.  */
1163
                if (! find_reg_note (insn, kind, label))
1164
                  add_reg_note (insn, kind, label);
1165
              }
1166
          }
1167
        return;
1168
      }
1169
 
1170
  /* Do walk the labels in a vector, but not the first operand of an
1171
     ADDR_DIFF_VEC.  Don't set the JUMP_LABEL of a vector.  */
1172
    case ADDR_VEC:
1173
    case ADDR_DIFF_VEC:
1174
      if (! INSN_DELETED_P (insn))
1175
        {
1176
          int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
1177
 
1178
          for (i = 0; i < XVECLEN (x, eltnum); i++)
1179
            mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
1180
                               is_target);
1181
        }
1182
      return;
1183
 
1184
    default:
1185
      break;
1186
    }
1187
 
1188
  fmt = GET_RTX_FORMAT (code);
1189
 
1190
  /* The primary target of a tablejump is the label of the ADDR_VEC,
1191
     which is canonically mentioned *last* in the insn.  To get it
1192
     marked as JUMP_LABEL, we iterate over items in reverse order.  */
1193
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1194
    {
1195
      if (fmt[i] == 'e')
1196
        mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
1197
      else if (fmt[i] == 'E')
1198
        {
1199
          int j;
1200
 
1201
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1202
            mark_jump_label_1 (XVECEXP (x, i, j), insn, in_mem,
1203
                               is_target);
1204
        }
1205
    }
1206
}
1207
 
1208
/* Worker function for mark_jump_label.  Handle asm insns specially.
1209
   In particular, output operands need not be considered so we can
1210
   avoid re-scanning the replicated asm_operand.  Also, the asm_labels
1211
   need to be considered targets.  */
1212
 
1213
static void
1214
mark_jump_label_asm (rtx asmop, rtx insn)
1215
{
1216
  int i;
1217
 
1218
  for (i = ASM_OPERANDS_INPUT_LENGTH (asmop) - 1; i >= 0; --i)
1219
    mark_jump_label_1 (ASM_OPERANDS_INPUT (asmop, i), insn, false, false);
1220
 
1221
  for (i = ASM_OPERANDS_LABEL_LENGTH (asmop) - 1; i >= 0; --i)
1222
    mark_jump_label_1 (ASM_OPERANDS_LABEL (asmop, i), insn, false, true);
1223
}
1224
 
1225
/* Delete insn INSN from the chain of insns and update label ref counts
1226
   and delete insns now unreachable.
1227
 
1228
   Returns the first insn after INSN that was not deleted.
1229
 
1230
   Usage of this instruction is deprecated.  Use delete_insn instead and
1231
   subsequent cfg_cleanup pass to delete unreachable code if needed.  */
1232
 
1233
rtx
1234
delete_related_insns (rtx insn)
1235
{
1236
  int was_code_label = (LABEL_P (insn));
1237
  rtx note;
1238
  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
1239
 
1240
  while (next && INSN_DELETED_P (next))
1241
    next = NEXT_INSN (next);
1242
 
1243
  /* This insn is already deleted => return first following nondeleted.  */
1244
  if (INSN_DELETED_P (insn))
1245
    return next;
1246
 
1247
  delete_insn (insn);
1248
 
1249
  /* If instruction is followed by a barrier,
1250
     delete the barrier too.  */
1251
 
1252
  if (next != 0 && BARRIER_P (next))
1253
    delete_insn (next);
1254
 
1255
  /* If deleting a jump, decrement the count of the label,
1256
     and delete the label if it is now unused.  */
1257
 
1258
  if (jump_to_label_p (insn))
1259
    {
1260
      rtx lab = JUMP_LABEL (insn), lab_next;
1261
 
1262
      if (LABEL_NUSES (lab) == 0)
1263
        /* This can delete NEXT or PREV,
1264
           either directly if NEXT is JUMP_LABEL (INSN),
1265
           or indirectly through more levels of jumps.  */
1266
        delete_related_insns (lab);
1267
      else if (tablejump_p (insn, NULL, &lab_next))
1268
        {
1269
          /* If we're deleting the tablejump, delete the dispatch table.
1270
             We may not be able to kill the label immediately preceding
1271
             just yet, as it might be referenced in code leading up to
1272
             the tablejump.  */
1273
          delete_related_insns (lab_next);
1274
        }
1275
    }
1276
 
1277
  /* Likewise if we're deleting a dispatch table.  */
1278
 
1279
  if (JUMP_TABLE_DATA_P (insn))
1280
    {
1281
      rtx pat = PATTERN (insn);
1282
      int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
1283
      int len = XVECLEN (pat, diff_vec_p);
1284
 
1285
      for (i = 0; i < len; i++)
1286
        if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
1287
          delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
1288
      while (next && INSN_DELETED_P (next))
1289
        next = NEXT_INSN (next);
1290
      return next;
1291
    }
1292
 
1293
  /* Likewise for any JUMP_P / INSN / CALL_INSN with a
1294
     REG_LABEL_OPERAND or REG_LABEL_TARGET note.  */
1295
  if (INSN_P (insn))
1296
    for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
1297
      if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
1298
           || REG_NOTE_KIND (note) == REG_LABEL_TARGET)
1299
          /* This could also be a NOTE_INSN_DELETED_LABEL note.  */
1300
          && LABEL_P (XEXP (note, 0)))
1301
        if (LABEL_NUSES (XEXP (note, 0)) == 0)
1302
          delete_related_insns (XEXP (note, 0));
1303
 
1304
  while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev)))
1305
    prev = PREV_INSN (prev);
1306
 
1307
  /* If INSN was a label and a dispatch table follows it,
1308
     delete the dispatch table.  The tablejump must have gone already.
1309
     It isn't useful to fall through into a table.  */
1310
 
1311
  if (was_code_label
1312
      && NEXT_INSN (insn) != 0
1313
      && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
1314
    next = delete_related_insns (NEXT_INSN (insn));
1315
 
1316
  /* If INSN was a label, delete insns following it if now unreachable.  */
1317
 
1318
  if (was_code_label && prev && BARRIER_P (prev))
1319
    {
1320
      enum rtx_code code;
1321
      while (next)
1322
        {
1323
          code = GET_CODE (next);
1324
          if (code == NOTE)
1325
            next = NEXT_INSN (next);
1326
          /* Keep going past other deleted labels to delete what follows.  */
1327
          else if (code == CODE_LABEL && INSN_DELETED_P (next))
1328
            next = NEXT_INSN (next);
1329
          else if (code == BARRIER || INSN_P (next))
1330
            /* Note: if this deletes a jump, it can cause more
1331
               deletion of unreachable code, after a different label.
1332
               As long as the value from this recursive call is correct,
1333
               this invocation functions correctly.  */
1334
            next = delete_related_insns (next);
1335
          else
1336
            break;
1337
        }
1338
    }
1339
 
1340
  /* I feel a little doubtful about this loop,
1341
     but I see no clean and sure alternative way
1342
     to find the first insn after INSN that is not now deleted.
1343
     I hope this works.  */
1344
  while (next && INSN_DELETED_P (next))
1345
    next = NEXT_INSN (next);
1346
  return next;
1347
}
1348
 
1349
/* Delete a range of insns from FROM to TO, inclusive.
1350
   This is for the sake of peephole optimization, so assume
1351
   that whatever these insns do will still be done by a new
1352
   peephole insn that will replace them.  */
1353
 
1354
void
1355
delete_for_peephole (rtx from, rtx to)
1356
{
1357
  rtx insn = from;
1358
 
1359
  while (1)
1360
    {
1361
      rtx next = NEXT_INSN (insn);
1362
      rtx prev = PREV_INSN (insn);
1363
 
1364
      if (!NOTE_P (insn))
1365
        {
1366
          INSN_DELETED_P (insn) = 1;
1367
 
1368
          /* Patch this insn out of the chain.  */
1369
          /* We don't do this all at once, because we
1370
             must preserve all NOTEs.  */
1371
          if (prev)
1372
            NEXT_INSN (prev) = next;
1373
 
1374
          if (next)
1375
            PREV_INSN (next) = prev;
1376
        }
1377
 
1378
      if (insn == to)
1379
        break;
1380
      insn = next;
1381
    }
1382
 
1383
  /* Note that if TO is an unconditional jump
1384
     we *do not* delete the BARRIER that follows,
1385
     since the peephole that replaces this sequence
1386
     is also an unconditional jump in that case.  */
1387
}
1388
 
1389
/* A helper function for redirect_exp_1; examines its input X and returns
1390
   either a LABEL_REF around a label, or a RETURN if X was NULL.  */
1391
static rtx
1392
redirect_target (rtx x)
1393
{
1394
  if (x == NULL_RTX)
1395
    return ret_rtx;
1396
  if (!ANY_RETURN_P (x))
1397
    return gen_rtx_LABEL_REF (Pmode, x);
1398
  return x;
1399
}
1400
 
1401
/* Throughout LOC, redirect OLABEL to NLABEL.  Treat null OLABEL or
1402
   NLABEL as a return.  Accrue modifications into the change group.  */
1403
 
1404
static void
1405
redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
1406
{
1407
  rtx x = *loc;
1408
  RTX_CODE code = GET_CODE (x);
1409
  int i;
1410
  const char *fmt;
1411
 
1412
  if ((code == LABEL_REF && XEXP (x, 0) == olabel)
1413
      || x == olabel)
1414
    {
1415
      x = redirect_target (nlabel);
1416
      if (GET_CODE (x) == LABEL_REF && loc == &PATTERN (insn))
1417
        x = gen_rtx_SET (VOIDmode, pc_rtx, x);
1418
      validate_change (insn, loc, x, 1);
1419
      return;
1420
    }
1421
 
1422
  if (code == SET && SET_DEST (x) == pc_rtx
1423
      && ANY_RETURN_P (nlabel)
1424
      && GET_CODE (SET_SRC (x)) == LABEL_REF
1425
      && XEXP (SET_SRC (x), 0) == olabel)
1426
    {
1427
      validate_change (insn, loc, nlabel, 1);
1428
      return;
1429
    }
1430
 
1431
  if (code == IF_THEN_ELSE)
1432
    {
1433
      /* Skip the condition of an IF_THEN_ELSE.  We only want to
1434
         change jump destinations, not eventual label comparisons.  */
1435
      redirect_exp_1 (&XEXP (x, 1), olabel, nlabel, insn);
1436
      redirect_exp_1 (&XEXP (x, 2), olabel, nlabel, insn);
1437
      return;
1438
    }
1439
 
1440
  fmt = GET_RTX_FORMAT (code);
1441
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1442
    {
1443
      if (fmt[i] == 'e')
1444
        redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
1445
      else if (fmt[i] == 'E')
1446
        {
1447
          int j;
1448
          for (j = 0; j < XVECLEN (x, i); j++)
1449
            redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
1450
        }
1451
    }
1452
}
1453
 
1454
/* Make JUMP go to NLABEL instead of where it jumps now.  Accrue
1455
   the modifications into the change group.  Return false if we did
1456
   not see how to do that.  */
1457
 
1458
int
1459
redirect_jump_1 (rtx jump, rtx nlabel)
1460
{
1461
  int ochanges = num_validated_changes ();
1462
  rtx *loc, asmop;
1463
 
1464
  gcc_assert (nlabel != NULL_RTX);
1465
  asmop = extract_asm_operands (PATTERN (jump));
1466
  if (asmop)
1467
    {
1468
      if (nlabel == NULL)
1469
        return 0;
1470
      gcc_assert (ASM_OPERANDS_LABEL_LENGTH (asmop) == 1);
1471
      loc = &ASM_OPERANDS_LABEL (asmop, 0);
1472
    }
1473
  else if (GET_CODE (PATTERN (jump)) == PARALLEL)
1474
    loc = &XVECEXP (PATTERN (jump), 0, 0);
1475
  else
1476
    loc = &PATTERN (jump);
1477
 
1478
  redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
1479
  return num_validated_changes () > ochanges;
1480
}
1481
 
1482
/* Make JUMP go to NLABEL instead of where it jumps now.  If the old
1483
   jump target label is unused as a result, it and the code following
1484
   it may be deleted.
1485
 
1486
   Normally, NLABEL will be a label, but it may also be a RETURN rtx;
1487
   in that case we are to turn the jump into a (possibly conditional)
1488
   return insn.
1489
 
1490
   The return value will be 1 if the change was made, 0 if it wasn't
1491
   (this can only occur when trying to produce return insns).  */
1492
 
1493
int
1494
redirect_jump (rtx jump, rtx nlabel, int delete_unused)
1495
{
1496
  rtx olabel = JUMP_LABEL (jump);
1497
 
1498
  if (!nlabel)
1499
    {
1500
      /* If there is no label, we are asked to redirect to the EXIT block.
1501
         When before the epilogue is emitted, return/simple_return cannot be
1502
         created so we return 0 immediately.  After the epilogue is emitted,
1503
         we always expect a label, either a non-null label, or a
1504
         return/simple_return RTX.  */
1505
 
1506
      if (!epilogue_completed)
1507
        return 0;
1508
      gcc_unreachable ();
1509
    }
1510
 
1511
  if (nlabel == olabel)
1512
    return 1;
1513
 
1514
  if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ())
1515
    return 0;
1516
 
1517
  redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0);
1518
  return 1;
1519
}
1520
 
1521
/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
1522
   NLABEL in JUMP.
1523
   If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
1524
   count has dropped to zero.  */
1525
void
1526
redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
1527
                 int invert)
1528
{
1529
  rtx note;
1530
 
1531
  gcc_assert (JUMP_LABEL (jump) == olabel);
1532
 
1533
  /* Negative DELETE_UNUSED used to be used to signalize behavior on
1534
     moving FUNCTION_END note.  Just sanity check that no user still worry
1535
     about this.  */
1536
  gcc_assert (delete_unused >= 0);
1537
  JUMP_LABEL (jump) = nlabel;
1538
  if (!ANY_RETURN_P (nlabel))
1539
    ++LABEL_NUSES (nlabel);
1540
 
1541
  /* Update labels in any REG_EQUAL note.  */
1542
  if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
1543
    {
1544
      if (ANY_RETURN_P (nlabel)
1545
          || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
1546
        remove_note (jump, note);
1547
      else
1548
        {
1549
          redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump);
1550
          confirm_change_group ();
1551
        }
1552
    }
1553
 
1554
  if (!ANY_RETURN_P (olabel)
1555
      && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
1556
      /* Undefined labels will remain outside the insn stream.  */
1557
      && INSN_UID (olabel))
1558
    delete_related_insns (olabel);
1559
  if (invert)
1560
    invert_br_probabilities (jump);
1561
}
1562
 
1563
/* Invert the jump condition X contained in jump insn INSN.  Accrue the
1564
   modifications into the change group.  Return nonzero for success.  */
1565
static int
1566
invert_exp_1 (rtx x, rtx insn)
1567
{
1568
  RTX_CODE code = GET_CODE (x);
1569
 
1570
  if (code == IF_THEN_ELSE)
1571
    {
1572
      rtx comp = XEXP (x, 0);
1573
      rtx tem;
1574
      enum rtx_code reversed_code;
1575
 
1576
      /* We can do this in two ways:  The preferable way, which can only
1577
         be done if this is not an integer comparison, is to reverse
1578
         the comparison code.  Otherwise, swap the THEN-part and ELSE-part
1579
         of the IF_THEN_ELSE.  If we can't do either, fail.  */
1580
 
1581
      reversed_code = reversed_comparison_code (comp, insn);
1582
 
1583
      if (reversed_code != UNKNOWN)
1584
        {
1585
          validate_change (insn, &XEXP (x, 0),
1586
                           gen_rtx_fmt_ee (reversed_code,
1587
                                           GET_MODE (comp), XEXP (comp, 0),
1588
                                           XEXP (comp, 1)),
1589
                           1);
1590
          return 1;
1591
        }
1592
 
1593
      tem = XEXP (x, 1);
1594
      validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
1595
      validate_change (insn, &XEXP (x, 2), tem, 1);
1596
      return 1;
1597
    }
1598
  else
1599
    return 0;
1600
}
1601
 
1602
/* Invert the condition of the jump JUMP, and make it jump to label
1603
   NLABEL instead of where it jumps now.  Accrue changes into the
1604
   change group.  Return false if we didn't see how to perform the
1605
   inversion and redirection.  */
1606
 
1607
int
1608
invert_jump_1 (rtx jump, rtx nlabel)
1609
{
1610
  rtx x = pc_set (jump);
1611
  int ochanges;
1612
  int ok;
1613
 
1614
  ochanges = num_validated_changes ();
1615
  if (x == NULL)
1616
    return 0;
1617
  ok = invert_exp_1 (SET_SRC (x), jump);
1618
  gcc_assert (ok);
1619
 
1620
  if (num_validated_changes () == ochanges)
1621
    return 0;
1622
 
1623
  /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
1624
     in Pmode, so checking this is not merely an optimization.  */
1625
  return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
1626
}
1627
 
1628
/* Invert the condition of the jump JUMP, and make it jump to label
1629
   NLABEL instead of where it jumps now.  Return true if successful.  */
1630
 
1631
int
1632
invert_jump (rtx jump, rtx nlabel, int delete_unused)
1633
{
1634
  rtx olabel = JUMP_LABEL (jump);
1635
 
1636
  if (invert_jump_1 (jump, nlabel) && apply_change_group ())
1637
    {
1638
      redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1);
1639
      return 1;
1640
    }
1641
  cancel_changes (0);
1642
  return 0;
1643
}
1644
 
1645
 
1646
/* Like rtx_equal_p except that it considers two REGs as equal
1647
   if they renumber to the same value and considers two commutative
1648
   operations to be the same if the order of the operands has been
1649
   reversed.  */
1650
 
1651
int
1652
rtx_renumbered_equal_p (const_rtx x, const_rtx y)
1653
{
1654
  int i;
1655
  const enum rtx_code code = GET_CODE (x);
1656
  const char *fmt;
1657
 
1658
  if (x == y)
1659
    return 1;
1660
 
1661
  if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x))))
1662
      && (REG_P (y) || (GET_CODE (y) == SUBREG
1663
                                  && REG_P (SUBREG_REG (y)))))
1664
    {
1665
      int reg_x = -1, reg_y = -1;
1666
      int byte_x = 0, byte_y = 0;
1667
      struct subreg_info info;
1668
 
1669
      if (GET_MODE (x) != GET_MODE (y))
1670
        return 0;
1671
 
1672
      /* If we haven't done any renumbering, don't
1673
         make any assumptions.  */
1674
      if (reg_renumber == 0)
1675
        return rtx_equal_p (x, y);
1676
 
1677
      if (code == SUBREG)
1678
        {
1679
          reg_x = REGNO (SUBREG_REG (x));
1680
          byte_x = SUBREG_BYTE (x);
1681
 
1682
          if (reg_renumber[reg_x] >= 0)
1683
            {
1684
              subreg_get_info (reg_renumber[reg_x],
1685
                               GET_MODE (SUBREG_REG (x)), byte_x,
1686
                               GET_MODE (x), &info);
1687
              if (!info.representable_p)
1688
                return 0;
1689
              reg_x = info.offset;
1690
              byte_x = 0;
1691
            }
1692
        }
1693
      else
1694
        {
1695
          reg_x = REGNO (x);
1696
          if (reg_renumber[reg_x] >= 0)
1697
            reg_x = reg_renumber[reg_x];
1698
        }
1699
 
1700
      if (GET_CODE (y) == SUBREG)
1701
        {
1702
          reg_y = REGNO (SUBREG_REG (y));
1703
          byte_y = SUBREG_BYTE (y);
1704
 
1705
          if (reg_renumber[reg_y] >= 0)
1706
            {
1707
              subreg_get_info (reg_renumber[reg_y],
1708
                               GET_MODE (SUBREG_REG (y)), byte_y,
1709
                               GET_MODE (y), &info);
1710
              if (!info.representable_p)
1711
                return 0;
1712
              reg_y = info.offset;
1713
              byte_y = 0;
1714
            }
1715
        }
1716
      else
1717
        {
1718
          reg_y = REGNO (y);
1719
          if (reg_renumber[reg_y] >= 0)
1720
            reg_y = reg_renumber[reg_y];
1721
        }
1722
 
1723
      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
1724
    }
1725
 
1726
  /* Now we have disposed of all the cases
1727
     in which different rtx codes can match.  */
1728
  if (code != GET_CODE (y))
1729
    return 0;
1730
 
1731
  switch (code)
1732
    {
1733
    case PC:
1734
    case CC0:
1735
    case ADDR_VEC:
1736
    case ADDR_DIFF_VEC:
1737
    case CONST_INT:
1738
    case CONST_DOUBLE:
1739
      return 0;
1740
 
1741
    case LABEL_REF:
1742
      /* We can't assume nonlocal labels have their following insns yet.  */
1743
      if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
1744
        return XEXP (x, 0) == XEXP (y, 0);
1745
 
1746
      /* Two label-refs are equivalent if they point at labels
1747
         in the same position in the instruction stream.  */
1748
      return (next_real_insn (XEXP (x, 0))
1749
              == next_real_insn (XEXP (y, 0)));
1750
 
1751
    case SYMBOL_REF:
1752
      return XSTR (x, 0) == XSTR (y, 0);
1753
 
1754
    case CODE_LABEL:
1755
      /* If we didn't match EQ equality above, they aren't the same.  */
1756
      return 0;
1757
 
1758
    default:
1759
      break;
1760
    }
1761
 
1762
  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
1763
 
1764
  if (GET_MODE (x) != GET_MODE (y))
1765
    return 0;
1766
 
1767
  /* MEMs refering to different address space are not equivalent.  */
1768
  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
1769
    return 0;
1770
 
1771
  /* For commutative operations, the RTX match if the operand match in any
1772
     order.  Also handle the simple binary and unary cases without a loop.  */
1773
  if (targetm.commutative_p (x, UNKNOWN))
1774
    return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
1775
             && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
1776
            || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
1777
                && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
1778
  else if (NON_COMMUTATIVE_P (x))
1779
    return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
1780
            && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
1781
  else if (UNARY_P (x))
1782
    return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));
1783
 
1784
  /* Compare the elements.  If any pair of corresponding elements
1785
     fail to match, return 0 for the whole things.  */
1786
 
1787
  fmt = GET_RTX_FORMAT (code);
1788
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1789
    {
1790
      int j;
1791
      switch (fmt[i])
1792
        {
1793
        case 'w':
1794
          if (XWINT (x, i) != XWINT (y, i))
1795
            return 0;
1796
          break;
1797
 
1798
        case 'i':
1799
          if (XINT (x, i) != XINT (y, i))
1800
            {
1801
              if (((code == ASM_OPERANDS && i == 6)
1802
                   || (code == ASM_INPUT && i == 1))
1803
                  && locator_eq (XINT (x, i), XINT (y, i)))
1804
                break;
1805
              return 0;
1806
            }
1807
          break;
1808
 
1809
        case 't':
1810
          if (XTREE (x, i) != XTREE (y, i))
1811
            return 0;
1812
          break;
1813
 
1814
        case 's':
1815
          if (strcmp (XSTR (x, i), XSTR (y, i)))
1816
            return 0;
1817
          break;
1818
 
1819
        case 'e':
1820
          if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
1821
            return 0;
1822
          break;
1823
 
1824
        case 'u':
1825
          if (XEXP (x, i) != XEXP (y, i))
1826
            return 0;
1827
          /* Fall through.  */
1828
        case '0':
1829
          break;
1830
 
1831
        case 'E':
1832
          if (XVECLEN (x, i) != XVECLEN (y, i))
1833
            return 0;
1834
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
1835
            if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
1836
              return 0;
1837
          break;
1838
 
1839
        default:
1840
          gcc_unreachable ();
1841
        }
1842
    }
1843
  return 1;
1844
}
1845
 
1846
/* If X is a hard register or equivalent to one or a subregister of one,
1847
   return the hard register number.  If X is a pseudo register that was not
1848
   assigned a hard register, return the pseudo register number.  Otherwise,
1849
   return -1.  Any rtx is valid for X.  */
1850
 
1851
int
1852
true_regnum (const_rtx x)
1853
{
1854
  if (REG_P (x))
1855
    {
1856
      if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
1857
        return reg_renumber[REGNO (x)];
1858
      return REGNO (x);
1859
    }
1860
  if (GET_CODE (x) == SUBREG)
1861
    {
1862
      int base = true_regnum (SUBREG_REG (x));
1863
      if (base >= 0
1864
          && base < FIRST_PSEUDO_REGISTER)
1865
        {
1866
          struct subreg_info info;
1867
 
1868
          subreg_get_info (REGNO (SUBREG_REG (x)),
1869
                           GET_MODE (SUBREG_REG (x)),
1870
                           SUBREG_BYTE (x), GET_MODE (x), &info);
1871
 
1872
          if (info.representable_p)
1873
            return base + info.offset;
1874
        }
1875
    }
1876
  return -1;
1877
}
1878
 
1879
/* Return regno of the register REG and handle subregs too.  */
1880
unsigned int
1881
reg_or_subregno (const_rtx reg)
1882
{
1883
  if (GET_CODE (reg) == SUBREG)
1884
    reg = SUBREG_REG (reg);
1885
  gcc_assert (REG_P (reg));
1886
  return REGNO (reg);
1887
}

powered by: WebSVN 2.1.0

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