00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038 #include "system.h"
00039 #include "rtl.h"
00040 #include "tm_p.h"
00041 #include "flags.h"
00042 #include "hard-reg-set.h"
00043 #include "regs.h"
00044 #include "insn-config.h"
00045 #include "insn-attr.h"
00046 #include "recog.h"
00047 #include "function.h"
00048 #include "expr.h"
00049 #include "real.h"
00050 #include "except.h"
00051 #include "toplev.h"
00052 #include "reload.h"
00053 #include "predict.h"
00054
00055
00056
00057
00058
00059
00060
00061
00062 static rtx next_nonnote_insn_in_loop PARAMS ((rtx));
00063 static int init_label_info PARAMS ((rtx));
00064 static void mark_all_labels PARAMS ((rtx));
00065 static int duplicate_loop_exit_test PARAMS ((rtx));
00066 static void delete_computation PARAMS ((rtx));
00067 static void redirect_exp_1 PARAMS ((rtx *, rtx, rtx, rtx));
00068 static int redirect_exp PARAMS ((rtx, rtx, rtx));
00069 static void invert_exp_1 PARAMS ((rtx));
00070 static int invert_exp PARAMS ((rtx));
00071 static int returnjump_p_1 PARAMS ((rtx *, void *));
00072 static void delete_prior_computation PARAMS ((rtx, rtx));
00073
00074
00075
00076
00077 void
00078 rebuild_jump_labels (f)
00079 rtx f;
00080 {
00081 rtx insn;
00082 int max_uid = 0;
00083
00084 max_uid = init_label_info (f) + 1;
00085
00086 mark_all_labels (f);
00087
00088
00089
00090
00091
00092 for (insn = forced_labels; insn; insn = XEXP (insn, 1))
00093 if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
00094 LABEL_NUSES (XEXP (insn, 0))++;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void
00106 cleanup_barriers ()
00107 {
00108 rtx insn, next, prev;
00109 for (insn = get_insns (); insn; insn = next)
00110 {
00111 next = NEXT_INSN (insn);
00112 if (GET_CODE (insn) == BARRIER)
00113 {
00114 prev = prev_nonnote_insn (insn);
00115 if (GET_CODE (prev) == BARRIER)
00116 delete_barrier (insn);
00117 else if (prev != PREV_INSN (insn))
00118 reorder_insns (insn, insn, prev);
00119 }
00120 }
00121 }
00122
00123
00124
00125
00126
00127 static rtx
00128 next_nonnote_insn_in_loop (insn)
00129 rtx insn;
00130 {
00131 while (insn)
00132 {
00133 insn = NEXT_INSN (insn);
00134 if (insn == 0 || GET_CODE (insn) != NOTE)
00135 break;
00136 if (GET_CODE (insn) == NOTE
00137 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
00138 return NULL_RTX;
00139 }
00140
00141 return insn;
00142 }
00143
00144 void
00145 copy_loop_headers (f)
00146 rtx f;
00147 {
00148 rtx insn, next;
00149
00150 for (insn = f; insn; insn = next)
00151 {
00152 rtx temp, temp1;
00153
00154 next = NEXT_INSN (insn);
00155
00156
00157
00158
00159
00160 if (GET_CODE (insn) == NOTE
00161 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
00162 && (temp1 = next_nonnote_insn_in_loop (insn)) != 0
00163 && any_uncondjump_p (temp1) && onlyjump_p (temp1))
00164 {
00165 temp = PREV_INSN (insn);
00166 if (duplicate_loop_exit_test (insn))
00167 {
00168 next = NEXT_INSN (temp);
00169 }
00170 }
00171 }
00172 }
00173
00174 void
00175 purge_line_number_notes (f)
00176 rtx f;
00177 {
00178 rtx last_note = 0;
00179 rtx insn;
00180
00181
00182
00183
00184
00185 for (insn = f; insn; insn = NEXT_INSN (insn))
00186 if (GET_CODE (insn) == NOTE)
00187 {
00188 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
00189
00190
00191 last_note = NULL_RTX;
00192 else if (NOTE_LINE_NUMBER (insn) >= 0)
00193 {
00194
00195 if (last_note
00196 && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
00197 && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))
00198 {
00199 delete_related_insns (insn);
00200 continue;
00201 }
00202
00203 last_note = insn;
00204 }
00205 }
00206 }
00207
00208
00209
00210
00211 static int
00212 init_label_info (f)
00213 rtx f;
00214 {
00215 int largest_uid = 0;
00216 rtx insn;
00217
00218 for (insn = f; insn; insn = NEXT_INSN (insn))
00219 {
00220 if (GET_CODE (insn) == CODE_LABEL)
00221 LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
00222 else if (GET_CODE (insn) == JUMP_INSN)
00223 JUMP_LABEL (insn) = 0;
00224 else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
00225 {
00226 rtx note, next;
00227
00228 for (note = REG_NOTES (insn); note; note = next)
00229 {
00230 next = XEXP (note, 1);
00231 if (REG_NOTE_KIND (note) == REG_LABEL
00232 && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
00233 remove_note (insn, note);
00234 }
00235 }
00236 if (INSN_UID (insn) > largest_uid)
00237 largest_uid = INSN_UID (insn);
00238 }
00239
00240 return largest_uid;
00241 }
00242
00243
00244
00245
00246 static void
00247 mark_all_labels (f)
00248 rtx f;
00249 {
00250 rtx insn;
00251
00252 for (insn = f; insn; insn = NEXT_INSN (insn))
00253 if (INSN_P (insn))
00254 {
00255 if (GET_CODE (insn) == CALL_INSN
00256 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
00257 {
00258 mark_all_labels (XEXP (PATTERN (insn), 0));
00259 mark_all_labels (XEXP (PATTERN (insn), 1));
00260 mark_all_labels (XEXP (PATTERN (insn), 2));
00261
00262
00263
00264 if (XEXP (PATTERN (insn), 3))
00265 {
00266 rtx label_ref = gen_rtx_LABEL_REF (VOIDmode,
00267 XEXP (PATTERN (insn), 3));
00268 mark_jump_label (label_ref, insn, 0);
00269 XEXP (PATTERN (insn), 3) = XEXP (label_ref, 0);
00270 }
00271
00272 continue;
00273 }
00274
00275 mark_jump_label (PATTERN (insn), insn, 0);
00276 if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN)
00277 {
00278
00279
00280
00281 if (JUMP_LABEL (insn) == 0)
00282 {
00283 rtx label_note = find_reg_note (insn, REG_LABEL, NULL_RTX);
00284 if (label_note)
00285 {
00286
00287
00288 rtx label_ref = gen_rtx_LABEL_REF (VOIDmode,
00289 XEXP (label_note, 0));
00290
00291 mark_jump_label (label_ref, insn, 0);
00292 XEXP (label_note, 0) = XEXP (label_ref, 0);
00293 JUMP_LABEL (insn) = XEXP (label_note, 0);
00294 }
00295 }
00296 }
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 static int
00312 duplicate_loop_exit_test (loop_start)
00313 rtx loop_start;
00314 {
00315 rtx insn, set, reg, p, link;
00316 rtx copy = 0, first_copy = 0;
00317 int num_insns = 0;
00318 rtx exitcode
00319 = NEXT_INSN (JUMP_LABEL (next_nonnote_insn_in_loop (loop_start)));
00320 rtx lastexit;
00321 int max_reg = max_reg_num ();
00322 rtx *reg_map = 0;
00323 rtx loop_pre_header_label;
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 for (insn = exitcode;
00339 insn
00340 && ! (GET_CODE (insn) == NOTE
00341 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END);
00342 insn = NEXT_INSN (insn))
00343 {
00344 switch (GET_CODE (insn))
00345 {
00346 case CODE_LABEL:
00347 case CALL_INSN:
00348 return 0;
00349 case NOTE:
00350
00351 if (optimize < 2
00352 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
00353 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
00354
00355
00356
00357
00358 return 0;
00359
00360 break;
00361 case JUMP_INSN:
00362 case INSN:
00363
00364
00365 while ((p = find_reg_note (insn, REG_WAS_0, NULL_RTX)) != 0)
00366 remove_note (insn, p);
00367 if (++num_insns > 20
00368 || find_reg_note (insn, REG_RETVAL, NULL_RTX)
00369 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
00370 return 0;
00371 break;
00372 default:
00373 break;
00374 }
00375 }
00376
00377
00378 if (insn == 0)
00379 return 0;
00380
00381 lastexit = insn;
00382
00383
00384
00385 for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
00386 if (GET_CODE (insn) == INSN
00387 && (set = single_set (insn)) != 0
00388 && ((reg = SET_DEST (set), GET_CODE (reg) == REG)
00389 || (GET_CODE (reg) == SUBREG
00390 && (reg = SUBREG_REG (reg), GET_CODE (reg) == REG)))
00391 && REGNO (reg) >= FIRST_PSEUDO_REGISTER
00392 && REGNO_FIRST_UID (REGNO (reg)) == INSN_UID (insn))
00393 {
00394 for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p))
00395 if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (p))
00396 break;
00397
00398 if (p != lastexit)
00399 {
00400
00401
00402 if (reg_map == 0)
00403 reg_map = (rtx *) xcalloc (max_reg, sizeof (rtx));
00404
00405 REG_LOOP_TEST_P (reg) = 1;
00406
00407 reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg));
00408 }
00409 }
00410 loop_pre_header_label = gen_label_rtx ();
00411
00412
00413 for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
00414 {
00415 switch (GET_CODE (insn))
00416 {
00417 case BARRIER:
00418 copy = emit_barrier_before (loop_start);
00419 break;
00420 case NOTE:
00421
00422 if (NOTE_LINE_NUMBER (insn) >= 0)
00423 {
00424 copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start);
00425 NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
00426 }
00427 break;
00428
00429 case INSN:
00430 copy = emit_insn_before (copy_insn (PATTERN (insn)), loop_start);
00431 if (reg_map)
00432 replace_regs (PATTERN (copy), reg_map, max_reg, 1);
00433
00434 mark_jump_label (PATTERN (copy), copy, 0);
00435 INSN_SCOPE (copy) = INSN_SCOPE (insn);
00436
00437
00438
00439 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00440 if (REG_NOTE_KIND (link) != REG_LABEL)
00441 {
00442 if (GET_CODE (link) == EXPR_LIST)
00443 REG_NOTES (copy)
00444 = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
00445 XEXP (link, 0),
00446 REG_NOTES (copy)));
00447 else
00448 REG_NOTES (copy)
00449 = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
00450 XEXP (link, 0),
00451 REG_NOTES (copy)));
00452 }
00453
00454 if (reg_map && REG_NOTES (copy))
00455 replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
00456 break;
00457
00458 case JUMP_INSN:
00459 copy = emit_jump_insn_before (copy_insn (PATTERN (insn)),
00460 loop_start);
00461 INSN_SCOPE (copy) = INSN_SCOPE (insn);
00462 if (reg_map)
00463 replace_regs (PATTERN (copy), reg_map, max_reg, 1);
00464 mark_jump_label (PATTERN (copy), copy, 0);
00465 if (REG_NOTES (insn))
00466 {
00467 REG_NOTES (copy) = copy_insn_1 (REG_NOTES (insn));
00468 if (reg_map)
00469 replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
00470 }
00471
00472
00473
00474
00475 if (any_condjump_p (copy))
00476 {
00477 rtx label = JUMP_LABEL (copy);
00478 if (label)
00479 {
00480
00481
00482 if (prev_nonnote_insn (label)
00483 && (prev_nonnote_insn (prev_nonnote_insn (label))
00484 == next_nonnote_insn (loop_start)))
00485 {
00486 predict_insn_def (copy, PRED_LOOP_HEADER, TAKEN);
00487
00488
00489 redirect_jump (copy, loop_pre_header_label, 0);
00490 }
00491 else
00492 predict_insn_def (copy, PRED_LOOP_HEADER, NOT_TAKEN);
00493 }
00494 }
00495 break;
00496
00497 default:
00498 abort ();
00499 }
00500
00501
00502
00503 if (! first_copy)
00504 first_copy = copy;
00505 }
00506
00507
00508
00509 if (! copy || GET_CODE (copy) != BARRIER)
00510 {
00511 copy = emit_jump_insn_before (gen_jump (get_label_after (insn)),
00512 loop_start);
00513
00514
00515
00516
00517
00518 if (! first_copy)
00519 first_copy = copy;
00520
00521 mark_jump_label (PATTERN (copy), copy, 0);
00522 emit_barrier_before (loop_start);
00523 }
00524
00525 emit_label_before (loop_pre_header_label, loop_start);
00526
00527
00528
00529
00530 reg_scan_update (first_copy, copy, max_reg);
00531
00532
00533 emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
00534
00535 delete_related_insns (next_nonnote_insn (loop_start));
00536
00537
00538 if (reg_map)
00539 free (reg_map);
00540
00541 return 1;
00542 }
00543
00544
00545
00546
00547
00548
00549
00550 bool
00551 squeeze_notes (startp, endp)
00552 rtx* startp;
00553 rtx* endp;
00554 {
00555 rtx start = *startp;
00556 rtx end = *endp;
00557
00558 rtx insn;
00559 rtx next;
00560 rtx last = NULL;
00561 rtx past_end = NEXT_INSN (end);
00562
00563 for (insn = start; insn != past_end; insn = next)
00564 {
00565 next = NEXT_INSN (insn);
00566 if (GET_CODE (insn) == NOTE
00567 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
00568 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
00569 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
00570 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
00571 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT
00572 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP))
00573 {
00574 if (insn == start)
00575 start = next;
00576 else
00577 {
00578 rtx prev = PREV_INSN (insn);
00579 PREV_INSN (insn) = PREV_INSN (start);
00580 NEXT_INSN (insn) = start;
00581 NEXT_INSN (PREV_INSN (insn)) = insn;
00582 PREV_INSN (NEXT_INSN (insn)) = insn;
00583 NEXT_INSN (prev) = next;
00584 PREV_INSN (next) = prev;
00585 }
00586 }
00587 else
00588 last = insn;
00589 }
00590
00591
00592 if (start == past_end)
00593 return true;
00594
00595 end = last;
00596
00597 *startp = start;
00598 *endp = end;
00599 return false;
00600 }
00601
00602
00603
00604 rtx
00605 get_label_before (insn)
00606 rtx insn;
00607 {
00608 rtx label;
00609
00610
00611
00612 label = prev_nonnote_insn (insn);
00613
00614 if (label == 0 || GET_CODE (label) != CODE_LABEL)
00615 {
00616 rtx prev = PREV_INSN (insn);
00617
00618 label = gen_label_rtx ();
00619 emit_label_after (label, prev);
00620 LABEL_NUSES (label) = 0;
00621 }
00622 return label;
00623 }
00624
00625
00626
00627 rtx
00628 get_label_after (insn)
00629 rtx insn;
00630 {
00631 rtx label;
00632
00633
00634
00635 label = next_nonnote_insn (insn);
00636
00637 if (label == 0 || GET_CODE (label) != CODE_LABEL)
00638 {
00639 label = gen_label_rtx ();
00640 emit_label_after (label, insn);
00641 LABEL_NUSES (label) = 0;
00642 }
00643 return label;
00644 }
00645
00646
00647
00648
00649
00650
00651
00652 enum rtx_code
00653 reversed_comparison_code_parts (code, arg0, arg1, insn)
00654 rtx insn, arg0, arg1;
00655 enum rtx_code code;
00656 {
00657 enum machine_mode mode;
00658
00659
00660 if (GET_RTX_CLASS (code) != '<')
00661 return UNKNOWN;
00662
00663 mode = GET_MODE (arg0);
00664 if (mode == VOIDmode)
00665 mode = GET_MODE (arg1);
00666
00667
00668
00669
00670 #ifdef REVERSIBLE_CC_MODE
00671 if (GET_MODE_CLASS (mode) == MODE_CC
00672 && REVERSIBLE_CC_MODE (mode))
00673 {
00674 #ifdef REVERSE_CONDITION
00675 return REVERSE_CONDITION (code, mode);
00676 #endif
00677 return reverse_condition (code);
00678 }
00679 #endif
00680
00681
00682 switch (code)
00683 {
00684 case GEU:
00685 case GTU:
00686 case LEU:
00687 case LTU:
00688 case NE:
00689 case EQ:
00690
00691
00692
00693 return reverse_condition (code);
00694 case ORDERED:
00695 case UNORDERED:
00696 case LTGT:
00697 case UNEQ:
00698
00699
00700 return reverse_condition_maybe_unordered (code);
00701 case UNLT:
00702 case UNLE:
00703 case UNGT:
00704 case UNGE:
00705
00706 return UNKNOWN;
00707 default:
00708 break;
00709 }
00710
00711 if (GET_MODE_CLASS (mode) == MODE_CC
00712 #ifdef HAVE_cc0
00713 || arg0 == cc0_rtx
00714 #endif
00715 )
00716 {
00717 rtx prev;
00718
00719
00720
00721
00722 if (! insn)
00723 return UNKNOWN;
00724
00725 for (prev = prev_nonnote_insn (insn);
00726 prev != 0 && GET_CODE (prev) != CODE_LABEL;
00727 prev = prev_nonnote_insn (prev))
00728 {
00729 rtx set = set_of (arg0, prev);
00730 if (set && GET_CODE (set) == SET
00731 && rtx_equal_p (SET_DEST (set), arg0))
00732 {
00733 rtx src = SET_SRC (set);
00734
00735 if (GET_CODE (src) == COMPARE)
00736 {
00737 rtx comparison = src;
00738 arg0 = XEXP (src, 0);
00739 mode = GET_MODE (arg0);
00740 if (mode == VOIDmode)
00741 mode = GET_MODE (XEXP (comparison, 1));
00742 break;
00743 }
00744
00745
00746 if (REG_P (src))
00747 {
00748 arg0 = src;
00749 continue;
00750 }
00751 }
00752
00753
00754 if (set)
00755 return UNKNOWN;
00756 }
00757 }
00758
00759
00760
00761 if (GET_CODE (arg0) == CONST_INT
00762 || (GET_MODE (arg0) != VOIDmode
00763 && GET_MODE_CLASS (mode) != MODE_CC
00764 && !HONOR_NANS (mode)))
00765 return reverse_condition (code);
00766
00767 return UNKNOWN;
00768 }
00769
00770
00771
00772 enum rtx_code
00773 reversed_comparison_code (comparison, insn)
00774 rtx comparison, insn;
00775 {
00776 if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
00777 return UNKNOWN;
00778 return reversed_comparison_code_parts (GET_CODE (comparison),
00779 XEXP (comparison, 0),
00780 XEXP (comparison, 1), insn);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 enum rtx_code
00792 reverse_condition (code)
00793 enum rtx_code code;
00794 {
00795 switch (code)
00796 {
00797 case EQ:
00798 return NE;
00799 case NE:
00800 return EQ;
00801 case GT:
00802 return LE;
00803 case GE:
00804 return LT;
00805 case LT:
00806 return GE;
00807 case LE:
00808 return GT;
00809 case GTU:
00810 return LEU;
00811 case GEU:
00812 return LTU;
00813 case LTU:
00814 return GEU;
00815 case LEU:
00816 return GTU;
00817 case UNORDERED:
00818 return ORDERED;
00819 case ORDERED:
00820 return UNORDERED;
00821
00822 case UNLT:
00823 case UNLE:
00824 case UNGT:
00825 case UNGE:
00826 case UNEQ:
00827 case LTGT:
00828 return UNKNOWN;
00829
00830 default:
00831 abort ();
00832 }
00833 }
00834
00835
00836
00837
00838
00839 enum rtx_code
00840 reverse_condition_maybe_unordered (code)
00841 enum rtx_code code;
00842 {
00843 switch (code)
00844 {
00845 case EQ:
00846 return NE;
00847 case NE:
00848 return EQ;
00849 case GT:
00850 return UNLE;
00851 case GE:
00852 return UNLT;
00853 case LT:
00854 return UNGE;
00855 case LE:
00856 return UNGT;
00857 case LTGT:
00858 return UNEQ;
00859 case UNORDERED:
00860 return ORDERED;
00861 case ORDERED:
00862 return UNORDERED;
00863 case UNLT:
00864 return GE;
00865 case UNLE:
00866 return GT;
00867 case UNGT:
00868 return LE;
00869 case UNGE:
00870 return LT;
00871 case UNEQ:
00872 return LTGT;
00873
00874 default:
00875 abort ();
00876 }
00877 }
00878
00879
00880
00881
00882 enum rtx_code
00883 swap_condition (code)
00884 enum rtx_code code;
00885 {
00886 switch (code)
00887 {
00888 case EQ:
00889 case NE:
00890 case UNORDERED:
00891 case ORDERED:
00892 case UNEQ:
00893 case LTGT:
00894 return code;
00895
00896 case GT:
00897 return LT;
00898 case GE:
00899 return LE;
00900 case LT:
00901 return GT;
00902 case LE:
00903 return GE;
00904 case GTU:
00905 return LTU;
00906 case GEU:
00907 return LEU;
00908 case LTU:
00909 return GTU;
00910 case LEU:
00911 return GEU;
00912 case UNLT:
00913 return UNGT;
00914 case UNLE:
00915 return UNGE;
00916 case UNGT:
00917 return UNLT;
00918 case UNGE:
00919 return UNLE;
00920
00921 default:
00922 abort ();
00923 }
00924 }
00925
00926
00927
00928
00929
00930 enum rtx_code
00931 unsigned_condition (code)
00932 enum rtx_code code;
00933 {
00934 switch (code)
00935 {
00936 case EQ:
00937 case NE:
00938 case GTU:
00939 case GEU:
00940 case LTU:
00941 case LEU:
00942 return code;
00943
00944 case GT:
00945 return GTU;
00946 case GE:
00947 return GEU;
00948 case LT:
00949 return LTU;
00950 case LE:
00951 return LEU;
00952
00953 default:
00954 abort ();
00955 }
00956 }
00957
00958
00959
00960 enum rtx_code
00961 signed_condition (code)
00962 enum rtx_code code;
00963 {
00964 switch (code)
00965 {
00966 case EQ:
00967 case NE:
00968 case GT:
00969 case GE:
00970 case LT:
00971 case LE:
00972 return code;
00973
00974 case GTU:
00975 return GT;
00976 case GEU:
00977 return GE;
00978 case LTU:
00979 return LT;
00980 case LEU:
00981 return LE;
00982
00983 default:
00984 abort ();
00985 }
00986 }
00987
00988
00989
00990
00991 int
00992 comparison_dominates_p (code1, code2)
00993 enum rtx_code code1, code2;
00994 {
00995
00996
00997
00998 if (code1 == UNKNOWN || code2 == UNKNOWN)
00999 return 0;
01000
01001 if (code1 == code2)
01002 return 1;
01003
01004 switch (code1)
01005 {
01006 case UNEQ:
01007 if (code2 == UNLE || code2 == UNGE)
01008 return 1;
01009 break;
01010
01011 case EQ:
01012 if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU
01013 || code2 == ORDERED)
01014 return 1;
01015 break;
01016
01017 case UNLT:
01018 if (code2 == UNLE || code2 == NE)
01019 return 1;
01020 break;
01021
01022 case LT:
01023 if (code2 == LE || code2 == NE || code2 == ORDERED || code2 == LTGT)
01024 return 1;
01025 break;
01026
01027 case UNGT:
01028 if (code2 == UNGE || code2 == NE)
01029 return 1;
01030 break;
01031
01032 case GT:
01033 if (code2 == GE || code2 == NE || code2 == ORDERED || code2 == LTGT)
01034 return 1;
01035 break;
01036
01037 case GE:
01038 case LE:
01039 if (code2 == ORDERED)
01040 return 1;
01041 break;
01042
01043 case LTGT:
01044 if (code2 == NE || code2 == ORDERED)
01045 return 1;
01046 break;
01047
01048 case LTU:
01049 if (code2 == LEU || code2 == NE)
01050 return 1;
01051 break;
01052
01053 case GTU:
01054 if (code2 == GEU || code2 == NE)
01055 return 1;
01056 break;
01057
01058 case UNORDERED:
01059 if (code2 == NE || code2 == UNEQ || code2 == UNLE || code2 == UNLT
01060 || code2 == UNGE || code2 == UNGT)
01061 return 1;
01062 break;
01063
01064 default:
01065 break;
01066 }
01067
01068 return 0;
01069 }
01070
01071
01072
01073 int
01074 simplejump_p (insn)
01075 rtx insn;
01076 {
01077 return (GET_CODE (insn) == JUMP_INSN
01078 && GET_CODE (PATTERN (insn)) == SET
01079 && GET_CODE (SET_DEST (PATTERN (insn))) == PC
01080 && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
01081 }
01082
01083
01084
01085 int
01086 tablejump_p (insn)
01087 rtx insn;
01088 {
01089 rtx table;
01090 return (GET_CODE (insn) == JUMP_INSN
01091 && JUMP_LABEL (insn)
01092 && NEXT_INSN (JUMP_LABEL (insn))
01093 && (table = next_active_insn (JUMP_LABEL (insn)))
01094 && GET_CODE (table) == JUMP_INSN
01095 && (GET_CODE (PATTERN (table)) == ADDR_VEC
01096 || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC));
01097 }
01098
01099
01100
01101
01102
01103
01104
01105 int
01106 condjump_p (insn)
01107 rtx insn;
01108 {
01109 rtx x = PATTERN (insn);
01110
01111 if (GET_CODE (x) != SET
01112 || GET_CODE (SET_DEST (x)) != PC)
01113 return 0;
01114
01115 x = SET_SRC (x);
01116 if (GET_CODE (x) == LABEL_REF)
01117 return 1;
01118 else
01119 return (GET_CODE (x) == IF_THEN_ELSE
01120 && ((GET_CODE (XEXP (x, 2)) == PC
01121 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
01122 || GET_CODE (XEXP (x, 1)) == RETURN))
01123 || (GET_CODE (XEXP (x, 1)) == PC
01124 && (GET_CODE (XEXP (x, 2)) == LABEL_REF
01125 || GET_CODE (XEXP (x, 2)) == RETURN))));
01126
01127 return 0;
01128 }
01129
01130
01131
01132
01133
01134
01135
01136 int
01137 condjump_in_parallel_p (insn)
01138 rtx insn;
01139 {
01140 rtx x = PATTERN (insn);
01141
01142 if (GET_CODE (x) != PARALLEL)
01143 return 0;
01144 else
01145 x = XVECEXP (x, 0, 0);
01146
01147 if (GET_CODE (x) != SET)
01148 return 0;
01149 if (GET_CODE (SET_DEST (x)) != PC)
01150 return 0;
01151 if (GET_CODE (SET_SRC (x)) == LABEL_REF)
01152 return 1;
01153 if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
01154 return 0;
01155 if (XEXP (SET_SRC (x), 2) == pc_rtx
01156 && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
01157 || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
01158 return 1;
01159 if (XEXP (SET_SRC (x), 1) == pc_rtx
01160 && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
01161 || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
01162 return 1;
01163 return 0;
01164 }
01165
01166
01167
01168 rtx
01169 pc_set (insn)
01170 rtx insn;
01171 {
01172 rtx pat;
01173 if (GET_CODE (insn) != JUMP_INSN)
01174 return NULL_RTX;
01175 pat = PATTERN (insn);
01176
01177
01178
01179 if (GET_CODE (pat) == PARALLEL)
01180 pat = XVECEXP (pat, 0, 0);
01181 if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == PC)
01182 return pat;
01183
01184 return NULL_RTX;
01185 }
01186
01187
01188
01189
01190 int
01191 any_uncondjump_p (insn)
01192 rtx insn;
01193 {
01194 rtx x = pc_set (insn);
01195 if (!x)
01196 return 0;
01197 if (GET_CODE (SET_SRC (x)) != LABEL_REF)
01198 return 0;
01199 return 1;
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209 int
01210 any_condjump_p (insn)
01211 rtx insn;
01212 {
01213 rtx x = pc_set (insn);
01214 enum rtx_code a, b;
01215
01216 if (!x)
01217 return 0;
01218 if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
01219 return 0;
01220
01221 a = GET_CODE (XEXP (SET_SRC (x), 1));
01222 b = GET_CODE (XEXP (SET_SRC (x), 2));
01223
01224 return ((b == PC && (a == LABEL_REF || a == RETURN))
01225 || (a == PC && (b == LABEL_REF || b == RETURN)));
01226 }
01227
01228
01229
01230 rtx
01231 condjump_label (insn)
01232 rtx insn;
01233 {
01234 rtx x = pc_set (insn);
01235
01236 if (!x)
01237 return NULL_RTX;
01238 x = SET_SRC (x);
01239 if (GET_CODE (x) == LABEL_REF)
01240 return x;
01241 if (GET_CODE (x) != IF_THEN_ELSE)
01242 return NULL_RTX;
01243 if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
01244 return XEXP (x, 1);
01245 if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
01246 return XEXP (x, 2);
01247 return NULL_RTX;
01248 }
01249
01250
01251
01252 static int
01253 returnjump_p_1 (loc, data)
01254 rtx *loc;
01255 void *data ATTRIBUTE_UNUSED;
01256 {
01257 rtx x = *loc;
01258
01259 return x && (GET_CODE (x) == RETURN
01260 || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
01261 }
01262
01263 int
01264 returnjump_p (insn)
01265 rtx insn;
01266 {
01267 if (GET_CODE (insn) != JUMP_INSN)
01268 return 0;
01269 return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
01270 }
01271
01272
01273
01274
01275 int
01276 onlyjump_p (insn)
01277 rtx insn;
01278 {
01279 rtx set;
01280
01281 if (GET_CODE (insn) != JUMP_INSN)
01282 return 0;
01283
01284 set = single_set (insn);
01285 if (set == NULL)
01286 return 0;
01287 if (GET_CODE (SET_DEST (set)) != PC)
01288 return 0;
01289 if (side_effects_p (SET_SRC (set)))
01290 return 0;
01291
01292 return 1;
01293 }
01294
01295 #ifdef HAVE_cc0
01296
01297
01298
01299
01300 int
01301 only_sets_cc0_p (x)
01302 rtx x;
01303 {
01304
01305 if (! x)
01306 return 0;
01307
01308 if (INSN_P (x))
01309 x = PATTERN (x);
01310
01311 return sets_cc0_p (x) == 1 && ! side_effects_p (x);
01312 }
01313
01314
01315
01316
01317
01318
01319 int
01320 sets_cc0_p (x)
01321 rtx x;
01322 {
01323
01324 if (! x)
01325 return 0;
01326
01327 if (INSN_P (x))
01328 x = PATTERN (x);
01329
01330 if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
01331 return 1;
01332 if (GET_CODE (x) == PARALLEL)
01333 {
01334 int i;
01335 int sets_cc0 = 0;
01336 int other_things = 0;
01337 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
01338 {
01339 if (GET_CODE (XVECEXP (x, 0, i)) == SET
01340 && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
01341 sets_cc0 = 1;
01342 else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
01343 other_things = 1;
01344 }
01345 return ! sets_cc0 ? 0 : other_things ? -1 : 1;
01346 }
01347 return 0;
01348 }
01349 #endif
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 rtx
01361 follow_jumps (label)
01362 rtx label;
01363 {
01364 rtx insn;
01365 rtx next;
01366 rtx value = label;
01367 int depth;
01368
01369 for (depth = 0;
01370 (depth < 10
01371 && (insn = next_active_insn (value)) != 0
01372 && GET_CODE (insn) == JUMP_INSN
01373 && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
01374 && onlyjump_p (insn))
01375 || GET_CODE (PATTERN (insn)) == RETURN)
01376 && (next = NEXT_INSN (insn))
01377 && GET_CODE (next) == BARRIER);
01378 depth++)
01379 {
01380
01381
01382
01383
01384 rtx tem;
01385 if (!reload_completed)
01386 for (tem = value; tem != insn; tem = NEXT_INSN (tem))
01387 if (GET_CODE (tem) == NOTE
01388 && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG
01389
01390
01391 || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0)))
01392 return value;
01393
01394
01395 if (JUMP_LABEL (insn) == label)
01396 return label;
01397
01398 tem = next_active_insn (JUMP_LABEL (insn));
01399 if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
01400 || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
01401 break;
01402
01403 value = JUMP_LABEL (insn);
01404 }
01405 if (depth == 10)
01406 return label;
01407 return value;
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 void
01425 mark_jump_label (x, insn, in_mem)
01426 rtx x;
01427 rtx insn;
01428 int in_mem;
01429 {
01430 RTX_CODE code = GET_CODE (x);
01431 int i;
01432 const char *fmt;
01433
01434 switch (code)
01435 {
01436 case PC:
01437 case CC0:
01438 case REG:
01439 case CONST_INT:
01440 case CONST_DOUBLE:
01441 case CLOBBER:
01442 case CALL:
01443 return;
01444
01445 case MEM:
01446 in_mem = 1;
01447 break;
01448
01449 case SYMBOL_REF:
01450 if (!in_mem)
01451 return;
01452
01453
01454 if (CONSTANT_POOL_ADDRESS_P (x))
01455 mark_jump_label (get_pool_constant (x), insn, in_mem);
01456 break;
01457
01458 case LABEL_REF:
01459 {
01460 rtx label = XEXP (x, 0);
01461
01462
01463
01464 if (GET_CODE (label) == NOTE
01465 && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
01466 break;
01467
01468 if (GET_CODE (label) != CODE_LABEL)
01469 abort ();
01470
01471
01472 if (LABEL_REF_NONLOCAL_P (x))
01473 break;
01474
01475 XEXP (x, 0) = label;
01476 if (! insn || ! INSN_DELETED_P (insn))
01477 ++LABEL_NUSES (label);
01478
01479 if (insn)
01480 {
01481 if (GET_CODE (insn) == JUMP_INSN)
01482 JUMP_LABEL (insn) = label;
01483 else
01484 {
01485
01486
01487
01488
01489 if (! find_reg_note (insn, REG_LABEL, label))
01490 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
01491 REG_NOTES (insn));
01492 }
01493 }
01494 return;
01495 }
01496
01497
01498
01499 case ADDR_VEC:
01500 case ADDR_DIFF_VEC:
01501 if (! INSN_DELETED_P (insn))
01502 {
01503 int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
01504
01505 for (i = 0; i < XVECLEN (x, eltnum); i++)
01506 mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, in_mem);
01507 }
01508 return;
01509
01510 default:
01511 break;
01512 }
01513
01514 fmt = GET_RTX_FORMAT (code);
01515 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
01516 {
01517 if (fmt[i] == 'e')
01518 mark_jump_label (XEXP (x, i), insn, in_mem);
01519 else if (fmt[i] == 'E')
01520 {
01521 int j;
01522 for (j = 0; j < XVECLEN (x, i); j++)
01523 mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
01524 }
01525 }
01526 }
01527
01528
01529
01530
01531
01532 void
01533 delete_jump (insn)
01534 rtx insn;
01535 {
01536 rtx set = single_set (insn);
01537
01538 if (set && GET_CODE (SET_DEST (set)) == PC)
01539 delete_computation (insn);
01540 }
01541
01542
01543
01544 void
01545 delete_barrier (insn)
01546 rtx insn;
01547 {
01548 if (GET_CODE (insn) != BARRIER)
01549 abort ();
01550
01551 delete_insn (insn);
01552 }
01553
01554
01555
01556
01557
01558 static void
01559 delete_prior_computation (note, insn)
01560 rtx note;
01561 rtx insn;
01562 {
01563 rtx our_prev;
01564 rtx reg = XEXP (note, 0);
01565
01566 for (our_prev = prev_nonnote_insn (insn);
01567 our_prev && (GET_CODE (our_prev) == INSN
01568 || GET_CODE (our_prev) == CALL_INSN);
01569 our_prev = prev_nonnote_insn (our_prev))
01570 {
01571 rtx pat = PATTERN (our_prev);
01572
01573
01574
01575 if (GET_CODE (our_prev) == CALL_INSN
01576 && (! CONST_OR_PURE_CALL_P (our_prev)
01577 || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL))
01578 break;
01579
01580
01581
01582
01583
01584 if (GET_CODE (pat) == SEQUENCE)
01585 break;
01586
01587 if (GET_CODE (pat) == USE
01588 && GET_CODE (XEXP (pat, 0)) == INSN)
01589
01590
01591 break;
01592
01593 if (reg_set_p (reg, pat))
01594 {
01595 if (side_effects_p (pat) && GET_CODE (our_prev) != CALL_INSN)
01596 break;
01597
01598 if (GET_CODE (pat) == PARALLEL)
01599 {
01600
01601
01602
01603 int i;
01604
01605 for (i = 0; i < XVECLEN (pat, 0); i++)
01606 {
01607 rtx part = XVECEXP (pat, 0, i);
01608
01609 if (GET_CODE (part) == SET
01610 && SET_DEST (part) != reg)
01611 break;
01612 }
01613
01614 if (i == XVECLEN (pat, 0))
01615 delete_computation (our_prev);
01616 }
01617 else if (GET_CODE (pat) == SET
01618 && GET_CODE (SET_DEST (pat)) == REG)
01619 {
01620 int dest_regno = REGNO (SET_DEST (pat));
01621 int dest_endregno
01622 = (dest_regno
01623 + (dest_regno < FIRST_PSEUDO_REGISTER
01624 ? HARD_REGNO_NREGS (dest_regno,
01625 GET_MODE (SET_DEST (pat))) : 1));
01626 int regno = REGNO (reg);
01627 int endregno
01628 = (regno
01629 + (regno < FIRST_PSEUDO_REGISTER
01630 ? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1));
01631
01632 if (dest_regno >= regno
01633 && dest_endregno <= endregno)
01634 delete_computation (our_prev);
01635
01636
01637
01638
01639
01640 else if (dest_regno <= regno
01641 && dest_endregno >= endregno)
01642 {
01643 int i;
01644
01645 REG_NOTES (our_prev)
01646 = gen_rtx_EXPR_LIST (REG_UNUSED, reg,
01647 REG_NOTES (our_prev));
01648
01649 for (i = dest_regno; i < dest_endregno; i++)
01650 if (! find_regno_note (our_prev, REG_UNUSED, i))
01651 break;
01652
01653 if (i == dest_endregno)
01654 delete_computation (our_prev);
01655 }
01656 }
01657
01658 break;
01659 }
01660
01661
01662
01663
01664 if (reg_overlap_mentioned_p (reg, pat))
01665 {
01666 XEXP (note, 1) = REG_NOTES (our_prev);
01667 REG_NOTES (our_prev) = note;
01668 break;
01669 }
01670 }
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 static void
01687 delete_computation (insn)
01688 rtx insn;
01689 {
01690 rtx note, next;
01691
01692 #ifdef HAVE_cc0
01693 if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
01694 {
01695 rtx prev = prev_nonnote_insn (insn);
01696
01697
01698
01699
01700
01701
01702 if (prev && GET_CODE (prev) == INSN
01703 && sets_cc0_p (PATTERN (prev)))
01704 {
01705 if (sets_cc0_p (PATTERN (prev)) > 0
01706 && ! side_effects_p (PATTERN (prev)))
01707 delete_computation (prev);
01708 else
01709
01710 REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED,
01711 cc0_rtx, REG_NOTES (prev));
01712 }
01713 }
01714 #endif
01715
01716 for (note = REG_NOTES (insn); note; note = next)
01717 {
01718 next = XEXP (note, 1);
01719
01720 if (REG_NOTE_KIND (note) != REG_DEAD
01721
01722 || GET_CODE (XEXP (note, 0)) != REG)
01723 continue;
01724
01725 delete_prior_computation (note, insn);
01726 }
01727
01728 delete_related_insns (insn);
01729 }
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739 rtx
01740 delete_related_insns (insn)
01741 rtx insn;
01742 {
01743 int was_code_label = (GET_CODE (insn) == CODE_LABEL);
01744 rtx note;
01745 rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
01746
01747 while (next && INSN_DELETED_P (next))
01748 next = NEXT_INSN (next);
01749
01750
01751 if (INSN_DELETED_P (insn))
01752 return next;
01753
01754 delete_insn (insn);
01755
01756
01757
01758
01759 if (next != 0 && GET_CODE (next) == BARRIER)
01760 delete_insn (next);
01761
01762
01763
01764
01765 if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
01766 {
01767 rtx lab = JUMP_LABEL (insn), lab_next;
01768
01769 if (LABEL_NUSES (lab) == 0)
01770 {
01771
01772
01773
01774 delete_related_insns (lab);
01775
01776
01777
01778
01779
01780 while (next && INSN_DELETED_P (next))
01781 next = NEXT_INSN (next);
01782 return next;
01783 }
01784 else if ((lab_next = next_nonnote_insn (lab)) != NULL
01785 && GET_CODE (lab_next) == JUMP_INSN
01786 && (GET_CODE (PATTERN (lab_next)) == ADDR_VEC
01787 || GET_CODE (PATTERN (lab_next)) == ADDR_DIFF_VEC))
01788 {
01789
01790
01791
01792
01793 delete_related_insns (lab_next);
01794 }
01795 }
01796
01797
01798
01799 if (GET_CODE (insn) == JUMP_INSN
01800 && (GET_CODE (PATTERN (insn)) == ADDR_VEC
01801 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
01802 {
01803 rtx pat = PATTERN (insn);
01804 int i, diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC;
01805 int len = XVECLEN (pat, diff_vec_p);
01806
01807 for (i = 0; i < len; i++)
01808 if (LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0)) == 0)
01809 delete_related_insns (XEXP (XVECEXP (pat, diff_vec_p, i), 0));
01810 while (next && INSN_DELETED_P (next))
01811 next = NEXT_INSN (next);
01812 return next;
01813 }
01814
01815
01816 if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
01817 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
01818 if (REG_NOTE_KIND (note) == REG_LABEL
01819
01820 && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
01821 if (LABEL_NUSES (XEXP (note, 0)) == 0)
01822 delete_related_insns (XEXP (note, 0));
01823
01824 while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE))
01825 prev = PREV_INSN (prev);
01826
01827
01828
01829
01830
01831 if (was_code_label
01832 && NEXT_INSN (insn) != 0
01833 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
01834 && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
01835 || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
01836 next = delete_related_insns (NEXT_INSN (insn));
01837
01838
01839
01840 if (was_code_label && prev && GET_CODE (prev) == BARRIER)
01841 {
01842 RTX_CODE code;
01843 while (next != 0
01844 && (GET_RTX_CLASS (code = GET_CODE (next)) == 'i'
01845 || code == NOTE || code == BARRIER
01846 || (code == CODE_LABEL && INSN_DELETED_P (next))))
01847 {
01848 if (code == NOTE
01849 && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END)
01850 next = NEXT_INSN (next);
01851
01852 else if (code == CODE_LABEL && INSN_DELETED_P (next))
01853 next = NEXT_INSN (next);
01854 else
01855
01856
01857
01858
01859 next = delete_related_insns (next);
01860 }
01861 }
01862
01863 return next;
01864 }
01865
01866
01867
01868
01869 rtx
01870 next_nondeleted_insn (insn)
01871 rtx insn;
01872 {
01873 while (INSN_DELETED_P (insn))
01874 insn = NEXT_INSN (insn);
01875 return insn;
01876 }
01877
01878
01879
01880
01881
01882
01883 void
01884 delete_for_peephole (from, to)
01885 rtx from, to;
01886 {
01887 rtx insn = from;
01888
01889 while (1)
01890 {
01891 rtx next = NEXT_INSN (insn);
01892 rtx prev = PREV_INSN (insn);
01893
01894 if (GET_CODE (insn) != NOTE)
01895 {
01896 INSN_DELETED_P (insn) = 1;
01897
01898
01899
01900
01901 if (prev)
01902 NEXT_INSN (prev) = next;
01903
01904 if (next)
01905 PREV_INSN (next) = prev;
01906 }
01907
01908 if (insn == to)
01909 break;
01910 insn = next;
01911 }
01912
01913
01914
01915
01916
01917 }
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928 void
01929 never_reached_warning (avoided_insn, finish)
01930 rtx avoided_insn, finish;
01931 {
01932 rtx insn;
01933 rtx a_line_note = NULL;
01934 int two_avoided_lines = 0, contains_insn = 0, reached_end = 0;
01935
01936 if (!warn_notreached)
01937 return;
01938
01939
01940
01941
01942 insn = avoided_insn;
01943 while (1)
01944 {
01945 rtx prev = PREV_INSN (insn);
01946 if (prev == NULL_RTX
01947 || GET_CODE (prev) != NOTE)
01948 break;
01949 insn = prev;
01950 }
01951
01952
01953
01954
01955 for (; insn != NULL; insn = NEXT_INSN (insn))
01956 {
01957 if ((finish == NULL && GET_CODE (insn) == CODE_LABEL)
01958 || GET_CODE (insn) == BARRIER)
01959 break;
01960
01961 if (GET_CODE (insn) == NOTE
01962 && NOTE_LINE_NUMBER (insn) >= 0)
01963 {
01964 if (a_line_note == NULL)
01965 a_line_note = insn;
01966 else
01967 two_avoided_lines |= (NOTE_LINE_NUMBER (a_line_note)
01968 != NOTE_LINE_NUMBER (insn));
01969 }
01970 else if (INSN_P (insn))
01971 {
01972 if (reached_end)
01973 break;
01974 contains_insn = 1;
01975 }
01976
01977 if (insn == finish)
01978 reached_end = 1;
01979 }
01980 if (two_avoided_lines && contains_insn)
01981 warning_with_file_and_line (NOTE_SOURCE_FILE (a_line_note),
01982 NOTE_LINE_NUMBER (a_line_note),
01983 "will never be executed");
01984 }
01985
01986
01987
01988
01989 static void
01990 redirect_exp_1 (loc, olabel, nlabel, insn)
01991 rtx *loc;
01992 rtx olabel, nlabel;
01993 rtx insn;
01994 {
01995 rtx x = *loc;
01996 RTX_CODE code = GET_CODE (x);
01997 int i;
01998 const char *fmt;
01999
02000 if (code == LABEL_REF)
02001 {
02002 if (XEXP (x, 0) == olabel)
02003 {
02004 rtx n;
02005 if (nlabel)
02006 n = gen_rtx_LABEL_REF (VOIDmode, nlabel);
02007 else
02008 n = gen_rtx_RETURN (VOIDmode);
02009
02010 validate_change (insn, loc, n, 1);
02011 return;
02012 }
02013 }
02014 else if (code == RETURN && olabel == 0)
02015 {
02016 x = gen_rtx_LABEL_REF (VOIDmode, nlabel);
02017 if (loc == &PATTERN (insn))
02018 x = gen_rtx_SET (VOIDmode, pc_rtx, x);
02019 validate_change (insn, loc, x, 1);
02020 return;
02021 }
02022
02023 if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
02024 && GET_CODE (SET_SRC (x)) == LABEL_REF
02025 && XEXP (SET_SRC (x), 0) == olabel)
02026 {
02027 validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
02028 return;
02029 }
02030
02031 fmt = GET_RTX_FORMAT (code);
02032 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02033 {
02034 if (fmt[i] == 'e')
02035 redirect_exp_1 (&XEXP (x, i), olabel, nlabel, insn);
02036 else if (fmt[i] == 'E')
02037 {
02038 int j;
02039 for (j = 0; j < XVECLEN (x, i); j++)
02040 redirect_exp_1 (&XVECEXP (x, i, j), olabel, nlabel, insn);
02041 }
02042 }
02043 }
02044
02045
02046
02047 static int
02048 redirect_exp (olabel, nlabel, insn)
02049 rtx olabel, nlabel;
02050 rtx insn;
02051 {
02052 rtx *loc;
02053
02054 if (GET_CODE (PATTERN (insn)) == PARALLEL)
02055 loc = &XVECEXP (PATTERN (insn), 0, 0);
02056 else
02057 loc = &PATTERN (insn);
02058
02059 redirect_exp_1 (loc, olabel, nlabel, insn);
02060 if (num_validated_changes () == 0)
02061 return 0;
02062
02063 return apply_change_group ();
02064 }
02065
02066
02067
02068
02069
02070 int
02071 redirect_jump_1 (jump, nlabel)
02072 rtx jump, nlabel;
02073 {
02074 int ochanges = num_validated_changes ();
02075 rtx *loc;
02076
02077 if (GET_CODE (PATTERN (jump)) == PARALLEL)
02078 loc = &XVECEXP (PATTERN (jump), 0, 0);
02079 else
02080 loc = &PATTERN (jump);
02081
02082 redirect_exp_1 (loc, JUMP_LABEL (jump), nlabel, jump);
02083 return num_validated_changes () > ochanges;
02084 }
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096 int
02097 redirect_jump (jump, nlabel, delete_unused)
02098 rtx jump, nlabel;
02099 int delete_unused;
02100 {
02101 rtx olabel = JUMP_LABEL (jump);
02102
02103 if (nlabel == olabel)
02104 return 1;
02105
02106 if (! redirect_exp (olabel, nlabel, jump))
02107 return 0;
02108
02109 JUMP_LABEL (jump) = nlabel;
02110 if (nlabel)
02111 ++LABEL_NUSES (nlabel);
02112
02113
02114
02115 if (olabel && nlabel
02116 && NEXT_INSN (olabel)
02117 && GET_CODE (NEXT_INSN (olabel)) == NOTE
02118 && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END)
02119 emit_note_after (NOTE_INSN_FUNCTION_END, nlabel);
02120
02121 if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused
02122
02123 && INSN_UID (olabel))
02124 delete_related_insns (olabel);
02125
02126 return 1;
02127 }
02128
02129
02130
02131
02132 static void
02133 invert_exp_1 (insn)
02134 rtx insn;
02135 {
02136 RTX_CODE code;
02137 rtx x = pc_set (insn);
02138
02139 if (!x)
02140 abort ();
02141 x = SET_SRC (x);
02142
02143 code = GET_CODE (x);
02144
02145 if (code == IF_THEN_ELSE)
02146 {
02147 rtx comp = XEXP (x, 0);
02148 rtx tem;
02149 enum rtx_code reversed_code;
02150
02151
02152
02153
02154
02155
02156 reversed_code = reversed_comparison_code (comp, insn);
02157
02158 if (reversed_code != UNKNOWN)
02159 {
02160 validate_change (insn, &XEXP (x, 0),
02161 gen_rtx_fmt_ee (reversed_code,
02162 GET_MODE (comp), XEXP (comp, 0),
02163 XEXP (comp, 1)),
02164 1);
02165 return;
02166 }
02167
02168 tem = XEXP (x, 1);
02169 validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
02170 validate_change (insn, &XEXP (x, 2), tem, 1);
02171 }
02172 else
02173 abort ();
02174 }
02175
02176
02177
02178
02179
02180
02181 static int
02182 invert_exp (insn)
02183 rtx insn;
02184 {
02185 invert_exp_1 (insn);
02186 if (num_validated_changes () == 0)
02187 return 0;
02188
02189 return apply_change_group ();
02190 }
02191
02192
02193
02194
02195
02196
02197 int
02198 invert_jump_1 (jump, nlabel)
02199 rtx jump, nlabel;
02200 {
02201 int ochanges;
02202
02203 ochanges = num_validated_changes ();
02204 invert_exp_1 (jump);
02205 if (num_validated_changes () == ochanges)
02206 return 0;
02207
02208 return redirect_jump_1 (jump, nlabel);
02209 }
02210
02211
02212
02213
02214 int
02215 invert_jump (jump, nlabel, delete_unused)
02216 rtx jump, nlabel;
02217 int delete_unused;
02218 {
02219
02220
02221
02222
02223
02224 if (! invert_exp (jump))
02225 return 0;
02226
02227 if (redirect_jump (jump, nlabel, delete_unused))
02228 {
02229 invert_br_probabilities (jump);
02230
02231 return 1;
02232 }
02233
02234 if (! invert_exp (jump))
02235
02236 abort ();
02237
02238 return 0;
02239 }
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255 int
02256 rtx_renumbered_equal_p (x, y)
02257 rtx x, y;
02258 {
02259 int i;
02260 RTX_CODE code = GET_CODE (x);
02261 const char *fmt;
02262
02263 if (x == y)
02264 return 1;
02265
02266 if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
02267 && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
02268 && GET_CODE (SUBREG_REG (y)) == REG)))
02269 {
02270 int reg_x = -1, reg_y = -1;
02271 int byte_x = 0, byte_y = 0;
02272
02273 if (GET_MODE (x) != GET_MODE (y))
02274 return 0;
02275
02276
02277
02278 if (reg_renumber == 0)
02279 return rtx_equal_p (x, y);
02280
02281 if (code == SUBREG)
02282 {
02283 reg_x = REGNO (SUBREG_REG (x));
02284 byte_x = SUBREG_BYTE (x);
02285
02286 if (reg_renumber[reg_x] >= 0)
02287 {
02288 reg_x = subreg_regno_offset (reg_renumber[reg_x],
02289 GET_MODE (SUBREG_REG (x)),
02290 byte_x,
02291 GET_MODE (x));
02292 byte_x = 0;
02293 }
02294 }
02295 else
02296 {
02297 reg_x = REGNO (x);
02298 if (reg_renumber[reg_x] >= 0)
02299 reg_x = reg_renumber[reg_x];
02300 }
02301
02302 if (GET_CODE (y) == SUBREG)
02303 {
02304 reg_y = REGNO (SUBREG_REG (y));
02305 byte_y = SUBREG_BYTE (y);
02306
02307 if (reg_renumber[reg_y] >= 0)
02308 {
02309 reg_y = subreg_regno_offset (reg_renumber[reg_y],
02310 GET_MODE (SUBREG_REG (y)),
02311 byte_y,
02312 GET_MODE (y));
02313 byte_y = 0;
02314 }
02315 }
02316 else
02317 {
02318 reg_y = REGNO (y);
02319 if (reg_renumber[reg_y] >= 0)
02320 reg_y = reg_renumber[reg_y];
02321 }
02322
02323 return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
02324 }
02325
02326
02327
02328 if (code != GET_CODE (y))
02329 return 0;
02330
02331 switch (code)
02332 {
02333 case PC:
02334 case CC0:
02335 case ADDR_VEC:
02336 case ADDR_DIFF_VEC:
02337 return 0;
02338
02339 case CONST_INT:
02340 return INTVAL (x) == INTVAL (y);
02341
02342 case LABEL_REF:
02343
02344 if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
02345 return XEXP (x, 0) == XEXP (y, 0);
02346
02347
02348
02349 return (next_real_insn (XEXP (x, 0))
02350 == next_real_insn (XEXP (y, 0)));
02351
02352 case SYMBOL_REF:
02353 return XSTR (x, 0) == XSTR (y, 0);
02354
02355 case CODE_LABEL:
02356
02357 return 0;
02358
02359 default:
02360 break;
02361 }
02362
02363
02364
02365 if (GET_MODE (x) != GET_MODE (y))
02366 return 0;
02367
02368
02369
02370
02371
02372 if ((code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
02373 && code != PLUS)
02374 return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
02375 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
02376 || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
02377 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 0))));
02378 else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
02379 return (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
02380 && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)));
02381 else if (GET_RTX_CLASS (code) == '1')
02382 return rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0));
02383
02384
02385
02386
02387 fmt = GET_RTX_FORMAT (code);
02388 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02389 {
02390 int j;
02391 switch (fmt[i])
02392 {
02393 case 'w':
02394 if (XWINT (x, i) != XWINT (y, i))
02395 return 0;
02396 break;
02397
02398 case 'i':
02399 if (XINT (x, i) != XINT (y, i))
02400 return 0;
02401 break;
02402
02403 case 't':
02404 if (XTREE (x, i) != XTREE (y, i))
02405 return 0;
02406 break;
02407
02408 case 's':
02409 if (strcmp (XSTR (x, i), XSTR (y, i)))
02410 return 0;
02411 break;
02412
02413 case 'e':
02414 if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
02415 return 0;
02416 break;
02417
02418 case 'u':
02419 if (XEXP (x, i) != XEXP (y, i))
02420 return 0;
02421
02422 case '0':
02423 break;
02424
02425 case 'E':
02426 if (XVECLEN (x, i) != XVECLEN (y, i))
02427 return 0;
02428 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
02429 if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
02430 return 0;
02431 break;
02432
02433 default:
02434 abort ();
02435 }
02436 }
02437 return 1;
02438 }
02439
02440
02441
02442
02443
02444
02445 int
02446 true_regnum (x)
02447 rtx x;
02448 {
02449 if (GET_CODE (x) == REG)
02450 {
02451 if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
02452 return reg_renumber[REGNO (x)];
02453 return REGNO (x);
02454 }
02455 if (GET_CODE (x) == SUBREG)
02456 {
02457 int base = true_regnum (SUBREG_REG (x));
02458 if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
02459 return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
02460 GET_MODE (SUBREG_REG (x)),
02461 SUBREG_BYTE (x), GET_MODE (x));
02462 }
02463 return -1;
02464 }
02465
02466
02467 unsigned int
02468 reg_or_subregno (reg)
02469 rtx reg;
02470 {
02471 if (REG_P (reg))
02472 return REGNO (reg);
02473 if (GET_CODE (reg) == SUBREG)
02474 return REGNO (SUBREG_REG (reg));
02475 abort ();
02476 }