|
|
1.1 ! root 1: /* Optimize jump instructions, for GNU compiler. ! 2: Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: /* This is the jump-optimization pass of the compiler. ! 22: It is run two or three times: once before cse, sometimes once after cse, ! 23: and once after reload (before final). ! 24: ! 25: jump_optimize deletes unreachable code and labels that are not used. ! 26: It also deletes jumps that jump to the following insn, ! 27: and simplifies jumps around unconditional jumps and jumps ! 28: to unconditional jumps. ! 29: ! 30: Each CODE_LABEL has a count of the times it is used ! 31: stored in the LABEL_NUSES internal field, and each JUMP_INSN ! 32: has one label that it refers to stored in the ! 33: JUMP_LABEL internal field. With this we can detect labels that ! 34: become unused because of the deletion of all the jumps that ! 35: formerly used them. The JUMP_LABEL info is sometimes looked ! 36: at by later passes. ! 37: ! 38: Optionally, cross-jumping can be done. Currently it is done ! 39: only the last time (when after reload and before final). ! 40: In fact, the code for cross-jumping now assumes that register ! 41: allocation has been done, since it uses `rtx_renumbered_equal_p'. ! 42: ! 43: Jump optimization is done after cse when cse's constant-propagation ! 44: causes jumps to become unconditional or to be deleted. ! 45: ! 46: Unreachable loops are not detected here, because the labels ! 47: have references and the insns appear reachable from the labels. ! 48: find_basic_blocks in flow.c finds and deletes such loops. ! 49: ! 50: The subroutines delete_insn, redirect_jump, and invert_jump are used ! 51: from other passes as well. */ ! 52: ! 53: #include "config.h" ! 54: #include "rtl.h" ! 55: #include "flags.h" ! 56: #include "hard-reg-set.h" ! 57: #include "regs.h" ! 58: #include "expr.h" ! 59: #include "insn-config.h" ! 60: #include "insn-flags.h" ! 61: #include "real.h" ! 62: ! 63: /* ??? Eventually must record somehow the labels used by jumps ! 64: from nested functions. */ ! 65: /* Pre-record the next or previous real insn for each label? ! 66: No, this pass is very fast anyway. */ ! 67: /* Condense consecutive labels? ! 68: This would make life analysis faster, maybe. */ ! 69: /* Optimize jump y; x: ... y: jumpif... x? ! 70: Don't know if it is worth bothering with. */ ! 71: /* Optimize two cases of conditional jump to conditional jump? ! 72: This can never delete any instruction or make anything dead, ! 73: or even change what is live at any point. ! 74: So perhaps let combiner do it. */ ! 75: ! 76: /* Vector indexed by uid. ! 77: For each CODE_LABEL, index by its uid to get first unconditional jump ! 78: that jumps to the label. ! 79: For each JUMP_INSN, index by its uid to get the next unconditional jump ! 80: that jumps to the same label. ! 81: Element 0 is the start of a chain of all return insns. ! 82: (It is safe to use element 0 because insn uid 0 is not used. */ ! 83: ! 84: static rtx *jump_chain; ! 85: ! 86: /* List of labels referred to from initializers. ! 87: These can never be deleted. */ ! 88: rtx forced_labels; ! 89: ! 90: /* Maximum index in jump_chain. */ ! 91: ! 92: static int max_jump_chain; ! 93: ! 94: /* Set nonzero by jump_optimize if control can fall through ! 95: to the end of the function. */ ! 96: int can_reach_end; ! 97: ! 98: /* Indicates whether death notes are significant in cross jump analysis. ! 99: Normally they are not significant, because of A and B jump to C, ! 100: and R dies in A, it must die in B. But this might not be true after ! 101: stack register conversion, and we must compare death notes in that ! 102: case. */ ! 103: ! 104: static int cross_jump_death_matters = 0; ! 105: ! 106: static int duplicate_loop_exit_test (); ! 107: rtx delete_insn (); ! 108: int redirect_jump (); ! 109: static int redirect_exp (); ! 110: void redirect_tablejump (); ! 111: static int delete_labelref_insn (); ! 112: int invert_jump (); ! 113: static int invert_exp (); ! 114: int condjump_p (); ! 115: int simplejump_p (); ! 116: ! 117: extern rtx gen_jump (); ! 118: ! 119: void squeeze_notes (); ! 120: static void mark_jump_label (); ! 121: void delete_jump (); ! 122: static void delete_from_jump_chain (); ! 123: static int tension_vector_labels (); ! 124: static void find_cross_jump (); ! 125: static void do_cross_jump (); ! 126: static int jump_back_p (); ! 127: ! 128: /* Delete no-op jumps and optimize jumps to jumps ! 129: and jumps around jumps. ! 130: Delete unused labels and unreachable code. ! 131: ! 132: If CROSS_JUMP is 1, detect matching code ! 133: before a jump and its destination and unify them. ! 134: If CROSS_JUMP is 2, do cross-jumping, but pay attention to death notes. ! 135: ! 136: If NOOP_MOVES is nonzero, delete no-op move insns. ! 137: ! 138: If AFTER_REGSCAN is nonzero, then this jump pass is being run immediately ! 139: after regscan, and it is safe to use regno_first_uid and regno_last_uid. ! 140: ! 141: If `optimize' is zero, don't change any code, ! 142: just determine whether control drops off the end of the function. ! 143: This case occurs when we have -W and not -O. ! 144: It works because `delete_insn' checks the value of `optimize' ! 145: and refrains from actually deleting when that is 0. */ ! 146: ! 147: void ! 148: jump_optimize (f, cross_jump, noop_moves, after_regscan) ! 149: rtx f; ! 150: int cross_jump; ! 151: int noop_moves; ! 152: int after_regscan; ! 153: { ! 154: register rtx insn; ! 155: int changed; ! 156: int first = 1; ! 157: int max_uid = 0; ! 158: rtx last_insn; ! 159: ! 160: cross_jump_death_matters = (cross_jump == 2); ! 161: ! 162: /* Initialize LABEL_NUSES and JUMP_LABEL fields. */ ! 163: ! 164: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 165: { ! 166: if (GET_CODE (insn) == CODE_LABEL) ! 167: LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); ! 168: else if (GET_CODE (insn) == JUMP_INSN) ! 169: JUMP_LABEL (insn) = 0; ! 170: if (INSN_UID (insn) > max_uid) ! 171: max_uid = INSN_UID (insn); ! 172: } ! 173: ! 174: max_uid++; ! 175: ! 176: /* Delete insns following barriers, up to next label. */ ! 177: ! 178: for (insn = f; insn;) ! 179: { ! 180: if (GET_CODE (insn) == BARRIER) ! 181: { ! 182: insn = NEXT_INSN (insn); ! 183: while (insn != 0 && GET_CODE (insn) != CODE_LABEL) ! 184: { ! 185: if (GET_CODE (insn) == NOTE ! 186: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END) ! 187: insn = NEXT_INSN (insn); ! 188: else ! 189: insn = delete_insn (insn); ! 190: } ! 191: /* INSN is now the code_label. */ ! 192: } ! 193: else ! 194: insn = NEXT_INSN (insn); ! 195: } ! 196: ! 197: /* Leave some extra room for labels and duplicate exit test insns ! 198: we make. */ ! 199: max_jump_chain = max_uid * 14 / 10; ! 200: jump_chain = (rtx *) alloca (max_jump_chain * sizeof (rtx)); ! 201: bzero (jump_chain, max_jump_chain * sizeof (rtx)); ! 202: ! 203: /* Mark the label each jump jumps to. ! 204: Combine consecutive labels, and count uses of labels. ! 205: ! 206: For each label, make a chain (using `jump_chain') ! 207: of all the *unconditional* jumps that jump to it; ! 208: also make a chain of all returns. */ ! 209: ! 210: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 211: if ((GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == INSN ! 212: || GET_CODE (insn) == CALL_INSN) ! 213: && ! INSN_DELETED_P (insn)) ! 214: { ! 215: mark_jump_label (PATTERN (insn), insn, cross_jump); ! 216: if (GET_CODE (insn) == JUMP_INSN) ! 217: { ! 218: if (JUMP_LABEL (insn) != 0 && simplejump_p (insn)) ! 219: { ! 220: jump_chain[INSN_UID (insn)] ! 221: = jump_chain[INSN_UID (JUMP_LABEL (insn))]; ! 222: jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn; ! 223: } ! 224: if (GET_CODE (PATTERN (insn)) == RETURN) ! 225: { ! 226: jump_chain[INSN_UID (insn)] = jump_chain[0]; ! 227: jump_chain[0] = insn; ! 228: } ! 229: } ! 230: } ! 231: ! 232: /* Keep track of labels used from static data; ! 233: they cannot ever be deleted. */ ! 234: ! 235: for (insn = forced_labels; insn; insn = XEXP (insn, 1)) ! 236: LABEL_NUSES (XEXP (insn, 0))++; ! 237: ! 238: /* Delete all labels already not referenced. ! 239: Also find the last insn. */ ! 240: ! 241: last_insn = 0; ! 242: for (insn = f; insn; ) ! 243: { ! 244: if (GET_CODE (insn) == CODE_LABEL && LABEL_NUSES (insn) == 0) ! 245: insn = delete_insn (insn); ! 246: else ! 247: { ! 248: last_insn = insn; ! 249: insn = NEXT_INSN (insn); ! 250: } ! 251: } ! 252: ! 253: if (!optimize) ! 254: { ! 255: /* See if there is still a NOTE_INSN_FUNCTION_END in this function. ! 256: If so record that this function can drop off the end. */ ! 257: ! 258: insn = last_insn; ! 259: { ! 260: int n_labels = 1; ! 261: while (insn ! 262: /* One label can follow the end-note: the return label. */ ! 263: && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0) ! 264: /* Ordinary insns can follow it if returning a structure. */ ! 265: || GET_CODE (insn) == INSN ! 266: /* If machine uses explicit RETURN insns, no epilogue, ! 267: then one of them follows the note. */ ! 268: || (GET_CODE (insn) == JUMP_INSN ! 269: && GET_CODE (PATTERN (insn)) == RETURN) ! 270: /* Other kinds of notes can follow also. */ ! 271: || (GET_CODE (insn) == NOTE ! 272: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END))) ! 273: insn = PREV_INSN (insn); ! 274: } ! 275: ! 276: /* Report if control can fall through at the end of the function. */ ! 277: if (insn && GET_CODE (insn) == NOTE ! 278: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END ! 279: && ! INSN_DELETED_P (insn)) ! 280: can_reach_end = 1; ! 281: ! 282: /* Zero the "deleted" flag of all the "deleted" insns. */ ! 283: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 284: INSN_DELETED_P (insn) = 0; ! 285: return; ! 286: } ! 287: ! 288: #ifdef HAVE_return ! 289: if (HAVE_return) ! 290: { ! 291: /* If we fall through to the epilogue, see if we can insert a RETURN insn ! 292: in front of it. If the machine allows it at this point (we might be ! 293: after reload for a leaf routine), it will improve optimization for it ! 294: to be there. */ ! 295: insn = get_last_insn (); ! 296: while (insn && GET_CODE (insn) == NOTE) ! 297: insn = PREV_INSN (insn); ! 298: ! 299: if (insn && GET_CODE (insn) != BARRIER) ! 300: { ! 301: emit_jump_insn (gen_return ()); ! 302: emit_barrier (); ! 303: } ! 304: } ! 305: #endif ! 306: ! 307: if (noop_moves) ! 308: for (insn = f; insn; ) ! 309: { ! 310: register rtx next = NEXT_INSN (insn); ! 311: ! 312: if (GET_CODE (insn) == INSN) ! 313: { ! 314: register rtx body = PATTERN (insn); ! 315: ! 316: /* Combine stack_adjusts with following push_insns. */ ! 317: #ifdef PUSH_ROUNDING ! 318: if (GET_CODE (body) == SET ! 319: && SET_DEST (body) == stack_pointer_rtx ! 320: && GET_CODE (SET_SRC (body)) == PLUS ! 321: && XEXP (SET_SRC (body), 0) == stack_pointer_rtx ! 322: && GET_CODE (XEXP (SET_SRC (body), 1)) == CONST_INT ! 323: && INTVAL (XEXP (SET_SRC (body), 1)) > 0) ! 324: { ! 325: rtx p; ! 326: rtx stack_adjust_insn = insn; ! 327: int stack_adjust_amount = INTVAL (XEXP (SET_SRC (body), 1)); ! 328: int total_pushed = 0; ! 329: int pushes = 0; ! 330: ! 331: /* Find all successive push insns. */ ! 332: p = insn; ! 333: /* Don't convert more than three pushes; ! 334: that starts adding too many displaced addresses ! 335: and the whole thing starts becoming a losing ! 336: proposition. */ ! 337: while (pushes < 3) ! 338: { ! 339: rtx pbody, dest; ! 340: p = next_nonnote_insn (p); ! 341: if (p == 0 || GET_CODE (p) != INSN) ! 342: break; ! 343: pbody = PATTERN (p); ! 344: if (GET_CODE (pbody) != SET) ! 345: break; ! 346: dest = SET_DEST (pbody); ! 347: /* Allow a no-op move between the adjust and the push. */ ! 348: if (GET_CODE (dest) == REG ! 349: && GET_CODE (SET_SRC (pbody)) == REG ! 350: && REGNO (dest) == REGNO (SET_SRC (pbody))) ! 351: continue; ! 352: if (! (GET_CODE (dest) == MEM ! 353: && GET_CODE (XEXP (dest, 0)) == POST_INC ! 354: && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)) ! 355: break; ! 356: pushes++; ! 357: if (total_pushed + GET_MODE_SIZE (SET_DEST (pbody)) ! 358: > stack_adjust_amount) ! 359: break; ! 360: total_pushed += GET_MODE_SIZE (SET_DEST (pbody)); ! 361: } ! 362: ! 363: /* Discard the amount pushed from the stack adjust; ! 364: maybe eliminate it entirely. */ ! 365: if (total_pushed >= stack_adjust_amount) ! 366: { ! 367: delete_insn (stack_adjust_insn); ! 368: total_pushed = stack_adjust_amount; ! 369: } ! 370: else ! 371: XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1) ! 372: = gen_rtx (CONST_INT, VOIDmode, ! 373: stack_adjust_amount - total_pushed); ! 374: ! 375: /* Change the appropriate push insns to ordinary stores. */ ! 376: p = insn; ! 377: while (total_pushed > 0) ! 378: { ! 379: rtx pbody, dest; ! 380: p = next_nonnote_insn (p); ! 381: if (GET_CODE (p) != INSN) ! 382: break; ! 383: pbody = PATTERN (p); ! 384: if (GET_CODE (pbody) == SET) ! 385: break; ! 386: dest = SET_DEST (pbody); ! 387: if (! (GET_CODE (dest) == MEM ! 388: && GET_CODE (XEXP (dest, 0)) == POST_INC ! 389: && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)) ! 390: break; ! 391: total_pushed -= GET_MODE_SIZE (SET_DEST (pbody)); ! 392: /* If this push doesn't fully fit in the space ! 393: of the stack adjust that we deleted, ! 394: make another stack adjust here for what we ! 395: didn't use up. There should be peepholes ! 396: to recognize the resulting sequence of insns. */ ! 397: if (total_pushed < 0) ! 398: { ! 399: emit_insn_before (gen_add2_insn (stack_pointer_rtx, ! 400: gen_rtx (CONST_INT, VOIDmode, - total_pushed)), ! 401: p); ! 402: break; ! 403: } ! 404: XEXP (dest, 0) ! 405: = plus_constant (stack_pointer_rtx, total_pushed); ! 406: } ! 407: } ! 408: #endif ! 409: ! 410: /* Detect and delete no-op move instructions ! 411: resulting from not allocating a parameter in a register. */ ! 412: ! 413: if (GET_CODE (body) == SET ! 414: && (SET_DEST (body) == SET_SRC (body) ! 415: || (GET_CODE (SET_DEST (body)) == MEM ! 416: && GET_CODE (SET_SRC (body)) == MEM ! 417: && rtx_equal_p (SET_SRC (body), SET_DEST (body)))) ! 418: && ! (GET_CODE (SET_DEST (body)) == MEM ! 419: && MEM_VOLATILE_P (SET_DEST (body))) ! 420: && ! (GET_CODE (SET_SRC (body)) == MEM ! 421: && MEM_VOLATILE_P (SET_SRC (body)))) ! 422: delete_insn (insn); ! 423: ! 424: /* Detect and ignore no-op move instructions ! 425: resulting from smart or fortuitous register allocation. */ ! 426: ! 427: else if (GET_CODE (body) == SET) ! 428: { ! 429: int sreg = true_regnum (SET_SRC (body)); ! 430: int dreg = true_regnum (SET_DEST (body)); ! 431: ! 432: if (sreg == dreg && sreg >= 0) ! 433: delete_insn (insn); ! 434: else if (sreg >= 0 && dreg >= 0) ! 435: { ! 436: rtx trial; ! 437: rtx tem = find_equiv_reg (0, insn, 0, ! 438: sreg, 0, dreg, ! 439: GET_MODE (SET_SRC (body))); ! 440: ! 441: #ifdef PRESERVE_DEATH_INFO_REGNO_P ! 442: /* Deleting insn could lose a death-note for SREG or DREG ! 443: so don't do it if final needs accurate death-notes. */ ! 444: if (! PRESERVE_DEATH_INFO_REGNO_P (sreg) ! 445: && ! PRESERVE_DEATH_INFO_REGNO_P (dreg)) ! 446: #endif ! 447: { ! 448: /* DREG may have been the target of a REG_DEAD note in ! 449: the insn which makes INSN redundant. If so, reorg ! 450: would still think it is dead. So search for such a ! 451: note and delete it if we find it. */ ! 452: for (trial = prev_nonnote_insn (insn); ! 453: trial && GET_CODE (trial) != CODE_LABEL; ! 454: trial = prev_nonnote_insn (trial)) ! 455: if (find_regno_note (trial, REG_DEAD, dreg)) ! 456: { ! 457: remove_death (dreg, trial); ! 458: break; ! 459: } ! 460: ! 461: if (tem != 0 ! 462: && GET_MODE (tem) == GET_MODE (SET_DEST (body))) ! 463: delete_insn (insn); ! 464: } ! 465: } ! 466: else if (dreg >= 0 && CONSTANT_P (SET_SRC (body)) ! 467: && find_equiv_reg (SET_SRC (body), insn, 0, dreg, 0, ! 468: 0, GET_MODE (SET_DEST (body)))) ! 469: { ! 470: /* This handles the case where we have two consecutive ! 471: assignments of the same constant to pseudos that didn't ! 472: get a hard reg. Each SET from the constant will be ! 473: converted into a SET of the spill register and an ! 474: output reload will be made following it. This produces ! 475: two loads of the same constant into the same spill ! 476: register. */ ! 477: ! 478: rtx in_insn = insn; ! 479: ! 480: /* Look back for a death note for the first reg. ! 481: If there is one, it is no longer accurate. */ ! 482: while (in_insn && GET_CODE (in_insn) != CODE_LABEL) ! 483: { ! 484: if ((GET_CODE (in_insn) == INSN ! 485: || GET_CODE (in_insn) == JUMP_INSN) ! 486: && find_regno_note (in_insn, REG_DEAD, dreg)) ! 487: { ! 488: remove_death (dreg, in_insn); ! 489: break; ! 490: } ! 491: in_insn = PREV_INSN (in_insn); ! 492: } ! 493: ! 494: /* Delete the second load of the value. */ ! 495: delete_insn (insn); ! 496: } ! 497: } ! 498: else if (GET_CODE (body) == PARALLEL) ! 499: { ! 500: /* If each part is a set between two identical registers or ! 501: a USE or CLOBBER, delete the insn. */ ! 502: int i, sreg, dreg; ! 503: rtx tem; ! 504: ! 505: for (i = XVECLEN (body, 0) - 1; i >= 0; i--) ! 506: { ! 507: tem = XVECEXP (body, 0, i); ! 508: if (GET_CODE (tem) == USE || GET_CODE (tem) == CLOBBER) ! 509: continue; ! 510: ! 511: if (GET_CODE (tem) != SET ! 512: || (sreg = true_regnum (SET_SRC (tem))) < 0 ! 513: || (dreg = true_regnum (SET_DEST (tem))) < 0 ! 514: || dreg != sreg) ! 515: break; ! 516: } ! 517: ! 518: if (i < 0) ! 519: delete_insn (insn); ! 520: } ! 521: #if !BYTES_BIG_ENDIAN /* Not worth the hair to detect this ! 522: in the big-endian case. */ ! 523: /* Also delete insns to store bit fields if they are no-ops. */ ! 524: else if (GET_CODE (body) == SET ! 525: && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT ! 526: && XEXP (SET_DEST (body), 2) == const0_rtx ! 527: && XEXP (SET_DEST (body), 0) == SET_SRC (body) ! 528: && ! (GET_CODE (SET_SRC (body)) == MEM ! 529: && MEM_VOLATILE_P (SET_SRC (body)))) ! 530: delete_insn (insn); ! 531: #endif /* not BYTES_BIG_ENDIAN */ ! 532: } ! 533: insn = next; ! 534: } ! 535: ! 536: /* Now iterate optimizing jumps until nothing changes over one pass. */ ! 537: changed = 1; ! 538: while (changed) ! 539: { ! 540: register rtx next; ! 541: changed = 0; ! 542: ! 543: for (insn = f; insn; insn = next) ! 544: { ! 545: rtx reallabelprev; ! 546: rtx temp, temp1, temp2, temp3, temp4, temp5; ! 547: rtx nlabel; ! 548: int this_is_simplejump, this_is_condjump; ! 549: #if 0 ! 550: /* If NOT the first iteration, if this is the last jump pass ! 551: (just before final), do the special peephole optimizations. ! 552: Avoiding the first iteration gives ordinary jump opts ! 553: a chance to work before peephole opts. */ ! 554: ! 555: if (reload_completed && !first && !flag_no_peephole) ! 556: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) ! 557: peephole (insn); ! 558: #endif ! 559: ! 560: /* That could have deleted some insns after INSN, so check now ! 561: what the following insn is. */ ! 562: ! 563: next = NEXT_INSN (insn); ! 564: ! 565: /* See if this is a NOTE_INSN_LOOP_BEG followed by an unconditional ! 566: jump. Try to optimize by duplicating the loop exit test if so. ! 567: This is only safe immediately after regscan, because it uses ! 568: the values of regno_first_uid and regno_last_uid. */ ! 569: if (after_regscan && GET_CODE (insn) == NOTE ! 570: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG ! 571: && (temp1 = next_nonnote_insn (insn)) != 0 ! 572: && simplejump_p (temp1)) ! 573: { ! 574: temp = PREV_INSN (insn); ! 575: if (duplicate_loop_exit_test (insn)) ! 576: { ! 577: changed = 1; ! 578: next = NEXT_INSN (temp); ! 579: continue; ! 580: } ! 581: } ! 582: ! 583: if (GET_CODE (insn) != JUMP_INSN) ! 584: continue; ! 585: ! 586: this_is_simplejump = simplejump_p (insn); ! 587: this_is_condjump = condjump_p (insn); ! 588: ! 589: /* Tension the labels in dispatch tables. */ ! 590: ! 591: if (GET_CODE (PATTERN (insn)) == ADDR_VEC) ! 592: changed |= tension_vector_labels (PATTERN (insn), 0); ! 593: if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) ! 594: changed |= tension_vector_labels (PATTERN (insn), 1); ! 595: ! 596: /* If a dispatch table always goes to the same place, ! 597: get rid of it and replace the insn that uses it. */ ! 598: ! 599: if (GET_CODE (PATTERN (insn)) == ADDR_VEC ! 600: || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) ! 601: { ! 602: int i; ! 603: rtx pat = PATTERN (insn); ! 604: int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC; ! 605: int len = XVECLEN (pat, diff_vec_p); ! 606: rtx dispatch = prev_real_insn (insn); ! 607: ! 608: for (i = 0; i < len; i++) ! 609: if (XEXP (XVECEXP (pat, diff_vec_p, i), 0) ! 610: != XEXP (XVECEXP (pat, diff_vec_p, 0), 0)) ! 611: break; ! 612: if (i == len ! 613: && GET_CODE (dispatch) == JUMP_INSN ! 614: && JUMP_LABEL (dispatch) != 0 ! 615: /* Don't mess with a casesi insn. */ ! 616: && !(GET_CODE (PATTERN (dispatch)) == SET ! 617: && (GET_CODE (SET_SRC (PATTERN (dispatch))) ! 618: == IF_THEN_ELSE)) ! 619: && next_real_insn (JUMP_LABEL (dispatch)) == insn) ! 620: { ! 621: redirect_tablejump (dispatch, ! 622: XEXP (XVECEXP (pat, diff_vec_p, 0), 0)); ! 623: changed = 1; ! 624: } ! 625: } ! 626: ! 627: reallabelprev = prev_active_insn (JUMP_LABEL (insn)); ! 628: ! 629: /* If a jump references the end of the function, try to turn ! 630: it into a RETURN insn, possibly a conditional one. */ ! 631: if (JUMP_LABEL (insn) ! 632: && next_active_insn (JUMP_LABEL (insn)) == 0) ! 633: changed |= redirect_jump (insn, 0); ! 634: ! 635: /* Detect jump to following insn. */ ! 636: if (reallabelprev == insn && condjump_p (insn)) ! 637: { ! 638: delete_jump (insn); ! 639: changed = 1; ! 640: continue; ! 641: } ! 642: ! 643: /* If we have an unconditional jump preceeded by a USE, try to put ! 644: the USE before the target and jump there. This simplifies many ! 645: of the optimizations below since we don't have to worry about ! 646: dealing with these USE insns. We only do this if the label ! 647: being branch to already has the identical USE or if code ! 648: never falls through to that label. */ ! 649: ! 650: if (this_is_simplejump ! 651: && (temp = prev_nonnote_insn (insn)) != 0 ! 652: && GET_CODE (temp) == INSN && GET_CODE (PATTERN (temp)) == USE ! 653: && (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0 ! 654: && (GET_CODE (temp1) == BARRIER ! 655: || (GET_CODE (temp1) == INSN ! 656: && rtx_equal_p (PATTERN (temp), PATTERN (temp1))))) ! 657: { ! 658: if (GET_CODE (temp1) == BARRIER) ! 659: { ! 660: reorder_insns (temp, temp, temp1); ! 661: temp1 = NEXT_INSN (temp1); ! 662: } ! 663: else ! 664: delete_insn (temp); ! 665: ! 666: redirect_jump (insn, get_label_before (temp1)); ! 667: reallabelprev = prev_real_insn (temp1); ! 668: changed = 1; ! 669: } ! 670: ! 671: /* Simplify if (...) x = a; else x = b; by converting it ! 672: to x = b; if (...) x = a; ! 673: if B is sufficiently simple, the test doesn't involve X, ! 674: and nothing in the test modifies B or X. ! 675: ! 676: If we have small register classes, we also can't do this if X ! 677: is a hard register. ! 678: ! 679: If the "x = b;" insn has any REG_NOTES, we don't do this because ! 680: of the possibility that we are running after CSE and there is a ! 681: REG_EQUAL note that is only valid if the branch has already been ! 682: taken. If we move the insn with the REG_EQUAL note, we may ! 683: fold the comparison to always be false in a later CSE pass. ! 684: (We could also delete the REG_NOTES when moving the insn, but it ! 685: seems simpler to not move it.) An exception is that we can move ! 686: the insn if the only note is a REG_EQUAL or REG_EQUIV whose ! 687: value is the same as "b". ! 688: ! 689: INSN is the branch over the `else' part. ! 690: ! 691: We set: ! 692: ! 693: TEMP to the jump insn preceeding "x = a;" ! 694: TEMP1 to X ! 695: TEMP2 to the insn that sets "x = b;" ! 696: TEMP3 to the insn that sets "x = a;" */ ! 697: ! 698: if (this_is_simplejump ! 699: && (temp3 = prev_active_insn (insn)) != 0 ! 700: && GET_CODE (temp3) == INSN ! 701: && GET_CODE (PATTERN (temp3)) == SET ! 702: && GET_CODE (temp1 = SET_DEST (PATTERN (temp3))) == REG ! 703: #ifdef SMALL_REGISTER_CLASSES ! 704: && REGNO (temp1) >= FIRST_PSEUDO_REGISTER ! 705: #endif ! 706: && (temp2 = next_active_insn (insn)) != 0 ! 707: && GET_CODE (temp2) == INSN ! 708: && GET_CODE (PATTERN (temp2)) == SET ! 709: && rtx_equal_p (SET_DEST (PATTERN (temp2)), temp1) ! 710: && (GET_CODE (SET_SRC (PATTERN (temp2))) == REG ! 711: || CONSTANT_P (SET_SRC (PATTERN (temp2)))) ! 712: && (REG_NOTES (temp2) == 0 ! 713: || ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL ! 714: || REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUIV) ! 715: && XEXP (REG_NOTES (temp2), 1) == 0 ! 716: && rtx_equal_p (XEXP (REG_NOTES (temp2), 0), ! 717: SET_SRC (PATTERN (temp2))))) ! 718: && (temp = prev_active_insn (temp3)) != 0 ! 719: && condjump_p (temp) && ! simplejump_p (temp) ! 720: /* TEMP must skip over the "x = a;" insn */ ! 721: && prev_real_insn (JUMP_LABEL (temp)) == insn ! 722: && no_labels_between_p (insn, JUMP_LABEL (temp)) ! 723: /* There must be no other entries to the "x = b;" insn. */ ! 724: && no_labels_between_p (JUMP_LABEL (temp), temp2) ! 725: /* INSN must either branch to the insn after TEMP2 or the insn ! 726: after TEMP2 must branch to the same place as INSN. */ ! 727: && (reallabelprev == temp2 ! 728: || ((temp4 = next_active_insn (temp2)) != 0 ! 729: && simplejump_p (temp4) ! 730: && JUMP_LABEL (temp4) == JUMP_LABEL (insn)))) ! 731: { ! 732: /* The test expression, X, may be a complicated test with ! 733: multiple branches. See if we can find all the uses of ! 734: the label that TEMP branches to without hitting a CALL_INSN ! 735: or a jump to somewhere else. */ ! 736: rtx target = JUMP_LABEL (temp); ! 737: int nuses = LABEL_NUSES (target); ! 738: rtx p, q; ! 739: ! 740: /* Set P to the first jump insn that goes around "x = a;". */ ! 741: for (p = temp; nuses && p; p = prev_nonnote_insn (p)) ! 742: { ! 743: if (GET_CODE (p) == JUMP_INSN) ! 744: { ! 745: if (condjump_p (p) && ! simplejump_p (p) ! 746: && JUMP_LABEL (p) == target) ! 747: { ! 748: nuses--; ! 749: if (nuses == 0) ! 750: break; ! 751: } ! 752: else ! 753: break; ! 754: } ! 755: else if (GET_CODE (p) == CALL_INSN) ! 756: break; ! 757: } ! 758: ! 759: #ifdef HAVE_cc0 ! 760: /* We cannot insert anything between a set of cc and its use ! 761: so if P uses cc0, we must back up to the previous insn. */ ! 762: q = prev_nonnote_insn (p); ! 763: if (q && GET_RTX_CLASS (GET_CODE (q)) == 'i' ! 764: && sets_cc0_p (PATTERN (q))) ! 765: p = q; ! 766: #endif ! 767: ! 768: if (p) ! 769: p = PREV_INSN (p); ! 770: ! 771: /* If we found all the uses and there was no data conflict, we ! 772: can move the assignment unless we can branch into the middle ! 773: from somewhere. */ ! 774: if (nuses == 0 && p ! 775: && no_labels_between_p (p, insn) ! 776: && ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3)) ! 777: && ! reg_set_between_p (temp1, p, temp3) ! 778: && (GET_CODE (SET_SRC (PATTERN (temp2))) == CONST_INT ! 779: || ! reg_set_between_p (SET_SRC (PATTERN (temp2)), ! 780: p, temp2))) ! 781: { ! 782: reorder_insns_with_line_notes (temp2, temp2, p); ! 783: ! 784: /* Set NEXT to an insn that we know won't go away. */ ! 785: next = next_active_insn (insn); ! 786: ! 787: /* Delete the jump around the set. Note that we must do ! 788: this before we redirect the test jumps so that it won't ! 789: delete the code immediately following the assignment ! 790: we moved (which might be a jump). */ ! 791: ! 792: delete_insn (insn); ! 793: ! 794: /* We either have two consecutive labels or a jump to ! 795: a jump, so adjust all the JUMP_INSNs to branch to where ! 796: INSN branches to. */ ! 797: for (p = NEXT_INSN (p); p != next; p = NEXT_INSN (p)) ! 798: if (GET_CODE (p) == JUMP_INSN) ! 799: redirect_jump (p, target); ! 800: ! 801: changed = 1; ! 802: continue; ! 803: } ! 804: } ! 805: ! 806: /* If we have x = a; if (...) x = b; ! 807: and either A or B is zero, or if we have if (...) x = 0; ! 808: and jumps are expensive, try to use a store-flag insn to ! 809: avoid the jump. (If the jump would be faster, the machine ! 810: should not have defined the scc insns!). These cases are often ! 811: made by the previous optimization. ! 812: ! 813: INSN here is the jump around the store. We set: ! 814: ! 815: TEMP to the "x = b;" insn. ! 816: TEMP1 to X. ! 817: TEMP2 to B (const0_rtx in the second case). ! 818: TEMP3 to A (X in the second case). ! 819: TEMP4 to the condition being tested. ! 820: TEMP5 to the earliest insn used to find the condition. */ ! 821: ! 822: if (/* We can't do this after reload has completed. */ ! 823: ! reload_completed ! 824: && this_is_condjump && ! this_is_simplejump ! 825: /* Set TEMP to the "x = b;" insn. */ ! 826: && (temp = next_nonnote_insn (insn)) != 0 ! 827: && GET_CODE (temp) == INSN ! 828: && GET_CODE (PATTERN (temp)) == SET ! 829: && GET_CODE (temp1 = SET_DEST (PATTERN (temp))) == REG ! 830: #ifdef SMALL_REGISTER_CLASSES ! 831: && REGNO (temp1) >= FIRST_PSEUDO_REGISTER ! 832: #endif ! 833: && GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT ! 834: && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG ! 835: || GET_CODE (temp2) == CONST_INT) ! 836: /* Allow either form, but prefer the former if both apply. */ ! 837: && (((temp3 = reg_set_last (temp1, insn)) != 0 ! 838: && ((GET_CODE (temp3) == REG ! 839: #ifdef SMALL_REGISTER_CLASSES ! 840: && REGNO (temp3) >= FIRST_PSEUDO_REGISTER ! 841: #endif ! 842: ) ! 843: || GET_CODE (temp3) == CONST_INT)) ! 844: /* Make the latter case look like x = x; if (...) x = 0; */ ! 845: || ((temp3 = temp1, BRANCH_COST > 1) ! 846: && temp2 == const0_rtx)) ! 847: /* INSN must either branch to the insn after TEMP or the insn ! 848: after TEMP must branch to the same place as INSN. */ ! 849: && (reallabelprev == temp ! 850: || ((temp4 = next_active_insn (temp)) != 0 ! 851: && simplejump_p (temp4) ! 852: && JUMP_LABEL (temp4) == JUMP_LABEL (insn))) ! 853: && (temp4 = get_condition (insn, &temp5)) != 0 ! 854: ! 855: /* If B is zero, OK; if A is zero, can only do this if we ! 856: can reverse the condition. */ ! 857: && (temp2 == const0_rtx ! 858: || (temp3 == const0_rtx ! 859: && (can_reverse_comparison_p (temp4, insn))))) ! 860: { ! 861: enum rtx_code code = GET_CODE (temp4); ! 862: rtx yes = temp3, var = temp1; ! 863: int normalizep; ! 864: rtx target; ! 865: ! 866: /* If necessary, reverse the condition. */ ! 867: if (temp3 == const0_rtx) ! 868: code = reverse_condition (code), yes = temp2; ! 869: ! 870: /* See if we can do this with a store-flag insn. */ ! 871: start_sequence (); ! 872: ! 873: /* If YES is the constant 1, it is best to just compute ! 874: the result directly. If YES is constant and STORE_FLAG_VALUE ! 875: includes all of its bits, it is best to compute the flag ! 876: value unnormalized and `and' it with YES. Otherwise, ! 877: normalize to -1 and `and' with YES. */ ! 878: normalizep = (yes == const1_rtx ? 1 ! 879: : (GET_CODE (yes) == CONST_INT ! 880: && (INTVAL (yes) & ~ STORE_FLAG_VALUE) == 0) ? 0 ! 881: : -1); ! 882: ! 883: /* We will be putting the store-flag insn immediately in ! 884: front of the comparison that was originally being done, ! 885: so we know all the variables in TEMP4 will be valid. ! 886: However, this might be in front of the assignment of ! 887: A to VAR. If it is, it would clobber the store-flag ! 888: we will be emitting. ! 889: ! 890: Therefore, emit into a temporary which will be copied to ! 891: VAR immediately after TEMP. */ ! 892: ! 893: target = emit_store_flag (gen_reg_rtx (GET_MODE (var)), code, ! 894: XEXP (temp4, 0), XEXP (temp4, 1), ! 895: VOIDmode, ! 896: (code == LTU || code == LEU ! 897: || code == GEU || code == GTU), ! 898: normalizep); ! 899: if (target) ! 900: { ! 901: rtx seq; ! 902: ! 903: if (normalizep != 1) ! 904: target = expand_and (yes, target, ! 905: (GET_CODE (target) == REG ! 906: ? target : 0)); ! 907: seq = gen_sequence (); ! 908: end_sequence (); ! 909: emit_insn_before (seq, temp5); ! 910: emit_insn_after (gen_move_insn (var, target), insn); ! 911: delete_insn (temp); ! 912: next = NEXT_INSN (insn); ! 913: #ifdef HAVE_cc0 ! 914: delete_insn (prev_nonnote_insn (insn)); ! 915: #endif ! 916: delete_insn (insn); ! 917: changed = 1; ! 918: continue; ! 919: } ! 920: else ! 921: end_sequence (); ! 922: } ! 923: ! 924: /* If branches are expensive, convert ! 925: if (foo) bar++; to bar += (foo != 0); ! 926: and similarly for "bar--;" ! 927: ! 928: INSN is the conditional branch around the arithmetic. We set: ! 929: ! 930: TEMP is the arithmetic insn. ! 931: TEMP1 is the SET doing the arthmetic. ! 932: TEMP2 is the operand being incremented or decremented. ! 933: TEMP3 to the condition being tested. ! 934: TEMP4 to the earliest insn used to find the condition. */ ! 935: ! 936: if (BRANCH_COST >= 2 ! 937: && ! reload_completed ! 938: && this_is_condjump && ! this_is_simplejump ! 939: && (temp = next_nonnote_insn (insn)) != 0 ! 940: && (temp1 = single_set (temp)) != 0 ! 941: && (temp2 = SET_DEST (temp1), ! 942: GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT) ! 943: && GET_CODE (SET_SRC (temp1)) == PLUS ! 944: && (XEXP (SET_SRC (temp1), 1) == const1_rtx ! 945: || XEXP (SET_SRC (temp1), 1) == constm1_rtx) ! 946: && rtx_equal_p (temp2, XEXP (SET_SRC (temp1), 0)) ! 947: /* INSN must either branch to the insn after TEMP or the insn ! 948: after TEMP must branch to the same place as INSN. */ ! 949: && (reallabelprev == temp ! 950: || ((temp3 = next_active_insn (temp)) != 0 ! 951: && simplejump_p (temp3) ! 952: && JUMP_LABEL (temp3) == JUMP_LABEL (insn))) ! 953: && (temp3 = get_condition (insn, &temp4)) != 0 ! 954: && can_reverse_comparison_p (temp3, insn)) ! 955: { ! 956: rtx target, seq; ! 957: enum rtx_code code = reverse_condition (GET_CODE (temp3)); ! 958: ! 959: start_sequence (); ! 960: ! 961: target = emit_store_flag (gen_reg_rtx (GET_MODE (temp2)), code, ! 962: XEXP (temp3, 0), XEXP (temp3, 1), ! 963: VOIDmode, ! 964: (code == LTU || code == LEU ! 965: || code == GTU || code == GEU), 1); ! 966: ! 967: /* If we can do the store-flag, do the addition or ! 968: subtraction. */ ! 969: ! 970: if (target) ! 971: target = expand_binop (GET_MODE (temp2), ! 972: (XEXP (SET_SRC (temp1), 1) == const1_rtx ! 973: ? add_optab : sub_optab), ! 974: temp2, target, temp2, OPTAB_WIDEN); ! 975: ! 976: if (target != 0) ! 977: { ! 978: /* Put the result back in temp2 in case it isn't already. ! 979: Then replace the jump, possible a CC0-setting insn in ! 980: front of the jump, and TEMP, with the sequence we have ! 981: made. */ ! 982: ! 983: if (target != temp2) ! 984: emit_move_insn (temp2, target); ! 985: ! 986: seq = get_insns (); ! 987: end_sequence (); ! 988: ! 989: emit_insns_before (seq, temp4); ! 990: delete_insn (temp); ! 991: next = NEXT_INSN (insn); ! 992: #ifdef HAVE_cc0 ! 993: delete_insn (prev_nonnote_insn (insn)); ! 994: #endif ! 995: delete_insn (insn); ! 996: changed = 1; ! 997: continue; ! 998: } ! 999: else ! 1000: end_sequence (); ! 1001: } ! 1002: ! 1003: /* Simplify if (...) x = 1; else {...} if (x) ... ! 1004: We recognize this case scanning backwards as well. ! 1005: ! 1006: TEMP is the assignment to x; ! 1007: TEMP1 is the label at the head of the second if. */ ! 1008: /* ?? This should call get_condition to find the values being ! 1009: compared, instead of looking for a COMPARE insn when HAVE_cc0 ! 1010: is not defined. This would allow it to work on the m88k. */ ! 1011: /* ?? This optimization is only safe before cse is run if HAVE_cc0 ! 1012: is not defined and the condition is tested by a separate compare ! 1013: insn. This is because the code below assumes that the result ! 1014: of the compare dies in the following branch. ! 1015: ! 1016: Not only that, but there might be other insns between the ! 1017: compare and branch whose results are live. Those insns need ! 1018: to be executed. ! 1019: ! 1020: A way to fix this is to move the insns at JUMP_LABEL (insn) ! 1021: to before INSN. If we are running before flow, they will ! 1022: be deleted if they aren't needed. But this doesn't work ! 1023: well after flow. ! 1024: ! 1025: This is really a special-case of jump threading, anyway. The ! 1026: right thing to do is to replace this and jump threading with ! 1027: much simpler code in cse. ! 1028: ! 1029: This code has been turned off in the non-cc0 case in the ! 1030: meantime. */ ! 1031: ! 1032: #ifdef HAVE_cc0 ! 1033: else if (this_is_simplejump ! 1034: /* Safe to skip USE and CLOBBER insns here ! 1035: since they will not be deleted. */ ! 1036: && (temp = prev_active_insn (insn)) ! 1037: && no_labels_between_p (temp, insn) ! 1038: && GET_CODE (temp) == INSN ! 1039: && GET_CODE (PATTERN (temp)) == SET ! 1040: && GET_CODE (SET_DEST (PATTERN (temp))) == REG ! 1041: && CONSTANT_P (SET_SRC (PATTERN (temp))) ! 1042: && (temp1 = next_active_insn (JUMP_LABEL (insn))) ! 1043: /* If we find that the next value tested is `x' ! 1044: (TEMP1 is the insn where this happens), win. */ ! 1045: && GET_CODE (temp1) == INSN ! 1046: && GET_CODE (PATTERN (temp1)) == SET ! 1047: #ifdef HAVE_cc0 ! 1048: /* Does temp1 `tst' the value of x? */ ! 1049: && SET_SRC (PATTERN (temp1)) == SET_DEST (PATTERN (temp)) ! 1050: && SET_DEST (PATTERN (temp1)) == cc0_rtx ! 1051: && (temp1 = next_nonnote_insn (temp1)) ! 1052: #else ! 1053: /* Does temp1 compare the value of x against zero? */ ! 1054: && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE ! 1055: && XEXP (SET_SRC (PATTERN (temp1)), 1) == const0_rtx ! 1056: && (XEXP (SET_SRC (PATTERN (temp1)), 0) ! 1057: == SET_DEST (PATTERN (temp))) ! 1058: && GET_CODE (SET_DEST (PATTERN (temp1))) == REG ! 1059: && (temp1 = find_next_ref (SET_DEST (PATTERN (temp1)), temp1)) ! 1060: #endif ! 1061: && condjump_p (temp1)) ! 1062: { ! 1063: /* Get the if_then_else from the condjump. */ ! 1064: rtx choice = SET_SRC (PATTERN (temp1)); ! 1065: if (GET_CODE (choice) == IF_THEN_ELSE) ! 1066: { ! 1067: enum rtx_code code = GET_CODE (XEXP (choice, 0)); ! 1068: rtx val = SET_SRC (PATTERN (temp)); ! 1069: rtx cond ! 1070: = simplify_relational_operation (code, GET_MODE (SET_DEST (PATTERN (temp))), ! 1071: val, const0_rtx); ! 1072: rtx ultimate; ! 1073: ! 1074: if (cond == const_true_rtx) ! 1075: ultimate = XEXP (choice, 1); ! 1076: else if (cond == const0_rtx) ! 1077: ultimate = XEXP (choice, 2); ! 1078: else ! 1079: ultimate = 0; ! 1080: ! 1081: if (ultimate == pc_rtx) ! 1082: ultimate = get_label_after (temp1); ! 1083: else if (ultimate && GET_CODE (ultimate) != RETURN) ! 1084: ultimate = XEXP (ultimate, 0); ! 1085: ! 1086: if (ultimate) ! 1087: changed |= redirect_jump (insn, ultimate); ! 1088: } ! 1089: } ! 1090: #endif ! 1091: ! 1092: #if 0 ! 1093: /* @@ This needs a bit of work before it will be right. ! 1094: ! 1095: Any type of comparison can be accepted for the first and ! 1096: second compare. When rewriting the first jump, we must ! 1097: compute the what conditions can reach label3, and use the ! 1098: appropriate code. We can not simply reverse/swap the code ! 1099: of the first jump. In some cases, the second jump must be ! 1100: rewritten also. ! 1101: ! 1102: For example, ! 1103: < == converts to > == ! 1104: < != converts to == > ! 1105: etc. ! 1106: ! 1107: If the code is written to only accept an '==' test for the second ! 1108: compare, then all that needs to be done is to swap the condition ! 1109: of the first branch. ! 1110: ! 1111: It is questionable whether we want this optimization anyways, ! 1112: since if the user wrote code like this because he/she knew that ! 1113: the jump to label1 is taken most of the time, then rewritting ! 1114: this gives slower code. */ ! 1115: /* @@ This should call get_condition to find the values being ! 1116: compared, instead of looking for a COMPARE insn when HAVE_cc0 ! 1117: is not defined. This would allow it to work on the m88k. */ ! 1118: /* @@ This optimization is only safe before cse is run if HAVE_cc0 ! 1119: is not defined and the condition is tested by a separate compare ! 1120: insn. This is because the code below assumes that the result ! 1121: of the compare dies in the following branch. */ ! 1122: ! 1123: /* Simplify test a ~= b ! 1124: condjump label1; ! 1125: test a == b ! 1126: condjump label2; ! 1127: jump label3; ! 1128: label1: ! 1129: ! 1130: rewriting as ! 1131: test a ~~= b ! 1132: condjump label3 ! 1133: test a == b ! 1134: condjump label2 ! 1135: label1: ! 1136: ! 1137: where ~= is an inequality, e.g. >, and ~~= is the swapped ! 1138: inequality, e.g. <. ! 1139: ! 1140: We recognize this case scanning backwards. ! 1141: ! 1142: TEMP is the conditional jump to `label2'; ! 1143: TEMP1 is the test for `a == b'; ! 1144: TEMP2 is the conditional jump to `label1'; ! 1145: TEMP3 is the test for `a ~= b'. */ ! 1146: else if (this_is_simplejump ! 1147: && (temp = prev_active_insn (insn)) ! 1148: && no_labels_between_p (temp, insn) ! 1149: && condjump_p (temp) ! 1150: && (temp1 = prev_active_insn (temp)) ! 1151: && no_labels_between_p (temp1, temp) ! 1152: && GET_CODE (temp1) == INSN ! 1153: && GET_CODE (PATTERN (temp1)) == SET ! 1154: #ifdef HAVE_cc0 ! 1155: && sets_cc0_p (PATTERN (temp1)) == 1 ! 1156: #else ! 1157: && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE ! 1158: && GET_CODE (SET_DEST (PATTERN (temp1))) == REG ! 1159: && (temp == find_next_ref (SET_DEST (PATTERN (temp1)), temp1)) ! 1160: #endif ! 1161: && (temp2 = prev_active_insn (temp1)) ! 1162: && no_labels_between_p (temp2, temp1) ! 1163: && condjump_p (temp2) ! 1164: && JUMP_LABEL (temp2) == next_nonnote_insn (NEXT_INSN (insn)) ! 1165: && (temp3 = prev_active_insn (temp2)) ! 1166: && no_labels_between_p (temp3, temp2) ! 1167: && GET_CODE (PATTERN (temp3)) == SET ! 1168: && rtx_equal_p (SET_DEST (PATTERN (temp3)), ! 1169: SET_DEST (PATTERN (temp1))) ! 1170: && rtx_equal_p (SET_SRC (PATTERN (temp1)), ! 1171: SET_SRC (PATTERN (temp3))) ! 1172: && ! inequality_comparisons_p (PATTERN (temp)) ! 1173: && inequality_comparisons_p (PATTERN (temp2))) ! 1174: { ! 1175: rtx fallthrough_label = JUMP_LABEL (temp2); ! 1176: ! 1177: ++LABEL_NUSES (fallthrough_label); ! 1178: if (swap_jump (temp2, JUMP_LABEL (insn))) ! 1179: { ! 1180: delete_insn (insn); ! 1181: changed = 1; ! 1182: } ! 1183: ! 1184: if (--LABEL_NUSES (fallthrough_label) == 0) ! 1185: delete_insn (fallthrough_label); ! 1186: } ! 1187: #endif ! 1188: /* Simplify if (...) {... x = 1;} if (x) ... ! 1189: ! 1190: We recognize this case backwards. ! 1191: ! 1192: TEMP is the test of `x'; ! 1193: TEMP1 is the assignment to `x' at the end of the ! 1194: previous statement. */ ! 1195: /* @@ This should call get_condition to find the values being ! 1196: compared, instead of looking for a COMPARE insn when HAVE_cc0 ! 1197: is not defined. This would allow it to work on the m88k. */ ! 1198: /* @@ This optimization is only safe before cse is run if HAVE_cc0 ! 1199: is not defined and the condition is tested by a separate compare ! 1200: insn. This is because the code below assumes that the result ! 1201: of the compare dies in the following branch. */ ! 1202: ! 1203: /* ??? This has to be turned off. The problem is that the ! 1204: unconditional jump might indirectly end up branching to the ! 1205: label between TEMP1 and TEMP. We can't detect this, in general, ! 1206: since it may become a jump to there after further optimizations. ! 1207: If that jump is done, it will be deleted, so we will retry ! 1208: this optimization in the next pass, thus an infinite loop. ! 1209: ! 1210: The present code prevents this by putting the jump after the ! 1211: label, but this is not logically correct. */ ! 1212: #if 0 ! 1213: else if (this_is_condjump ! 1214: /* Safe to skip USE and CLOBBER insns here ! 1215: since they will not be deleted. */ ! 1216: && (temp = prev_active_insn (insn)) ! 1217: && no_labels_between_p (temp, insn) ! 1218: && GET_CODE (temp) == INSN ! 1219: && GET_CODE (PATTERN (temp)) == SET ! 1220: #ifdef HAVE_cc0 ! 1221: && sets_cc0_p (PATTERN (temp)) == 1 ! 1222: && GET_CODE (SET_SRC (PATTERN (temp))) == REG ! 1223: #else ! 1224: /* Temp must be a compare insn, we can not accept a register ! 1225: to register move here, since it may not be simply a ! 1226: tst insn. */ ! 1227: && GET_CODE (SET_SRC (PATTERN (temp))) == COMPARE ! 1228: && XEXP (SET_SRC (PATTERN (temp)), 1) == const0_rtx ! 1229: && GET_CODE (XEXP (SET_SRC (PATTERN (temp)), 0)) == REG ! 1230: && GET_CODE (SET_DEST (PATTERN (temp))) == REG ! 1231: && insn == find_next_ref (SET_DEST (PATTERN (temp)), temp) ! 1232: #endif ! 1233: /* May skip USE or CLOBBER insns here ! 1234: for checking for opportunity, since we ! 1235: take care of them later. */ ! 1236: && (temp1 = prev_active_insn (temp)) ! 1237: && GET_CODE (temp1) == INSN ! 1238: && GET_CODE (PATTERN (temp1)) == SET ! 1239: #ifdef HAVE_cc0 ! 1240: && SET_SRC (PATTERN (temp)) == SET_DEST (PATTERN (temp1)) ! 1241: #else ! 1242: && (XEXP (SET_SRC (PATTERN (temp)), 0) ! 1243: == SET_DEST (PATTERN (temp1))) ! 1244: #endif ! 1245: && CONSTANT_P (SET_SRC (PATTERN (temp1))) ! 1246: /* If this isn't true, cse will do the job. */ ! 1247: && ! no_labels_between_p (temp1, temp)) ! 1248: { ! 1249: /* Get the if_then_else from the condjump. */ ! 1250: rtx choice = SET_SRC (PATTERN (insn)); ! 1251: if (GET_CODE (choice) == IF_THEN_ELSE ! 1252: && (GET_CODE (XEXP (choice, 0)) == EQ ! 1253: || GET_CODE (XEXP (choice, 0)) == NE)) ! 1254: { ! 1255: int want_nonzero = (GET_CODE (XEXP (choice, 0)) == NE); ! 1256: rtx last_insn; ! 1257: rtx ultimate; ! 1258: rtx p; ! 1259: ! 1260: /* Get the place that condjump will jump to ! 1261: if it is reached from here. */ ! 1262: if ((SET_SRC (PATTERN (temp1)) != const0_rtx) ! 1263: == want_nonzero) ! 1264: ultimate = XEXP (choice, 1); ! 1265: else ! 1266: ultimate = XEXP (choice, 2); ! 1267: /* Get it as a CODE_LABEL. */ ! 1268: if (ultimate == pc_rtx) ! 1269: ultimate = get_label_after (insn); ! 1270: else ! 1271: /* Get the label out of the LABEL_REF. */ ! 1272: ultimate = XEXP (ultimate, 0); ! 1273: ! 1274: /* Insert the jump immediately before TEMP, specifically ! 1275: after the label that is between TEMP1 and TEMP. */ ! 1276: last_insn = PREV_INSN (temp); ! 1277: ! 1278: /* If we would be branching to the next insn, the jump ! 1279: would immediately be deleted and the re-inserted in ! 1280: a subsequent pass over the code. So don't do anything ! 1281: in that case. */ ! 1282: if (next_active_insn (last_insn) ! 1283: != next_active_insn (ultimate)) ! 1284: { ! 1285: emit_barrier_after (last_insn); ! 1286: p = emit_jump_insn_after (gen_jump (ultimate), ! 1287: last_insn); ! 1288: JUMP_LABEL (p) = ultimate; ! 1289: ++LABEL_NUSES (ultimate); ! 1290: if (INSN_UID (ultimate) < max_jump_chain ! 1291: && INSN_CODE (p) < max_jump_chain) ! 1292: { ! 1293: jump_chain[INSN_UID (p)] ! 1294: = jump_chain[INSN_UID (ultimate)]; ! 1295: jump_chain[INSN_UID (ultimate)] = p; ! 1296: } ! 1297: changed = 1; ! 1298: continue; ! 1299: } ! 1300: } ! 1301: } ! 1302: #endif ! 1303: /* Detect a conditional jump going to the same place ! 1304: as an immediately following unconditional jump. */ ! 1305: else if (this_is_condjump ! 1306: && (temp = next_active_insn (insn)) != 0 ! 1307: && simplejump_p (temp) ! 1308: && (next_active_insn (JUMP_LABEL (insn)) ! 1309: == next_active_insn (JUMP_LABEL (temp)))) ! 1310: { ! 1311: delete_jump (insn); ! 1312: changed = 1; ! 1313: continue; ! 1314: } ! 1315: /* Detect a conditional jump jumping over an unconditional jump. */ ! 1316: ! 1317: else if (this_is_condjump && ! this_is_simplejump ! 1318: && reallabelprev != 0 ! 1319: && GET_CODE (reallabelprev) == JUMP_INSN ! 1320: && prev_active_insn (reallabelprev) == insn ! 1321: && no_labels_between_p (insn, reallabelprev) ! 1322: && simplejump_p (reallabelprev)) ! 1323: { ! 1324: /* When we invert the unconditional jump, we will be ! 1325: decrementing the usage count of its old label. ! 1326: Make sure that we don't delete it now because that ! 1327: might cause the following code to be deleted. */ ! 1328: rtx prev_uses = prev_nonnote_insn (reallabelprev); ! 1329: rtx prev_label = JUMP_LABEL (insn); ! 1330: ! 1331: ++LABEL_NUSES (prev_label); ! 1332: ! 1333: if (invert_jump (insn, JUMP_LABEL (reallabelprev))) ! 1334: { ! 1335: /* It is very likely that if there are USE insns before ! 1336: this jump, they hold REG_DEAD notes. These REG_DEAD ! 1337: notes are no longer valid due to this optimization, ! 1338: and will cause the life-analysis that following passes ! 1339: (notably delayed-branch scheduling) to think that ! 1340: these registers are dead when they are not. ! 1341: ! 1342: To prevent this trouble, we just remove the USE insns ! 1343: from the insn chain. */ ! 1344: ! 1345: while (prev_uses && GET_CODE (prev_uses) == INSN ! 1346: && GET_CODE (PATTERN (prev_uses)) == USE) ! 1347: { ! 1348: rtx useless = prev_uses; ! 1349: prev_uses = prev_nonnote_insn (prev_uses); ! 1350: delete_insn (useless); ! 1351: } ! 1352: ! 1353: delete_insn (reallabelprev); ! 1354: next = insn; ! 1355: changed = 1; ! 1356: } ! 1357: ! 1358: /* We can now safely delete the label if it is unreferenced ! 1359: since the delete_insn above has deleted the BARRIER. */ ! 1360: if (--LABEL_NUSES (prev_label) == 0) ! 1361: delete_insn (prev_label); ! 1362: continue; ! 1363: } ! 1364: else ! 1365: { ! 1366: /* Detect a jump to a jump. */ ! 1367: ! 1368: nlabel = follow_jumps (JUMP_LABEL (insn)); ! 1369: if (nlabel != JUMP_LABEL (insn) ! 1370: && redirect_jump (insn, nlabel)) ! 1371: { ! 1372: changed = 1; ! 1373: next = insn; ! 1374: } ! 1375: ! 1376: /* Look for if (foo) bar; else break; */ ! 1377: /* The insns look like this: ! 1378: insn = condjump label1; ! 1379: ...range1 (some insns)... ! 1380: jump label2; ! 1381: label1: ! 1382: ...range2 (some insns)... ! 1383: jump somewhere unconditionally ! 1384: label2: */ ! 1385: { ! 1386: rtx label1 = next_label (insn); ! 1387: rtx range1end = label1 ? prev_active_insn (label1) : 0; ! 1388: /* Don't do this optimization on the first round, so that ! 1389: jump-around-a-jump gets simplified before we ask here ! 1390: whether a jump is unconditional. ! 1391: ! 1392: Also don't do it when we are called after reload since ! 1393: it will confuse reorg. */ ! 1394: if (! first ! 1395: && (reload_completed ? ! flag_delayed_branch : 1) ! 1396: /* Make sure INSN is something we can invert. */ ! 1397: && condjump_p (insn) ! 1398: && label1 != 0 ! 1399: && JUMP_LABEL (insn) == label1 ! 1400: && LABEL_NUSES (label1) == 1 ! 1401: && GET_CODE (range1end) == JUMP_INSN ! 1402: && simplejump_p (range1end)) ! 1403: { ! 1404: rtx label2 = next_label (label1); ! 1405: rtx range2end = label2 ? prev_active_insn (label2) : 0; ! 1406: if (range1end != range2end ! 1407: && JUMP_LABEL (range1end) == label2 ! 1408: && GET_CODE (range2end) == JUMP_INSN ! 1409: && GET_CODE (NEXT_INSN (range2end)) == BARRIER ! 1410: /* Invert the jump condition, so we ! 1411: still execute the same insns in each case. */ ! 1412: && invert_jump (insn, label1)) ! 1413: { ! 1414: rtx range1beg = next_active_insn (insn); ! 1415: rtx range2beg = next_active_insn (label1); ! 1416: rtx range1after, range2after; ! 1417: rtx range1before, range2before; ! 1418: ! 1419: /* Don't move NOTEs for blocks or loops; shift them ! 1420: outside the ranges, where they'll stay put. */ ! 1421: squeeze_notes (range1beg, range1end); ! 1422: squeeze_notes (range2beg, range2end); ! 1423: ! 1424: /* Get current surrounds of the 2 ranges. */ ! 1425: range1before = PREV_INSN (range1beg); ! 1426: range2before = PREV_INSN (range2beg); ! 1427: range1after = NEXT_INSN (range1end); ! 1428: range2after = NEXT_INSN (range2end); ! 1429: ! 1430: /* Splice range2 where range1 was. */ ! 1431: NEXT_INSN (range1before) = range2beg; ! 1432: PREV_INSN (range2beg) = range1before; ! 1433: NEXT_INSN (range2end) = range1after; ! 1434: PREV_INSN (range1after) = range2end; ! 1435: /* Splice range1 where range2 was. */ ! 1436: NEXT_INSN (range2before) = range1beg; ! 1437: PREV_INSN (range1beg) = range2before; ! 1438: NEXT_INSN (range1end) = range2after; ! 1439: PREV_INSN (range2after) = range1end; ! 1440: changed = 1; ! 1441: continue; ! 1442: } ! 1443: } ! 1444: } ! 1445: ! 1446: /* Now that the jump has been tensioned, ! 1447: try cross jumping: check for identical code ! 1448: before the jump and before its target label. */ ! 1449: ! 1450: /* First, cross jumping of conditional jumps: */ ! 1451: ! 1452: if (cross_jump && condjump_p (insn)) ! 1453: { ! 1454: rtx newjpos, newlpos; ! 1455: rtx x = prev_real_insn (JUMP_LABEL (insn)); ! 1456: ! 1457: /* A conditional jump may be crossjumped ! 1458: only if the place it jumps to follows ! 1459: an opposing jump that comes back here. */ ! 1460: ! 1461: if (x != 0 && ! jump_back_p (x, insn)) ! 1462: /* We have no opposing jump; ! 1463: cannot cross jump this insn. */ ! 1464: x = 0; ! 1465: ! 1466: newjpos = 0; ! 1467: /* TARGET is nonzero if it is ok to cross jump ! 1468: to code before TARGET. If so, see if matches. */ ! 1469: if (x != 0) ! 1470: find_cross_jump (insn, x, 2, ! 1471: &newjpos, &newlpos); ! 1472: ! 1473: if (newjpos != 0) ! 1474: { ! 1475: do_cross_jump (insn, newjpos, newlpos); ! 1476: /* Make the old conditional jump ! 1477: into an unconditional one. */ ! 1478: SET_SRC (PATTERN (insn)) ! 1479: = gen_rtx (LABEL_REF, VOIDmode, JUMP_LABEL (insn)); ! 1480: INSN_CODE (insn) = -1; ! 1481: emit_barrier_after (insn); ! 1482: /* Add to jump_chain unless this is a new label ! 1483: whose UID is too large. */ ! 1484: if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain) ! 1485: { ! 1486: jump_chain[INSN_UID (insn)] ! 1487: = jump_chain[INSN_UID (JUMP_LABEL (insn))]; ! 1488: jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn; ! 1489: } ! 1490: changed = 1; ! 1491: next = insn; ! 1492: } ! 1493: } ! 1494: ! 1495: /* Cross jumping of unconditional jumps: ! 1496: a few differences. */ ! 1497: ! 1498: if (cross_jump && simplejump_p (insn)) ! 1499: { ! 1500: rtx newjpos, newlpos; ! 1501: rtx target; ! 1502: ! 1503: newjpos = 0; ! 1504: ! 1505: /* TARGET is nonzero if it is ok to cross jump ! 1506: to code before TARGET. If so, see if matches. */ ! 1507: find_cross_jump (insn, JUMP_LABEL (insn), 1, ! 1508: &newjpos, &newlpos); ! 1509: ! 1510: /* If cannot cross jump to code before the label, ! 1511: see if we can cross jump to another jump to ! 1512: the same label. */ ! 1513: /* Try each other jump to this label. */ ! 1514: if (INSN_UID (JUMP_LABEL (insn)) < max_uid) ! 1515: for (target = jump_chain[INSN_UID (JUMP_LABEL (insn))]; ! 1516: target != 0 && newjpos == 0; ! 1517: target = jump_chain[INSN_UID (target)]) ! 1518: if (target != insn ! 1519: && JUMP_LABEL (target) == JUMP_LABEL (insn) ! 1520: /* Ignore TARGET if it's deleted. */ ! 1521: && ! INSN_DELETED_P (target)) ! 1522: find_cross_jump (insn, target, 2, ! 1523: &newjpos, &newlpos); ! 1524: ! 1525: if (newjpos != 0) ! 1526: { ! 1527: do_cross_jump (insn, newjpos, newlpos); ! 1528: changed = 1; ! 1529: next = insn; ! 1530: } ! 1531: } ! 1532: ! 1533: /* This code was dead in the previous jump.c! */ ! 1534: if (cross_jump && GET_CODE (PATTERN (insn)) == RETURN) ! 1535: { ! 1536: /* Return insns all "jump to the same place" ! 1537: so we can cross-jump between any two of them. */ ! 1538: ! 1539: rtx newjpos, newlpos, target; ! 1540: ! 1541: newjpos = 0; ! 1542: ! 1543: /* If cannot cross jump to code before the label, ! 1544: see if we can cross jump to another jump to ! 1545: the same label. */ ! 1546: /* Try each other jump to this label. */ ! 1547: for (target = jump_chain[0]; ! 1548: target != 0 && newjpos == 0; ! 1549: target = jump_chain[INSN_UID (target)]) ! 1550: if (target != insn ! 1551: && ! INSN_DELETED_P (target) ! 1552: && GET_CODE (PATTERN (target)) == RETURN) ! 1553: find_cross_jump (insn, target, 2, ! 1554: &newjpos, &newlpos); ! 1555: ! 1556: if (newjpos != 0) ! 1557: { ! 1558: do_cross_jump (insn, newjpos, newlpos); ! 1559: changed = 1; ! 1560: next = insn; ! 1561: } ! 1562: } ! 1563: } ! 1564: } ! 1565: ! 1566: first = 0; ! 1567: } ! 1568: ! 1569: /* Delete extraneous line number notes. ! 1570: Note that two consecutive notes for different lines are not really ! 1571: extraneous. There should be some indication where that line belonged, ! 1572: even if it became empty. */ ! 1573: ! 1574: { ! 1575: rtx last_note = 0; ! 1576: ! 1577: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 1578: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) >= 0) ! 1579: { ! 1580: /* Delete this note if it is identical to previous note. */ ! 1581: if (last_note ! 1582: && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note) ! 1583: && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note)) ! 1584: { ! 1585: delete_insn (insn); ! 1586: continue; ! 1587: } ! 1588: ! 1589: last_note = insn; ! 1590: } ! 1591: } ! 1592: ! 1593: /* See if there is still a NOTE_INSN_FUNCTION_END in this function. ! 1594: If so, delete it, and record that this function can drop off the end. */ ! 1595: ! 1596: insn = last_insn; ! 1597: { ! 1598: int n_labels = 1; ! 1599: while (insn ! 1600: /* One label can follow the end-note: the return label. */ ! 1601: && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0) ! 1602: /* Ordinary insns can follow it if returning a structure. */ ! 1603: || GET_CODE (insn) == INSN ! 1604: /* If machine uses explicit RETURN insns, no epilogue, ! 1605: then one of them follows the note. */ ! 1606: || (GET_CODE (insn) == JUMP_INSN ! 1607: && GET_CODE (PATTERN (insn)) == RETURN) ! 1608: /* Other kinds of notes can follow also. */ ! 1609: || (GET_CODE (insn) == NOTE ! 1610: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END))) ! 1611: insn = PREV_INSN (insn); ! 1612: } ! 1613: ! 1614: /* Report if control can fall through at the end of the function. */ ! 1615: if (insn && GET_CODE (insn) == NOTE ! 1616: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END) ! 1617: { ! 1618: can_reach_end = 1; ! 1619: delete_insn (insn); ! 1620: } ! 1621: ! 1622: /* Show JUMP_CHAIN no longer valid. */ ! 1623: jump_chain = 0; ! 1624: } ! 1625: ! 1626: /* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional ! 1627: jump. Assume that this unconditional jump is to the exit test code. If ! 1628: the code is sufficiently simple, make a copy of it before INSN, ! 1629: followed by a jump to the exit of the loop. Then delete the unconditional ! 1630: jump after INSN. ! 1631: ! 1632: Note that it is possible we can get confused here if the jump immediately ! 1633: after the loop start branches outside the loop but within an outer loop. ! 1634: If we are near the exit of that loop, we will copy its exit test. This ! 1635: will not generate incorrect code, but could suppress some optimizations. ! 1636: However, such cases are degenerate loops anyway. ! 1637: ! 1638: Return 1 if we made the change, else 0. ! 1639: ! 1640: This is only safe immediately after a regscan pass because it uses the ! 1641: values of regno_first_uid and regno_last_uid. */ ! 1642: ! 1643: static int ! 1644: duplicate_loop_exit_test (loop_start) ! 1645: rtx loop_start; ! 1646: { ! 1647: rtx insn, set, p; ! 1648: rtx copy, link; ! 1649: int num_insns = 0; ! 1650: rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start))); ! 1651: rtx lastexit; ! 1652: int max_reg = max_reg_num (); ! 1653: rtx *reg_map = 0; ! 1654: ! 1655: /* Scan the exit code. We do not perform this optimization if any insn: ! 1656: ! 1657: is a CALL_INSN ! 1658: is a CODE_LABEL ! 1659: has a REG_RETVAL or REG_LIBCALL note (hard to adjust) ! 1660: is a NOTE_INSN_LOOP_BEG because this means we have a nested loop ! 1661: is a NOTE_INSN_BLOCK_{BEG,END} because duplicating these notes ! 1662: are not valid ! 1663: ! 1664: Also, don't do this if the exit code is more than 20 insns. */ ! 1665: ! 1666: for (insn = exitcode; ! 1667: insn ! 1668: && ! (GET_CODE (insn) == NOTE ! 1669: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END); ! 1670: insn = NEXT_INSN (insn)) ! 1671: { ! 1672: switch (GET_CODE (insn)) ! 1673: { ! 1674: case CODE_LABEL: ! 1675: case CALL_INSN: ! 1676: return 0; ! 1677: case NOTE: ! 1678: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG ! 1679: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG ! 1680: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) ! 1681: return 0; ! 1682: break; ! 1683: case JUMP_INSN: ! 1684: case INSN: ! 1685: if (++num_insns > 20 ! 1686: || find_reg_note (insn, REG_RETVAL, 0) ! 1687: || find_reg_note (insn, REG_LIBCALL, 0)) ! 1688: return 0; ! 1689: break; ! 1690: } ! 1691: } ! 1692: ! 1693: /* Unless INSN is zero, we can do the optimization. */ ! 1694: if (insn == 0) ! 1695: return 0; ! 1696: ! 1697: lastexit = insn; ! 1698: ! 1699: /* See if any insn sets a register only used in the loop exit code and ! 1700: not a user variable. If so, replace it with a new register. */ ! 1701: for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) ! 1702: if (GET_CODE (insn) == INSN ! 1703: && (set = single_set (insn)) != 0 ! 1704: && GET_CODE (SET_DEST (set)) == REG ! 1705: && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER ! 1706: && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)) ! 1707: { ! 1708: for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p)) ! 1709: if (regno_last_uid[REGNO (SET_DEST (set))] == INSN_UID (p)) ! 1710: break; ! 1711: ! 1712: if (p != lastexit) ! 1713: { ! 1714: /* We can do the replacement. Allocate reg_map if this is the ! 1715: first replacement we found. */ ! 1716: if (reg_map == 0) ! 1717: { ! 1718: reg_map = (rtx *) alloca (max_reg * sizeof (rtx)); ! 1719: bzero (reg_map, max_reg * sizeof (rtx)); ! 1720: } ! 1721: ! 1722: REG_LOOP_TEST_P (SET_DEST (set)) = 1; ! 1723: ! 1724: reg_map[REGNO (SET_DEST (set))] ! 1725: = gen_reg_rtx (GET_MODE (SET_DEST (set))); ! 1726: } ! 1727: } ! 1728: ! 1729: /* Now copy each insn. */ ! 1730: for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) ! 1731: switch (GET_CODE (insn)) ! 1732: { ! 1733: case BARRIER: ! 1734: copy = emit_barrier_before (loop_start); ! 1735: break; ! 1736: case NOTE: ! 1737: /* Only copy line-number notes. */ ! 1738: if (NOTE_LINE_NUMBER (insn) >= 0) ! 1739: { ! 1740: copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start); ! 1741: NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); ! 1742: } ! 1743: break; ! 1744: ! 1745: case INSN: ! 1746: copy = emit_insn_before (copy_rtx (PATTERN (insn)), loop_start); ! 1747: if (reg_map) ! 1748: replace_regs (PATTERN (copy), reg_map, max_reg, 1); ! 1749: ! 1750: mark_jump_label (PATTERN (copy), copy, 0); ! 1751: ! 1752: /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will ! 1753: make them. */ ! 1754: for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) ! 1755: if (REG_NOTE_KIND (link) != REG_LABEL) ! 1756: REG_NOTES (copy) ! 1757: = copy_rtx (gen_rtx (EXPR_LIST, REG_NOTE_KIND (link), ! 1758: XEXP (link, 0), REG_NOTES (copy))); ! 1759: if (reg_map && REG_NOTES (copy)) ! 1760: replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); ! 1761: break; ! 1762: ! 1763: case JUMP_INSN: ! 1764: copy = emit_jump_insn_before (copy_rtx (PATTERN (insn)), loop_start); ! 1765: if (reg_map) ! 1766: replace_regs (PATTERN (copy), reg_map, max_reg, 1); ! 1767: mark_jump_label (PATTERN (copy), copy, 0); ! 1768: if (REG_NOTES (insn)) ! 1769: { ! 1770: REG_NOTES (copy) = copy_rtx (REG_NOTES (insn)); ! 1771: if (reg_map) ! 1772: replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); ! 1773: } ! 1774: ! 1775: /* If this is a simple jump, add it to the jump chain. */ ! 1776: ! 1777: if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy) ! 1778: && simplejump_p (copy)) ! 1779: { ! 1780: jump_chain[INSN_UID (copy)] ! 1781: = jump_chain[INSN_UID (JUMP_LABEL (copy))]; ! 1782: jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy; ! 1783: } ! 1784: break; ! 1785: ! 1786: default: ! 1787: abort (); ! 1788: } ! 1789: ! 1790: /* Now clean up by emitting a jump to the end label and deleting the jump ! 1791: at the start of the loop. */ ! 1792: if (GET_CODE (copy) != BARRIER) ! 1793: { ! 1794: copy = emit_jump_insn_before (gen_jump (get_label_after (insn)), ! 1795: loop_start); ! 1796: mark_jump_label (PATTERN (copy), copy, 0); ! 1797: if (INSN_UID (copy) < max_jump_chain ! 1798: && INSN_UID (JUMP_LABEL (copy)) < max_jump_chain) ! 1799: { ! 1800: jump_chain[INSN_UID (copy)] ! 1801: = jump_chain[INSN_UID (JUMP_LABEL (copy))]; ! 1802: jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy; ! 1803: } ! 1804: emit_barrier_before (loop_start); ! 1805: } ! 1806: ! 1807: delete_insn (next_nonnote_insn (loop_start)); ! 1808: ! 1809: /* Mark the exit code as the virtual top of the converted loop. */ ! 1810: emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode); ! 1811: ! 1812: return 1; ! 1813: } ! 1814: ! 1815: /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, and ! 1816: loop-end notes between START and END out before START. Assume neither ! 1817: START nor END is such a note. */ ! 1818: ! 1819: void ! 1820: squeeze_notes (start, end) ! 1821: rtx start, end; ! 1822: { ! 1823: rtx insn; ! 1824: rtx next; ! 1825: ! 1826: for (insn = start; insn != end; insn = next) ! 1827: { ! 1828: next = NEXT_INSN (insn); ! 1829: if (GET_CODE (insn) == NOTE ! 1830: && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END ! 1831: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG ! 1832: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG ! 1833: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END ! 1834: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT ! 1835: || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP)) ! 1836: { ! 1837: rtx prev = PREV_INSN (insn); ! 1838: PREV_INSN (insn) = PREV_INSN (start); ! 1839: NEXT_INSN (insn) = start; ! 1840: NEXT_INSN (PREV_INSN (insn)) = insn; ! 1841: PREV_INSN (NEXT_INSN (insn)) = insn; ! 1842: NEXT_INSN (prev) = next; ! 1843: PREV_INSN (next) = prev; ! 1844: } ! 1845: } ! 1846: } ! 1847: ! 1848: /* Compare the instructions before insn E1 with those before E2 ! 1849: to find an opportunity for cross jumping. ! 1850: (This means detecting identical sequences of insns followed by ! 1851: jumps to the same place, or followed by a label and a jump ! 1852: to that label, and replacing one with a jump to the other.) ! 1853: ! 1854: Assume E1 is a jump that jumps to label E2 ! 1855: (that is not always true but it might as well be). ! 1856: Find the longest possible equivalent sequences ! 1857: and store the first insns of those sequences into *F1 and *F2. ! 1858: Store zero there if no equivalent preceding instructions are found. ! 1859: ! 1860: We give up if we find a label in stream 1. ! 1861: Actually we could transfer that label into stream 2. */ ! 1862: ! 1863: static void ! 1864: find_cross_jump (e1, e2, minimum, f1, f2) ! 1865: rtx e1, e2; ! 1866: int minimum; ! 1867: rtx *f1, *f2; ! 1868: { ! 1869: register rtx i1 = e1, i2 = e2; ! 1870: register rtx p1, p2; ! 1871: int lose = 0; ! 1872: ! 1873: rtx last1 = 0, last2 = 0; ! 1874: rtx afterlast1 = 0, afterlast2 = 0; ! 1875: rtx prev1; ! 1876: ! 1877: *f1 = 0; ! 1878: *f2 = 0; ! 1879: ! 1880: while (1) ! 1881: { ! 1882: i1 = prev_nonnote_insn (i1); ! 1883: ! 1884: i2 = PREV_INSN (i2); ! 1885: while (i2 && (GET_CODE (i2) == NOTE || GET_CODE (i2) == CODE_LABEL)) ! 1886: i2 = PREV_INSN (i2); ! 1887: ! 1888: if (i1 == 0) ! 1889: break; ! 1890: ! 1891: /* Don't allow the range of insns preceding E1 or E2 ! 1892: to include the other (E2 or E1). */ ! 1893: if (i2 == e1 || i1 == e2) ! 1894: break; ! 1895: ! 1896: /* If we will get to this code by jumping, those jumps will be ! 1897: tensioned to go directly to the new label (before I2), ! 1898: so this cross-jumping won't cost extra. So reduce the minimum. */ ! 1899: if (GET_CODE (i1) == CODE_LABEL) ! 1900: { ! 1901: --minimum; ! 1902: break; ! 1903: } ! 1904: ! 1905: if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2)) ! 1906: break; ! 1907: ! 1908: p1 = PATTERN (i1); ! 1909: p2 = PATTERN (i2); ! 1910: ! 1911: #ifdef STACK_REGS ! 1912: /* If cross_jump_death_matters is not 0, the insn's mode ! 1913: indicates whether or not the insn contains any stack-like ! 1914: regs. */ ! 1915: ! 1916: if (cross_jump_death_matters && GET_MODE (i1) == QImode) ! 1917: { ! 1918: /* If register stack conversion has already been done, then ! 1919: death notes must also be compared before it is certain that ! 1920: the two instruction streams match. */ ! 1921: ! 1922: rtx note; ! 1923: HARD_REG_SET i1_regset, i2_regset; ! 1924: ! 1925: CLEAR_HARD_REG_SET (i1_regset); ! 1926: CLEAR_HARD_REG_SET (i2_regset); ! 1927: ! 1928: for (note = REG_NOTES (i1); note; note = XEXP (note, 1)) ! 1929: if (REG_NOTE_KIND (note) == REG_DEAD ! 1930: && STACK_REG_P (XEXP (note, 0))) ! 1931: SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0))); ! 1932: ! 1933: for (note = REG_NOTES (i2); note; note = XEXP (note, 1)) ! 1934: if (REG_NOTE_KIND (note) == REG_DEAD ! 1935: && STACK_REG_P (XEXP (note, 0))) ! 1936: SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0))); ! 1937: ! 1938: GO_IF_HARD_REG_EQUAL (i1_regset, i2_regset, done); ! 1939: ! 1940: lose = 1; ! 1941: ! 1942: done: ! 1943: ; ! 1944: } ! 1945: #endif ! 1946: ! 1947: if (lose || GET_CODE (p1) != GET_CODE (p2) ! 1948: || ! rtx_renumbered_equal_p (p1, p2)) ! 1949: { ! 1950: /* The following code helps take care of G++ cleanups. */ ! 1951: rtx equiv1; ! 1952: rtx equiv2; ! 1953: ! 1954: if (!lose && GET_CODE (p1) == GET_CODE (p2) ! 1955: && ((equiv1 = find_reg_note (i1, REG_EQUAL, 0)) != 0 ! 1956: || (equiv1 = find_reg_note (i1, REG_EQUIV, 0)) != 0) ! 1957: && ((equiv2 = find_reg_note (i2, REG_EQUAL, 0)) != 0 ! 1958: || (equiv2 = find_reg_note (i2, REG_EQUIV, 0)) != 0) ! 1959: /* If the equivalences are not to a constant, they may ! 1960: reference pseudos that no longer exist, so we can't ! 1961: use them. */ ! 1962: && CONSTANT_P (XEXP (equiv1, 0)) ! 1963: && rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0))) ! 1964: { ! 1965: rtx s1 = single_set (i1); ! 1966: rtx s2 = single_set (i2); ! 1967: if (s1 != 0 && s2 != 0 ! 1968: && rtx_renumbered_equal_p (SET_DEST (s1), SET_DEST (s2))) ! 1969: { ! 1970: validate_change (i1, &SET_SRC (s1), XEXP (equiv1, 0), 1); ! 1971: validate_change (i2, &SET_SRC (s2), XEXP (equiv2, 0), 1); ! 1972: if (! rtx_renumbered_equal_p (p1, p2)) ! 1973: cancel_changes (0); ! 1974: else if (apply_change_group ()) ! 1975: goto win; ! 1976: } ! 1977: } ! 1978: ! 1979: /* Insns fail to match; cross jumping is limited to the following ! 1980: insns. */ ! 1981: ! 1982: #ifdef HAVE_cc0 ! 1983: /* Don't allow the insn after a compare to be shared by ! 1984: cross-jumping unless the compare is also shared. ! 1985: Here, if either of these non-matching insns is a compare, ! 1986: exclude the following insn from possible cross-jumping. */ ! 1987: if (sets_cc0_p (p1) || sets_cc0_p (p2)) ! 1988: last1 = afterlast1, last2 = afterlast2, ++minimum; ! 1989: #endif ! 1990: ! 1991: /* If cross-jumping here will feed a jump-around-jump ! 1992: optimization, this jump won't cost extra, so reduce ! 1993: the minimum. */ ! 1994: if (GET_CODE (i1) == JUMP_INSN ! 1995: && JUMP_LABEL (i1) ! 1996: && prev_real_insn (JUMP_LABEL (i1)) == e1) ! 1997: --minimum; ! 1998: break; ! 1999: } ! 2000: ! 2001: win: ! 2002: if (GET_CODE (p1) != USE && GET_CODE (p1) != CLOBBER) ! 2003: { ! 2004: /* Ok, this insn is potentially includable in a cross-jump here. */ ! 2005: afterlast1 = last1, afterlast2 = last2; ! 2006: last1 = i1, last2 = i2, --minimum; ! 2007: } ! 2008: } ! 2009: ! 2010: /* We have to be careful that we do not cross-jump into the middle of ! 2011: USE-CALL_INSN-CLOBBER sequence. This sequence is used instead of ! 2012: putting the USE and CLOBBERs inside the CALL_INSN. The delay slot ! 2013: scheduler needs to know what registers are used and modified by the ! 2014: CALL_INSN and needs the adjacent USE and CLOBBERs to do so. ! 2015: ! 2016: ??? At some point we should probably change this so that these are ! 2017: part of the CALL_INSN. The way we are doing it now is a kludge that ! 2018: is now causing trouble. */ ! 2019: ! 2020: if (last1 != 0 && GET_CODE (last1) == CALL_INSN ! 2021: && (prev1 = prev_nonnote_insn (last1)) ! 2022: && GET_CODE (prev1) == INSN ! 2023: && GET_CODE (PATTERN (prev1)) == USE) ! 2024: { ! 2025: /* Remove this CALL_INSN from the range we can cross-jump. */ ! 2026: last1 = next_real_insn (last1); ! 2027: last2 = next_real_insn (last2); ! 2028: ! 2029: minimum++; ! 2030: } ! 2031: ! 2032: /* Skip past CLOBBERS since they may be right after a CALL_INSN. It ! 2033: isn't worth checking for the CALL_INSN. */ ! 2034: while (last1 != 0 && GET_CODE (PATTERN (last1)) == CLOBBER) ! 2035: last1 = next_real_insn (last1), last2 = next_real_insn (last2); ! 2036: ! 2037: if (minimum <= 0 && last1 != 0 && last1 != e1) ! 2038: *f1 = last1, *f2 = last2; ! 2039: } ! 2040: ! 2041: static void ! 2042: do_cross_jump (insn, newjpos, newlpos) ! 2043: rtx insn, newjpos, newlpos; ! 2044: { ! 2045: /* Find an existing label at this point ! 2046: or make a new one if there is none. */ ! 2047: register rtx label = get_label_before (newlpos); ! 2048: ! 2049: /* Make the same jump insn jump to the new point. */ ! 2050: if (GET_CODE (PATTERN (insn)) == RETURN) ! 2051: { ! 2052: /* Remove from jump chain of returns. */ ! 2053: delete_from_jump_chain (insn); ! 2054: /* Change the insn. */ ! 2055: PATTERN (insn) = gen_jump (label); ! 2056: INSN_CODE (insn) = -1; ! 2057: JUMP_LABEL (insn) = label; ! 2058: LABEL_NUSES (label)++; ! 2059: /* Add to new the jump chain. */ ! 2060: if (INSN_UID (label) < max_jump_chain ! 2061: && INSN_UID (insn) < max_jump_chain) ! 2062: { ! 2063: jump_chain[INSN_UID (insn)] = jump_chain[INSN_UID (label)]; ! 2064: jump_chain[INSN_UID (label)] = insn; ! 2065: } ! 2066: } ! 2067: else ! 2068: redirect_jump (insn, label); ! 2069: ! 2070: /* Delete the matching insns before the jump. Also, remove any REG_EQUAL ! 2071: or REG_EQUIV note in the NEWLPOS stream that isn't also present in ! 2072: the NEWJPOS stream. */ ! 2073: ! 2074: while (newjpos != insn) ! 2075: { ! 2076: rtx lnote; ! 2077: ! 2078: for (lnote = REG_NOTES (newlpos); lnote; lnote = XEXP (lnote, 1)) ! 2079: if ((REG_NOTE_KIND (lnote) == REG_EQUAL ! 2080: || REG_NOTE_KIND (lnote) == REG_EQUIV) ! 2081: && ! find_reg_note (newjpos, REG_EQUAL, XEXP (lnote, 0)) ! 2082: && ! find_reg_note (newjpos, REG_EQUIV, XEXP (lnote, 0))) ! 2083: remove_note (newlpos, lnote); ! 2084: ! 2085: delete_insn (newjpos); ! 2086: newjpos = next_real_insn (newjpos); ! 2087: newlpos = next_real_insn (newlpos); ! 2088: } ! 2089: } ! 2090: ! 2091: /* Return the label before INSN, or put a new label there. */ ! 2092: ! 2093: rtx ! 2094: get_label_before (insn) ! 2095: rtx insn; ! 2096: { ! 2097: rtx label; ! 2098: ! 2099: /* Find an existing label at this point ! 2100: or make a new one if there is none. */ ! 2101: label = prev_nonnote_insn (insn); ! 2102: ! 2103: if (label == 0 || GET_CODE (label) != CODE_LABEL) ! 2104: { ! 2105: rtx prev = PREV_INSN (insn); ! 2106: ! 2107: /* Don't put a label between a CALL_INSN and USE insns that preceed ! 2108: it. */ ! 2109: ! 2110: if (GET_CODE (insn) == CALL_INSN ! 2111: || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE ! 2112: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) ! 2113: while (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == USE) ! 2114: prev = PREV_INSN (prev); ! 2115: ! 2116: label = gen_label_rtx (); ! 2117: emit_label_after (label, prev); ! 2118: LABEL_NUSES (label) = 0; ! 2119: } ! 2120: return label; ! 2121: } ! 2122: ! 2123: /* Return the label after INSN, or put a new label there. */ ! 2124: ! 2125: rtx ! 2126: get_label_after (insn) ! 2127: rtx insn; ! 2128: { ! 2129: rtx label; ! 2130: ! 2131: /* Find an existing label at this point ! 2132: or make a new one if there is none. */ ! 2133: label = next_nonnote_insn (insn); ! 2134: ! 2135: if (label == 0 || GET_CODE (label) != CODE_LABEL) ! 2136: { ! 2137: /* Don't put a label between a CALL_INSN and CLOBBER insns ! 2138: following it. */ ! 2139: ! 2140: if (GET_CODE (insn) == CALL_INSN ! 2141: || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE ! 2142: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) ! 2143: while (GET_CODE (NEXT_INSN (insn)) == INSN ! 2144: && GET_CODE (PATTERN (NEXT_INSN (insn))) == CLOBBER) ! 2145: insn = NEXT_INSN (insn); ! 2146: ! 2147: label = gen_label_rtx (); ! 2148: emit_label_after (label, insn); ! 2149: LABEL_NUSES (label) = 0; ! 2150: } ! 2151: return label; ! 2152: } ! 2153: ! 2154: /* Return 1 if INSN is a jump that jumps to right after TARGET ! 2155: only on the condition that TARGET itself would drop through. ! 2156: Assumes that TARGET is a conditional jump. */ ! 2157: ! 2158: static int ! 2159: jump_back_p (insn, target) ! 2160: rtx insn, target; ! 2161: { ! 2162: rtx cinsn, ctarget; ! 2163: enum rtx_code codei, codet; ! 2164: ! 2165: if (simplejump_p (insn) || ! condjump_p (insn) ! 2166: || simplejump_p (target) ! 2167: || target != prev_real_insn (JUMP_LABEL (insn))) ! 2168: return 0; ! 2169: ! 2170: cinsn = XEXP (SET_SRC (PATTERN (insn)), 0); ! 2171: ctarget = XEXP (SET_SRC (PATTERN (target)), 0); ! 2172: ! 2173: codei = GET_CODE (cinsn); ! 2174: codet = GET_CODE (ctarget); ! 2175: ! 2176: if (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx) ! 2177: { ! 2178: if (! can_reverse_comparison_p (cinsn, insn)) ! 2179: return 0; ! 2180: codei = reverse_condition (codei); ! 2181: } ! 2182: ! 2183: if (XEXP (SET_SRC (PATTERN (target)), 2) == pc_rtx) ! 2184: { ! 2185: if (! can_reverse_comparison_p (ctarget, target)) ! 2186: return 0; ! 2187: codet = reverse_condition (codet); ! 2188: } ! 2189: ! 2190: return (codei == codet ! 2191: && rtx_renumbered_equal_p (XEXP (cinsn, 0), XEXP (ctarget, 0)) ! 2192: && rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1))); ! 2193: } ! 2194: ! 2195: /* Given a comparison, COMPARISON, inside a conditional jump insn, INSN, ! 2196: return non-zero if it is safe to reverse this comparison. It is if our ! 2197: floating-point is not IEEE, if this is an NE or EQ comparison, or if ! 2198: this is known to be an integer comparison. */ ! 2199: ! 2200: int ! 2201: can_reverse_comparison_p (comparison, insn) ! 2202: rtx comparison; ! 2203: rtx insn; ! 2204: { ! 2205: rtx arg0; ! 2206: ! 2207: /* If this is not actually a comparison, we can't reverse it. */ ! 2208: if (GET_RTX_CLASS (GET_CODE (comparison)) != '<') ! 2209: return 0; ! 2210: ! 2211: if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT ! 2212: /* If this is an NE comparison, it is safe to reverse it to an EQ ! 2213: comparison and vice versa, even for floating point. If no operands ! 2214: are NaNs, the reversal is valid. If some operand is a NaN, EQ is ! 2215: always false and NE is always true, so the reversal is also valid. */ ! 2216: || GET_CODE (comparison) == NE ! 2217: || GET_CODE (comparison) == EQ) ! 2218: return 1; ! 2219: ! 2220: arg0 = XEXP (comparison, 0); ! 2221: ! 2222: /* Make sure ARG0 is one of the actual objects being compared. If we ! 2223: can't do this, we can't be sure the comparison can be reversed. ! 2224: ! 2225: Handle cc0 and a MODE_CC register. */ ! 2226: if ((GET_CODE (arg0) == REG && GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC) ! 2227: #ifdef HAVE_cc0 ! 2228: || arg0 == cc0_rtx ! 2229: #endif ! 2230: ) ! 2231: { ! 2232: rtx prev = prev_nonnote_insn (insn); ! 2233: rtx set = single_set (prev); ! 2234: ! 2235: if (set == 0 || SET_DEST (set) != arg0) ! 2236: return 0; ! 2237: ! 2238: arg0 = SET_SRC (set); ! 2239: ! 2240: if (GET_CODE (arg0) == COMPARE) ! 2241: arg0 = XEXP (arg0, 0); ! 2242: } ! 2243: ! 2244: /* We can reverse this if ARG0 is a CONST_INT or if its mode is ! 2245: not VOIDmode and neither a MODE_CC nor MODE_FLOAT type. */ ! 2246: return (GET_CODE (arg0) == CONST_INT ! 2247: || (GET_MODE (arg0) != VOIDmode ! 2248: && GET_MODE_CLASS (GET_MODE (arg0)) != MODE_CC ! 2249: && GET_MODE_CLASS (GET_MODE (arg0)) != MODE_FLOAT)); ! 2250: } ! 2251: ! 2252: /* Given an rtx-code for a comparison, return the code ! 2253: for the negated comparison. ! 2254: WATCH OUT! reverse_condition is not safe to use on a jump ! 2255: that might be acting on the results of an IEEE floating point comparison, ! 2256: because of the special treatment of non-signaling nans in comparisons. ! 2257: Use can_reverse_comparison_p to be sure. */ ! 2258: ! 2259: enum rtx_code ! 2260: reverse_condition (code) ! 2261: enum rtx_code code; ! 2262: { ! 2263: switch (code) ! 2264: { ! 2265: case EQ: ! 2266: return NE; ! 2267: ! 2268: case NE: ! 2269: return EQ; ! 2270: ! 2271: case GT: ! 2272: return LE; ! 2273: ! 2274: case GE: ! 2275: return LT; ! 2276: ! 2277: case LT: ! 2278: return GE; ! 2279: ! 2280: case LE: ! 2281: return GT; ! 2282: ! 2283: case GTU: ! 2284: return LEU; ! 2285: ! 2286: case GEU: ! 2287: return LTU; ! 2288: ! 2289: case LTU: ! 2290: return GEU; ! 2291: ! 2292: case LEU: ! 2293: return GTU; ! 2294: ! 2295: default: ! 2296: abort (); ! 2297: return UNKNOWN; ! 2298: } ! 2299: } ! 2300: ! 2301: /* Similar, but return the code when two operands of a comparison are swapped. ! 2302: This IS safe for IEEE floating-point. */ ! 2303: ! 2304: enum rtx_code ! 2305: swap_condition (code) ! 2306: enum rtx_code code; ! 2307: { ! 2308: switch (code) ! 2309: { ! 2310: case EQ: ! 2311: case NE: ! 2312: return code; ! 2313: ! 2314: case GT: ! 2315: return LT; ! 2316: ! 2317: case GE: ! 2318: return LE; ! 2319: ! 2320: case LT: ! 2321: return GT; ! 2322: ! 2323: case LE: ! 2324: return GE; ! 2325: ! 2326: case GTU: ! 2327: return LTU; ! 2328: ! 2329: case GEU: ! 2330: return LEU; ! 2331: ! 2332: case LTU: ! 2333: return GTU; ! 2334: ! 2335: case LEU: ! 2336: return GEU; ! 2337: ! 2338: default: ! 2339: abort (); ! 2340: return UNKNOWN; ! 2341: } ! 2342: } ! 2343: ! 2344: /* Given a comparison CODE, return the corresponding unsigned comparison. ! 2345: If CODE is an equality comparison or already an unsigned comparison, ! 2346: CODE is returned. */ ! 2347: ! 2348: enum rtx_code ! 2349: unsigned_condition (code) ! 2350: enum rtx_code code; ! 2351: { ! 2352: switch (code) ! 2353: { ! 2354: case EQ: ! 2355: case NE: ! 2356: case GTU: ! 2357: case GEU: ! 2358: case LTU: ! 2359: case LEU: ! 2360: return code; ! 2361: ! 2362: case GT: ! 2363: return GTU; ! 2364: ! 2365: case GE: ! 2366: return GEU; ! 2367: ! 2368: case LT: ! 2369: return LTU; ! 2370: ! 2371: case LE: ! 2372: return LEU; ! 2373: ! 2374: default: ! 2375: abort (); ! 2376: } ! 2377: } ! 2378: ! 2379: /* Similarly, return the signed version of a comparison. */ ! 2380: ! 2381: enum rtx_code ! 2382: signed_condition (code) ! 2383: enum rtx_code code; ! 2384: { ! 2385: switch (code) ! 2386: { ! 2387: case EQ: ! 2388: case NE: ! 2389: case GT: ! 2390: case GE: ! 2391: case LT: ! 2392: case LE: ! 2393: return code; ! 2394: ! 2395: case GTU: ! 2396: return GT; ! 2397: ! 2398: case GEU: ! 2399: return GE; ! 2400: ! 2401: case LTU: ! 2402: return LT; ! 2403: ! 2404: case LEU: ! 2405: return LE; ! 2406: ! 2407: default: ! 2408: abort (); ! 2409: } ! 2410: } ! 2411: ! 2412: /* Return non-zero if CODE1 is more strict than CODE2, i.e., if the ! 2413: truth of CODE1 implies the truth of CODE2. */ ! 2414: ! 2415: int ! 2416: comparison_dominates_p (code1, code2) ! 2417: enum rtx_code code1, code2; ! 2418: { ! 2419: if (code1 == code2) ! 2420: return 1; ! 2421: ! 2422: switch (code1) ! 2423: { ! 2424: case EQ: ! 2425: if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU) ! 2426: return 1; ! 2427: break; ! 2428: ! 2429: case LT: ! 2430: if (code2 == LE) ! 2431: return 1; ! 2432: break; ! 2433: ! 2434: case GT: ! 2435: if (code2 == GE) ! 2436: return 1; ! 2437: break; ! 2438: ! 2439: case LTU: ! 2440: if (code2 == LEU) ! 2441: return 1; ! 2442: break; ! 2443: ! 2444: case GTU: ! 2445: if (code2 == GEU) ! 2446: return 1; ! 2447: break; ! 2448: } ! 2449: ! 2450: return 0; ! 2451: } ! 2452: ! 2453: /* Return 1 if INSN is an unconditional jump and nothing else. */ ! 2454: ! 2455: int ! 2456: simplejump_p (insn) ! 2457: rtx insn; ! 2458: { ! 2459: return (GET_CODE (insn) == JUMP_INSN ! 2460: && GET_CODE (PATTERN (insn)) == SET ! 2461: && GET_CODE (SET_DEST (PATTERN (insn))) == PC ! 2462: && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF); ! 2463: } ! 2464: ! 2465: /* Return nonzero if INSN is a (possibly) conditional jump ! 2466: and nothing more. */ ! 2467: ! 2468: int ! 2469: condjump_p (insn) ! 2470: rtx insn; ! 2471: { ! 2472: register rtx x = PATTERN (insn); ! 2473: if (GET_CODE (x) != SET) ! 2474: return 0; ! 2475: if (GET_CODE (SET_DEST (x)) != PC) ! 2476: return 0; ! 2477: if (GET_CODE (SET_SRC (x)) == LABEL_REF) ! 2478: return 1; ! 2479: if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE) ! 2480: return 0; ! 2481: if (XEXP (SET_SRC (x), 2) == pc_rtx ! 2482: && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF ! 2483: || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN)) ! 2484: return 1; ! 2485: if (XEXP (SET_SRC (x), 1) == pc_rtx ! 2486: && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF ! 2487: || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN)) ! 2488: return 1; ! 2489: return 0; ! 2490: } ! 2491: ! 2492: /* Return 1 if X is an RTX that does nothing but set the condition codes ! 2493: and CLOBBER or USE registers. ! 2494: Return -1 if X does explicitly set the condition codes, ! 2495: but also does other things. */ ! 2496: ! 2497: int ! 2498: sets_cc0_p (x) ! 2499: rtx x; ! 2500: { ! 2501: #ifdef HAVE_cc0 ! 2502: if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx) ! 2503: return 1; ! 2504: if (GET_CODE (x) == PARALLEL) ! 2505: { ! 2506: int i; ! 2507: int sets_cc0 = 0; ! 2508: int other_things = 0; ! 2509: for (i = XVECLEN (x, 0) - 1; i >= 0; i--) ! 2510: { ! 2511: if (GET_CODE (XVECEXP (x, 0, i)) == SET ! 2512: && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx) ! 2513: sets_cc0 = 1; ! 2514: else if (GET_CODE (XVECEXP (x, 0, i)) == SET) ! 2515: other_things = 1; ! 2516: } ! 2517: return ! sets_cc0 ? 0 : other_things ? -1 : 1; ! 2518: } ! 2519: return 0; ! 2520: #else ! 2521: abort (); ! 2522: #endif ! 2523: } ! 2524: ! 2525: /* Follow any unconditional jump at LABEL; ! 2526: return the ultimate label reached by any such chain of jumps. ! 2527: If LABEL is not followed by a jump, return LABEL. ! 2528: If the chain loops or we can't find end, return LABEL, ! 2529: since that tells caller to avoid changing the insn. ! 2530: ! 2531: If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or ! 2532: a USE or CLOBBER. */ ! 2533: ! 2534: rtx ! 2535: follow_jumps (label) ! 2536: rtx label; ! 2537: { ! 2538: register rtx insn; ! 2539: register rtx next; ! 2540: register rtx value = label; ! 2541: register int depth; ! 2542: ! 2543: for (depth = 0; ! 2544: (depth < 10 ! 2545: && (insn = next_active_insn (value)) != 0 ! 2546: && GET_CODE (insn) == JUMP_INSN ! 2547: && (JUMP_LABEL (insn) != 0 || GET_CODE (PATTERN (insn)) == RETURN) ! 2548: && (next = NEXT_INSN (insn)) ! 2549: && GET_CODE (next) == BARRIER); ! 2550: depth++) ! 2551: { ! 2552: /* Don't chain through the insn that jumps into a loop ! 2553: from outside the loop, ! 2554: since that would create multiple loop entry jumps ! 2555: and prevent loop optimization. */ ! 2556: rtx tem; ! 2557: if (!reload_completed) ! 2558: for (tem = value; tem != insn; tem = NEXT_INSN (tem)) ! 2559: if (GET_CODE (tem) == NOTE ! 2560: && NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG) ! 2561: return value; ! 2562: ! 2563: /* If we have found a cycle, make the insn jump to itself. */ ! 2564: if (JUMP_LABEL (insn) == label) ! 2565: return label; ! 2566: value = JUMP_LABEL (insn); ! 2567: } ! 2568: if (depth == 10) ! 2569: return label; ! 2570: return value; ! 2571: } ! 2572: ! 2573: /* Assuming that field IDX of X is a vector of label_refs, ! 2574: replace each of them by the ultimate label reached by it. ! 2575: Return nonzero if a change is made. ! 2576: If IGNORE_LOOPS is 0, we do not chain across a NOTE_INSN_LOOP_BEG. */ ! 2577: ! 2578: static int ! 2579: tension_vector_labels (x, idx) ! 2580: register rtx x; ! 2581: register int idx; ! 2582: { ! 2583: int changed = 0; ! 2584: register int i; ! 2585: for (i = XVECLEN (x, idx) - 1; i >= 0; i--) ! 2586: { ! 2587: register rtx olabel = XEXP (XVECEXP (x, idx, i), 0); ! 2588: register rtx nlabel = follow_jumps (olabel); ! 2589: if (nlabel && nlabel != olabel) ! 2590: { ! 2591: XEXP (XVECEXP (x, idx, i), 0) = nlabel; ! 2592: ++LABEL_NUSES (nlabel); ! 2593: if (--LABEL_NUSES (olabel) == 0) ! 2594: delete_insn (olabel); ! 2595: changed = 1; ! 2596: } ! 2597: } ! 2598: return changed; ! 2599: } ! 2600: ! 2601: /* Find all CODE_LABELs referred to in X, and increment their use counts. ! 2602: If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced ! 2603: in INSN, then store one of them in JUMP_LABEL (INSN). ! 2604: If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL ! 2605: referenced in INSN, add a REG_LABEL note containing that label to INSN. ! 2606: Also, when there are consecutive labels, canonicalize on the last of them. ! 2607: ! 2608: Note that two labels separated by a loop-beginning note ! 2609: must be kept distinct if we have not yet done loop-optimization, ! 2610: because the gap between them is where loop-optimize ! 2611: will want to move invariant code to. CROSS_JUMP tells us ! 2612: that loop-optimization is done with. ! 2613: ! 2614: Once reload has completed (CROSS_JUMP non-zero), we need not consider ! 2615: two labels distinct if they are separated by only USE or CLOBBER insns. */ ! 2616: ! 2617: static void ! 2618: mark_jump_label (x, insn, cross_jump) ! 2619: register rtx x; ! 2620: rtx insn; ! 2621: int cross_jump; ! 2622: { ! 2623: register RTX_CODE code = GET_CODE (x); ! 2624: register int i; ! 2625: register char *fmt; ! 2626: ! 2627: switch (code) ! 2628: { ! 2629: case PC: ! 2630: case CC0: ! 2631: case REG: ! 2632: case SUBREG: ! 2633: case CONST_INT: ! 2634: case SYMBOL_REF: ! 2635: case CONST_DOUBLE: ! 2636: case CLOBBER: ! 2637: case CALL: ! 2638: return; ! 2639: ! 2640: case LABEL_REF: ! 2641: { ! 2642: register rtx label = XEXP (x, 0); ! 2643: register rtx next; ! 2644: if (GET_CODE (label) != CODE_LABEL) ! 2645: abort (); ! 2646: /* If there are other labels following this one, ! 2647: replace it with the last of the consecutive labels. */ ! 2648: for (next = NEXT_INSN (label); next; next = NEXT_INSN (next)) ! 2649: { ! 2650: if (GET_CODE (next) == CODE_LABEL) ! 2651: label = next; ! 2652: else if (cross_jump && GET_CODE (next) == INSN ! 2653: && (GET_CODE (PATTERN (next)) == USE ! 2654: || GET_CODE (PATTERN (next)) == CLOBBER)) ! 2655: continue; ! 2656: else if (GET_CODE (next) != NOTE) ! 2657: break; ! 2658: else if (! cross_jump ! 2659: && (NOTE_LINE_NUMBER (next) == NOTE_INSN_LOOP_BEG ! 2660: || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END)) ! 2661: break; ! 2662: } ! 2663: XEXP (x, 0) = label; ! 2664: ++LABEL_NUSES (label); ! 2665: if (insn) ! 2666: { ! 2667: if (GET_CODE (insn) == JUMP_INSN) ! 2668: JUMP_LABEL (insn) = label; ! 2669: else if (! find_reg_note (insn, REG_LABEL, 0)) ! 2670: { ! 2671: rtx next = next_real_insn (label); ! 2672: /* Don't record labels that refer to dispatch tables. ! 2673: This is not necessary, since the tablejump ! 2674: references the same label. ! 2675: And if we did record them, flow.c would make worse code. */ ! 2676: if (next == 0 ! 2677: || ! (GET_CODE (next) == JUMP_INSN ! 2678: && (GET_CODE (PATTERN (next)) == ADDR_VEC ! 2679: || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))) ! 2680: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label, ! 2681: REG_NOTES (insn)); ! 2682: } ! 2683: } ! 2684: return; ! 2685: } ! 2686: ! 2687: /* Do walk the labels in a vector, but not the first operand of an ! 2688: ADDR_DIFF_VEC. Don't set the JUMP_LABEL of a vector. */ ! 2689: case ADDR_VEC: ! 2690: case ADDR_DIFF_VEC: ! 2691: { ! 2692: int eltnum = code == ADDR_DIFF_VEC ? 1 : 0; ! 2693: ! 2694: for (i = 0; i < XVECLEN (x, eltnum); i++) ! 2695: mark_jump_label (XVECEXP (x, eltnum, i), 0, cross_jump); ! 2696: return; ! 2697: } ! 2698: } ! 2699: ! 2700: fmt = GET_RTX_FORMAT (code); ! 2701: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 2702: { ! 2703: if (fmt[i] == 'e') ! 2704: mark_jump_label (XEXP (x, i), insn, cross_jump); ! 2705: else if (fmt[i] == 'E') ! 2706: { ! 2707: register int j; ! 2708: for (j = 0; j < XVECLEN (x, i); j++) ! 2709: mark_jump_label (XVECEXP (x, i, j), insn, cross_jump); ! 2710: } ! 2711: } ! 2712: } ! 2713: ! 2714: /* If all INSN does is set the pc, delete it, ! 2715: and delete the insn that set the condition codes for it ! 2716: if that's what the previous thing was. */ ! 2717: ! 2718: void ! 2719: delete_jump (insn) ! 2720: rtx insn; ! 2721: { ! 2722: register rtx x = PATTERN (insn); ! 2723: register rtx prev; ! 2724: ! 2725: if (GET_CODE (x) == SET ! 2726: && GET_CODE (SET_DEST (x)) == PC) ! 2727: { ! 2728: prev = prev_nonnote_insn (insn); ! 2729: #ifdef HAVE_cc0 ! 2730: /* We assume that at this stage ! 2731: CC's are always set explicitly ! 2732: and always immediately before the jump that ! 2733: will use them. So if the previous insn ! 2734: exists to set the CC's, delete it ! 2735: (unless it performs auto-increments, etc.). */ ! 2736: if (prev && GET_CODE (prev) == INSN ! 2737: && sets_cc0_p (PATTERN (prev))) ! 2738: { ! 2739: if (sets_cc0_p (PATTERN (prev)) > 0 ! 2740: && !FIND_REG_INC_NOTE (prev, 0)) ! 2741: delete_insn (prev); ! 2742: else ! 2743: /* Otherwise, show that cc0 won't be used. */ ! 2744: REG_NOTES (prev) = gen_rtx (EXPR_LIST, REG_UNUSED, ! 2745: cc0_rtx, REG_NOTES (prev)); ! 2746: } ! 2747: #else ! 2748: { ! 2749: rtx note; ! 2750: ! 2751: /* If we are running before flow.c, we need do nothing since flow.c ! 2752: will delete the set of the condition code if it is dead. We also ! 2753: can't know if the register being used as the condition code is ! 2754: dead or not at this point. ! 2755: ! 2756: Otherwise, look at all our REG_DEAD notes. If a previous insn ! 2757: does nothing other than set a register that dies in this jump, ! 2758: we can delete the insn. */ ! 2759: ! 2760: for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) ! 2761: { ! 2762: rtx our_prev; ! 2763: ! 2764: if (REG_NOTE_KIND (note) != REG_DEAD ! 2765: /* Verify that the REG_NOTE has a legal value. */ ! 2766: || GET_CODE (XEXP (note, 0)) != REG) ! 2767: continue; ! 2768: ! 2769: for (our_prev = prev_nonnote_insn (insn); ! 2770: our_prev && GET_CODE (our_prev) == INSN; ! 2771: our_prev = prev_nonnote_insn (our_prev)) ! 2772: { ! 2773: /* If we reach a SEQUENCE, it is too complex to try to ! 2774: do anything with it, so give up. */ ! 2775: if (GET_CODE (PATTERN (our_prev)) == SEQUENCE) ! 2776: break; ! 2777: ! 2778: if (GET_CODE (PATTERN (our_prev)) == USE ! 2779: && GET_CODE (XEXP (PATTERN (our_prev), 0)) == INSN) ! 2780: /* reorg creates USEs that look like this. We leave them ! 2781: alone because reorg needs them for its own purposes. */ ! 2782: break; ! 2783: ! 2784: if (reg_set_p (XEXP (note, 0), PATTERN (our_prev))) ! 2785: { ! 2786: if (FIND_REG_INC_NOTE (our_prev, 0)) ! 2787: break; ! 2788: ! 2789: if (GET_CODE (PATTERN (our_prev)) == PARALLEL) ! 2790: { ! 2791: /* If we find a SET of something else, we can't ! 2792: delete the insn. */ ! 2793: ! 2794: int i; ! 2795: ! 2796: for (i = 0; i < XVECLEN (PATTERN (our_prev), 0); i++) ! 2797: { ! 2798: rtx part = XVECEXP (PATTERN (our_prev), 0, i); ! 2799: ! 2800: if (GET_CODE (part) == SET ! 2801: && SET_DEST (part) != XEXP (note, 0)) ! 2802: break; ! 2803: } ! 2804: ! 2805: if (i == XVECLEN (PATTERN (our_prev), 0)) ! 2806: delete_insn (our_prev); ! 2807: } ! 2808: else if (GET_CODE (PATTERN (our_prev)) == SET ! 2809: && SET_DEST (PATTERN (our_prev)) == XEXP (note, 0)) ! 2810: delete_insn (our_prev); ! 2811: ! 2812: break; ! 2813: } ! 2814: ! 2815: /* If OUR_PREV references the register that dies here, ! 2816: it is an additional use. Hence any prior SET isn't ! 2817: dead. */ ! 2818: if (reg_overlap_mentioned_p (XEXP (note, 0), ! 2819: PATTERN (our_prev))) ! 2820: break; ! 2821: } ! 2822: } ! 2823: } ! 2824: #endif ! 2825: /* Now delete the jump insn itself. */ ! 2826: delete_insn (insn); ! 2827: } ! 2828: } ! 2829: ! 2830: /* Delete insn INSN from the chain of insns and update label ref counts. ! 2831: May delete some following insns as a consequence; may even delete ! 2832: a label elsewhere and insns that follow it. ! 2833: ! 2834: Returns the first insn after INSN that was not deleted. */ ! 2835: ! 2836: rtx ! 2837: delete_insn (insn) ! 2838: register rtx insn; ! 2839: { ! 2840: register rtx next = NEXT_INSN (insn); ! 2841: register rtx prev = PREV_INSN (insn); ! 2842: ! 2843: while (next && INSN_DELETED_P (next)) ! 2844: next = NEXT_INSN (next); ! 2845: ! 2846: /* This insn is already deleted => return first following nondeleted. */ ! 2847: if (INSN_DELETED_P (insn)) ! 2848: return next; ! 2849: ! 2850: /* Mark this insn as deleted. */ ! 2851: ! 2852: INSN_DELETED_P (insn) = 1; ! 2853: ! 2854: /* If this is an unconditional jump, delete it from the jump chain. */ ! 2855: if (simplejump_p (insn)) ! 2856: delete_from_jump_chain (insn); ! 2857: ! 2858: /* If instruction is followed by a barrier, ! 2859: delete the barrier too. */ ! 2860: ! 2861: if (next != 0 && GET_CODE (next) == BARRIER) ! 2862: { ! 2863: INSN_DELETED_P (next) = 1; ! 2864: next = NEXT_INSN (next); ! 2865: } ! 2866: ! 2867: /* Patch out INSN (and the barrier if any) */ ! 2868: ! 2869: if (optimize) ! 2870: { ! 2871: if (prev) ! 2872: { ! 2873: NEXT_INSN (prev) = next; ! 2874: if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE) ! 2875: NEXT_INSN (XVECEXP (PATTERN (prev), 0, ! 2876: XVECLEN (PATTERN (prev), 0) - 1)) = next; ! 2877: } ! 2878: ! 2879: if (next) ! 2880: { ! 2881: PREV_INSN (next) = prev; ! 2882: if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE) ! 2883: PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev; ! 2884: } ! 2885: ! 2886: if (prev && NEXT_INSN (prev) == 0) ! 2887: set_last_insn (prev); ! 2888: } ! 2889: ! 2890: /* If deleting a jump, decrement the count of the label, ! 2891: and delete the label if it is now unused. */ ! 2892: ! 2893: if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn)) ! 2894: if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0) ! 2895: { ! 2896: /* This can delete NEXT or PREV, ! 2897: either directly if NEXT is JUMP_LABEL (INSN), ! 2898: or indirectly through more levels of jumps. */ ! 2899: delete_insn (JUMP_LABEL (insn)); ! 2900: /* I feel a little doubtful about this loop, ! 2901: but I see no clean and sure alternative way ! 2902: to find the first insn after INSN that is not now deleted. ! 2903: I hope this works. */ ! 2904: while (next && INSN_DELETED_P (next)) ! 2905: next = NEXT_INSN (next); ! 2906: return next; ! 2907: } ! 2908: ! 2909: while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE)) ! 2910: prev = PREV_INSN (prev); ! 2911: ! 2912: /* If INSN was a label and a dispatch table follows it, ! 2913: delete the dispatch table. The tablejump must have gone already. ! 2914: It isn't useful to fall through into a table. */ ! 2915: ! 2916: if (GET_CODE (insn) == CODE_LABEL ! 2917: && NEXT_INSN (insn) != 0 ! 2918: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN ! 2919: && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC ! 2920: || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC)) ! 2921: next = delete_insn (NEXT_INSN (insn)); ! 2922: ! 2923: /* If INSN was a label, delete insns following it if now unreachable. */ ! 2924: ! 2925: if (GET_CODE (insn) == CODE_LABEL && prev ! 2926: && GET_CODE (prev) == BARRIER) ! 2927: { ! 2928: register RTX_CODE code; ! 2929: while (next != 0 ! 2930: && ((code = GET_CODE (next)) == INSN ! 2931: || code == JUMP_INSN || code == CALL_INSN ! 2932: || code == NOTE)) ! 2933: { ! 2934: if (code == NOTE ! 2935: && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END) ! 2936: next = NEXT_INSN (next); ! 2937: else ! 2938: /* Note: if this deletes a jump, it can cause more ! 2939: deletion of unreachable code, after a different label. ! 2940: As long as the value from this recursive call is correct, ! 2941: this invocation functions correctly. */ ! 2942: next = delete_insn (next); ! 2943: } ! 2944: } ! 2945: ! 2946: return next; ! 2947: } ! 2948: ! 2949: /* Advance from INSN till reaching something not deleted ! 2950: then return that. May return INSN itself. */ ! 2951: ! 2952: rtx ! 2953: next_nondeleted_insn (insn) ! 2954: rtx insn; ! 2955: { ! 2956: while (INSN_DELETED_P (insn)) ! 2957: insn = NEXT_INSN (insn); ! 2958: return insn; ! 2959: } ! 2960: ! 2961: /* Delete a range of insns from FROM to TO, inclusive. ! 2962: This is for the sake of peephole optimization, so assume ! 2963: that whatever these insns do will still be done by a new ! 2964: peephole insn that will replace them. */ ! 2965: ! 2966: void ! 2967: delete_for_peephole (from, to) ! 2968: register rtx from, to; ! 2969: { ! 2970: register rtx insn = from; ! 2971: ! 2972: while (1) ! 2973: { ! 2974: register rtx next = NEXT_INSN (insn); ! 2975: register rtx prev = PREV_INSN (insn); ! 2976: ! 2977: if (GET_CODE (insn) != NOTE) ! 2978: { ! 2979: INSN_DELETED_P (insn) = 1; ! 2980: ! 2981: /* Patch this insn out of the chain. */ ! 2982: /* We don't do this all at once, because we ! 2983: must preserve all NOTEs. */ ! 2984: if (prev) ! 2985: NEXT_INSN (prev) = next; ! 2986: ! 2987: if (next) ! 2988: PREV_INSN (next) = prev; ! 2989: } ! 2990: ! 2991: if (insn == to) ! 2992: break; ! 2993: insn = next; ! 2994: } ! 2995: ! 2996: /* Note that if TO is an unconditional jump ! 2997: we *do not* delete the BARRIER that follows, ! 2998: since the peephole that replaces this sequence ! 2999: is also an unconditional jump in that case. */ ! 3000: } ! 3001: ! 3002: /* Invert the condition of the jump JUMP, and make it jump ! 3003: to label NLABEL instead of where it jumps now. */ ! 3004: ! 3005: int ! 3006: invert_jump (jump, nlabel) ! 3007: rtx jump, nlabel; ! 3008: { ! 3009: register rtx olabel = JUMP_LABEL (jump); ! 3010: ! 3011: /* We have to either invert the condition and change the label or ! 3012: do neither. Either operation could fail. We first try to invert ! 3013: the jump. If that succeeds, we try changing the label. If that fails, ! 3014: we invert the jump back to what it was. */ ! 3015: ! 3016: if (! invert_exp (PATTERN (jump), jump)) ! 3017: return 0; ! 3018: ! 3019: if (redirect_jump (jump, nlabel)) ! 3020: return 1; ! 3021: ! 3022: if (! invert_exp (PATTERN (jump), jump)) ! 3023: /* This should just be putting it back the way it was. */ ! 3024: abort (); ! 3025: ! 3026: return 0; ! 3027: } ! 3028: ! 3029: /* Invert the jump condition of rtx X contained in jump insn, INSN. ! 3030: ! 3031: Return 1 if we can do so, 0 if we cannot find a way to do so that ! 3032: matches a pattern. */ ! 3033: ! 3034: static int ! 3035: invert_exp (x, insn) ! 3036: rtx x; ! 3037: rtx insn; ! 3038: { ! 3039: register RTX_CODE code; ! 3040: register int i; ! 3041: register char *fmt; ! 3042: ! 3043: code = GET_CODE (x); ! 3044: ! 3045: if (code == IF_THEN_ELSE) ! 3046: { ! 3047: register rtx comp = XEXP (x, 0); ! 3048: register rtx tem; ! 3049: ! 3050: /* We can do this in two ways: The preferable way, which can only ! 3051: be done if this is not an integer comparison, is to reverse ! 3052: the comparison code. Otherwise, swap the THEN-part and ELSE-part ! 3053: of the IF_THEN_ELSE. If we can't do either, fail. */ ! 3054: ! 3055: if (can_reverse_comparison_p (comp, insn) ! 3056: && validate_change (insn, &XEXP (x, 0), ! 3057: gen_rtx (reverse_condition (GET_CODE (comp)), ! 3058: GET_MODE (comp), XEXP (comp, 0), ! 3059: XEXP (comp, 1)), 0)) ! 3060: return 1; ! 3061: ! 3062: tem = XEXP (x, 1); ! 3063: validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1); ! 3064: validate_change (insn, &XEXP (x, 2), tem, 1); ! 3065: return apply_change_group (); ! 3066: } ! 3067: ! 3068: fmt = GET_RTX_FORMAT (code); ! 3069: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 3070: { ! 3071: if (fmt[i] == 'e') ! 3072: if (! invert_exp (XEXP (x, i), insn)) ! 3073: return 0; ! 3074: if (fmt[i] == 'E') ! 3075: { ! 3076: register int j; ! 3077: for (j = 0; j < XVECLEN (x, i); j++) ! 3078: if (!invert_exp (XVECEXP (x, i, j), insn)) ! 3079: return 0; ! 3080: } ! 3081: } ! 3082: ! 3083: return 1; ! 3084: } ! 3085: ! 3086: /* Make jump JUMP jump to label NLABEL instead of where it jumps now. ! 3087: If the old jump target label is unused as a result, ! 3088: it and the code following it may be deleted. ! 3089: ! 3090: If NLABEL is zero, we are to turn the jump into a (possibly conditional) ! 3091: RETURN insn. ! 3092: ! 3093: The return value will be 1 if the change was made, 0 if it wasn't (this ! 3094: can only occur for NLABEL == 0). */ ! 3095: ! 3096: int ! 3097: redirect_jump (jump, nlabel) ! 3098: rtx jump, nlabel; ! 3099: { ! 3100: register rtx olabel = JUMP_LABEL (jump); ! 3101: ! 3102: if (nlabel == olabel) ! 3103: return 1; ! 3104: ! 3105: if (! redirect_exp (&PATTERN (jump), olabel, nlabel, jump)) ! 3106: return 0; ! 3107: ! 3108: /* If this is an unconditional branch, delete it from the jump_chain of ! 3109: OLABEL and add it to the jump_chain of NLABEL (assuming both labels ! 3110: have UID's in range and JUMP_CHAIN is valid). */ ! 3111: if (jump_chain && (simplejump_p (jump) ! 3112: || GET_CODE (PATTERN (jump)) == RETURN)) ! 3113: { ! 3114: int label_index = nlabel ? INSN_UID (nlabel) : 0; ! 3115: ! 3116: delete_from_jump_chain (jump); ! 3117: if (label_index < max_jump_chain ! 3118: && INSN_UID (jump) < max_jump_chain) ! 3119: { ! 3120: jump_chain[INSN_UID (jump)] = jump_chain[label_index]; ! 3121: jump_chain[label_index] = jump; ! 3122: } ! 3123: } ! 3124: ! 3125: JUMP_LABEL (jump) = nlabel; ! 3126: if (nlabel) ! 3127: ++LABEL_NUSES (nlabel); ! 3128: ! 3129: if (olabel && --LABEL_NUSES (olabel) == 0) ! 3130: delete_insn (olabel); ! 3131: ! 3132: return 1; ! 3133: } ! 3134: ! 3135: /* Delete the instruction JUMP from any jump chain it might be on. */ ! 3136: ! 3137: static void ! 3138: delete_from_jump_chain (jump) ! 3139: rtx jump; ! 3140: { ! 3141: int index; ! 3142: rtx olabel = JUMP_LABEL (jump); ! 3143: ! 3144: /* Handle unconditional jumps. */ ! 3145: if (jump_chain && olabel != 0 ! 3146: && INSN_UID (olabel) < max_jump_chain ! 3147: && simplejump_p (jump)) ! 3148: index = INSN_UID (olabel); ! 3149: /* Handle return insns. */ ! 3150: else if (jump_chain && GET_CODE (PATTERN (jump)) == RETURN) ! 3151: index = 0; ! 3152: else return; ! 3153: ! 3154: if (jump_chain[index] == jump) ! 3155: jump_chain[index] = jump_chain[INSN_UID (jump)]; ! 3156: else ! 3157: { ! 3158: rtx insn; ! 3159: ! 3160: for (insn = jump_chain[index]; ! 3161: insn != 0; ! 3162: insn = jump_chain[INSN_UID (insn)]) ! 3163: if (jump_chain[INSN_UID (insn)] == jump) ! 3164: { ! 3165: jump_chain[INSN_UID (insn)] = jump_chain[INSN_UID (jump)]; ! 3166: break; ! 3167: } ! 3168: } ! 3169: } ! 3170: ! 3171: /* If NLABEL is nonzero, throughout the rtx at LOC, ! 3172: alter (LABEL_REF OLABEL) to (LABEL_REF NLABEL). If OLABEL is ! 3173: zero, alter (RETURN) to (LABEL_REF NLABEL). ! 3174: ! 3175: If NLABEL is zero, alter (LABEL_REF OLABEL) to (RETURN) and check ! 3176: validity with validate_change. Convert (set (pc) (label_ref olabel)) ! 3177: to (return). ! 3178: ! 3179: Return 0 if we found a change we would like to make but it is invalid. ! 3180: Otherwise, return 1. */ ! 3181: ! 3182: static int ! 3183: redirect_exp (loc, olabel, nlabel, insn) ! 3184: rtx *loc; ! 3185: rtx olabel, nlabel; ! 3186: rtx insn; ! 3187: { ! 3188: register rtx x = *loc; ! 3189: register RTX_CODE code = GET_CODE (x); ! 3190: register int i; ! 3191: register char *fmt; ! 3192: ! 3193: if (code == LABEL_REF) ! 3194: { ! 3195: if (XEXP (x, 0) == olabel) ! 3196: { ! 3197: if (nlabel) ! 3198: XEXP (x, 0) = nlabel; ! 3199: else ! 3200: return validate_change (insn, loc, gen_rtx (RETURN, VOIDmode), 0); ! 3201: return 1; ! 3202: } ! 3203: } ! 3204: else if (code == RETURN && olabel == 0) ! 3205: { ! 3206: x = gen_rtx (LABEL_REF, VOIDmode, nlabel); ! 3207: if (loc == &PATTERN (insn)) ! 3208: x = gen_rtx (SET, VOIDmode, pc_rtx, x); ! 3209: return validate_change (insn, loc, x, 0); ! 3210: } ! 3211: ! 3212: if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx ! 3213: && GET_CODE (SET_SRC (x)) == LABEL_REF ! 3214: && XEXP (SET_SRC (x), 0) == olabel) ! 3215: return validate_change (insn, loc, gen_rtx (RETURN, VOIDmode), 0); ! 3216: ! 3217: fmt = GET_RTX_FORMAT (code); ! 3218: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 3219: { ! 3220: if (fmt[i] == 'e') ! 3221: if (! redirect_exp (&XEXP (x, i), olabel, nlabel, insn)) ! 3222: return 0; ! 3223: if (fmt[i] == 'E') ! 3224: { ! 3225: register int j; ! 3226: for (j = 0; j < XVECLEN (x, i); j++) ! 3227: if (! redirect_exp (&XVECEXP (x, i, j), olabel, nlabel, insn)) ! 3228: return 0; ! 3229: } ! 3230: } ! 3231: ! 3232: return 1; ! 3233: } ! 3234: ! 3235: /* Make jump JUMP jump to label NLABEL, assuming it used to be a tablejump. ! 3236: ! 3237: If the old jump target label (before the dispatch table) becomes unused, ! 3238: it and the dispatch table may be deleted. In that case, find the insn ! 3239: before the jump references that label and delete it and logical sucessors ! 3240: too. */ ! 3241: ! 3242: void ! 3243: redirect_tablejump (jump, nlabel) ! 3244: rtx jump, nlabel; ! 3245: { ! 3246: register rtx olabel = JUMP_LABEL (jump); ! 3247: ! 3248: /* Add this jump to the jump_chain of NLABEL. */ ! 3249: if (jump_chain && INSN_UID (nlabel) < max_jump_chain ! 3250: && INSN_UID (jump) < max_jump_chain) ! 3251: { ! 3252: jump_chain[INSN_UID (jump)] = jump_chain[INSN_UID (nlabel)]; ! 3253: jump_chain[INSN_UID (nlabel)] = jump; ! 3254: } ! 3255: ! 3256: PATTERN (jump) = gen_jump (nlabel); ! 3257: JUMP_LABEL (jump) = nlabel; ! 3258: ++LABEL_NUSES (nlabel); ! 3259: INSN_CODE (jump) = -1; ! 3260: ! 3261: if (--LABEL_NUSES (olabel) == 0) ! 3262: { ! 3263: delete_labelref_insn (jump, olabel, 0); ! 3264: delete_insn (olabel); ! 3265: } ! 3266: } ! 3267: ! 3268: /* Find the insn referencing LABEL that is a logical predecessor of INSN. ! 3269: If we found one, delete it and then delete this insn if DELETE_THIS is ! 3270: non-zero. Return non-zero if INSN or a predecessor references LABEL. */ ! 3271: ! 3272: static int ! 3273: delete_labelref_insn (insn, label, delete_this) ! 3274: rtx insn, label; ! 3275: int delete_this; ! 3276: { ! 3277: int deleted = 0; ! 3278: rtx link; ! 3279: ! 3280: if (GET_CODE (insn) != NOTE ! 3281: && reg_mentioned_p (label, PATTERN (insn))) ! 3282: { ! 3283: if (delete_this) ! 3284: { ! 3285: delete_insn (insn); ! 3286: deleted = 1; ! 3287: } ! 3288: else ! 3289: return 1; ! 3290: } ! 3291: ! 3292: for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) ! 3293: if (delete_labelref_insn (XEXP (link, 0), label, 1)) ! 3294: { ! 3295: if (delete_this) ! 3296: { ! 3297: delete_insn (insn); ! 3298: deleted = 1; ! 3299: } ! 3300: else ! 3301: return 1; ! 3302: } ! 3303: ! 3304: return deleted; ! 3305: } ! 3306: ! 3307: /* Like rtx_equal_p except that it considers two REGs as equal ! 3308: if they renumber to the same value. */ ! 3309: ! 3310: int ! 3311: rtx_renumbered_equal_p (x, y) ! 3312: rtx x, y; ! 3313: { ! 3314: register int i; ! 3315: register RTX_CODE code = GET_CODE (x); ! 3316: register char *fmt; ! 3317: ! 3318: if (x == y) ! 3319: return 1; ! 3320: if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)) ! 3321: && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG ! 3322: && GET_CODE (SUBREG_REG (y)) == REG))) ! 3323: { ! 3324: register int j; ! 3325: ! 3326: if (GET_MODE (x) != GET_MODE (y)) ! 3327: return 0; ! 3328: ! 3329: /* If we haven't done any renumbering, don't ! 3330: make any assumptions. */ ! 3331: if (reg_renumber == 0) ! 3332: return rtx_equal_p (x, y); ! 3333: ! 3334: if (code == SUBREG) ! 3335: { ! 3336: i = REGNO (SUBREG_REG (x)); ! 3337: if (reg_renumber[i] >= 0) ! 3338: i = reg_renumber[i]; ! 3339: i += SUBREG_WORD (x); ! 3340: } ! 3341: else ! 3342: { ! 3343: i = REGNO (x); ! 3344: if (reg_renumber[i] >= 0) ! 3345: i = reg_renumber[i]; ! 3346: } ! 3347: if (GET_CODE (y) == SUBREG) ! 3348: { ! 3349: j = REGNO (SUBREG_REG (y)); ! 3350: if (reg_renumber[j] >= 0) ! 3351: j = reg_renumber[j]; ! 3352: j += SUBREG_WORD (y); ! 3353: } ! 3354: else ! 3355: { ! 3356: j = REGNO (y); ! 3357: if (reg_renumber[j] >= 0) ! 3358: j = reg_renumber[j]; ! 3359: } ! 3360: return i == j; ! 3361: } ! 3362: /* Now we have disposed of all the cases ! 3363: in which different rtx codes can match. */ ! 3364: if (code != GET_CODE (y)) ! 3365: return 0; ! 3366: switch (code) ! 3367: { ! 3368: case PC: ! 3369: case CC0: ! 3370: case ADDR_VEC: ! 3371: case ADDR_DIFF_VEC: ! 3372: return 0; ! 3373: ! 3374: case CONST_INT: ! 3375: return XINT (x, 0) == XINT (y, 0); ! 3376: ! 3377: case LABEL_REF: ! 3378: /* Two label-refs are equivalent if they point at labels ! 3379: in the same position in the instruction stream. */ ! 3380: return (next_real_insn (XEXP (x, 0)) ! 3381: == next_real_insn (XEXP (y, 0))); ! 3382: ! 3383: case SYMBOL_REF: ! 3384: return XSTR (x, 0) == XSTR (y, 0); ! 3385: } ! 3386: ! 3387: /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */ ! 3388: ! 3389: if (GET_MODE (x) != GET_MODE (y)) ! 3390: return 0; ! 3391: ! 3392: /* Compare the elements. If any pair of corresponding elements ! 3393: fail to match, return 0 for the whole things. */ ! 3394: ! 3395: fmt = GET_RTX_FORMAT (code); ! 3396: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 3397: { ! 3398: register int j; ! 3399: switch (fmt[i]) ! 3400: { ! 3401: case 'i': ! 3402: if (XINT (x, i) != XINT (y, i)) ! 3403: return 0; ! 3404: break; ! 3405: ! 3406: case 's': ! 3407: if (strcmp (XSTR (x, i), XSTR (y, i))) ! 3408: return 0; ! 3409: break; ! 3410: ! 3411: case 'e': ! 3412: if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i))) ! 3413: return 0; ! 3414: break; ! 3415: ! 3416: case 'u': ! 3417: if (XEXP (x, i) != XEXP (y, i)) ! 3418: return 0; ! 3419: /* fall through. */ ! 3420: case '0': ! 3421: break; ! 3422: ! 3423: case 'E': ! 3424: if (XVECLEN (x, i) != XVECLEN (y, i)) ! 3425: return 0; ! 3426: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 3427: if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j))) ! 3428: return 0; ! 3429: break; ! 3430: ! 3431: default: ! 3432: abort (); ! 3433: } ! 3434: } ! 3435: return 1; ! 3436: } ! 3437: ! 3438: /* If X is a hard register or equivalent to one or a subregister of one, ! 3439: return the hard register number. If X is a pseudo register that was not ! 3440: assigned a hard register, return the pseudo register number. Otherwise, ! 3441: return -1. Any rtx is valid for X. */ ! 3442: ! 3443: int ! 3444: true_regnum (x) ! 3445: rtx x; ! 3446: { ! 3447: if (GET_CODE (x) == REG) ! 3448: { ! 3449: if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0) ! 3450: return reg_renumber[REGNO (x)]; ! 3451: return REGNO (x); ! 3452: } ! 3453: if (GET_CODE (x) == SUBREG) ! 3454: { ! 3455: int base = true_regnum (SUBREG_REG (x)); ! 3456: if (base >= 0 && base < FIRST_PSEUDO_REGISTER) ! 3457: return SUBREG_WORD (x) + base; ! 3458: } ! 3459: return -1; ! 3460: } ! 3461: ! 3462: /* Optimize code of the form: ! 3463: ! 3464: for (x = a[i]; x; ...) ! 3465: ... ! 3466: for (x = a[i]; x; ...) ! 3467: ... ! 3468: foo: ! 3469: ! 3470: Loop optimize will change the above code into ! 3471: ! 3472: if (x = a[i]) ! 3473: for (;;) ! 3474: { ...; if (! (x = ...)) break; } ! 3475: if (x = a[i]) ! 3476: for (;;) ! 3477: { ...; if (! (x = ...)) break; } ! 3478: foo: ! 3479: ! 3480: In general, if the first test fails, the program can branch ! 3481: directly to `foo' and skip the second try which is doomed to fail. ! 3482: We run this after loop optimization and before flow analysis. */ ! 3483: ! 3484: /* When comparing the insn patterns, we track the fact that different ! 3485: pseudo-register numbers may have been used in each computation. ! 3486: The following array stores an equivalence -- same_regs[I] == J means ! 3487: that pseudo register I was used in the first set of tests in a context ! 3488: where J was used in the second set. We also count the number of such ! 3489: pending equivalences. If nonzero, the expressions really aren't the ! 3490: same. */ ! 3491: ! 3492: static short *same_regs; ! 3493: ! 3494: static int num_same_regs; ! 3495: ! 3496: /* Track any registers modified between the target of the first jump and ! 3497: the second jump. They never compare equal. */ ! 3498: ! 3499: static char *modified_regs; ! 3500: ! 3501: /* Record if memory was modified. */ ! 3502: ! 3503: static int modified_mem; ! 3504: ! 3505: /* Called via note_stores on each insn between the target of the first ! 3506: branch and the second branch. It marks any changed registers. */ ! 3507: ! 3508: static void ! 3509: mark_modified_reg (dest, x) ! 3510: rtx dest; ! 3511: rtx x; ! 3512: { ! 3513: int regno, i; ! 3514: ! 3515: if (GET_CODE (dest) == SUBREG) ! 3516: dest = SUBREG_REG (dest); ! 3517: ! 3518: if (GET_CODE (dest) == MEM) ! 3519: modified_mem = 1; ! 3520: ! 3521: if (GET_CODE (dest) != REG) ! 3522: return; ! 3523: ! 3524: regno = REGNO (dest); ! 3525: if (regno >= FIRST_PSEUDO_REGISTER) ! 3526: modified_regs[regno] = 1; ! 3527: else ! 3528: for (i = 0; i < HARD_REGNO_NREGS (regno, GET_MODE (dest)); i++) ! 3529: modified_regs[regno + i] = 1; ! 3530: } ! 3531: ! 3532: /* F is the first insn in the chain of insns. */ ! 3533: ! 3534: void ! 3535: thread_jumps (f, max_reg, verbose) ! 3536: rtx f; ! 3537: int max_reg; ! 3538: int verbose; ! 3539: { ! 3540: /* Basic algorithm is to find a conditional branch, ! 3541: the label it may branch to, and the branch after ! 3542: that label. If the two branches test the same condition, ! 3543: walk back from both branch paths until the insn patterns ! 3544: differ, or code labels are hit. If we make it back to ! 3545: the target of the first branch, then we know that the first branch ! 3546: will either always succeed or always fail depending on the relative ! 3547: senses of the two branches. So adjust the first branch accordingly ! 3548: in this case. */ ! 3549: ! 3550: rtx label, b1, b2, t1, t2; ! 3551: enum rtx_code code1, code2; ! 3552: rtx b1op0, b1op1, b2op0, b2op1; ! 3553: int changed = 1; ! 3554: int i; ! 3555: short *all_reset; ! 3556: ! 3557: /* Allocate register tables and quick-reset table. */ ! 3558: modified_regs = (char *) alloca (max_reg * sizeof (char)); ! 3559: same_regs = (short *) alloca (max_reg * sizeof (short)); ! 3560: all_reset = (short *) alloca (max_reg * sizeof (short)); ! 3561: for (i = 0; i < max_reg; i++) ! 3562: all_reset[i] = -1; ! 3563: ! 3564: while (changed) ! 3565: { ! 3566: changed = 0; ! 3567: ! 3568: for (b1 = f; b1; b1 = NEXT_INSN (b1)) ! 3569: { ! 3570: /* Get to a candidate branch insn. */ ! 3571: if (GET_CODE (b1) != JUMP_INSN ! 3572: || ! condjump_p (b1) || simplejump_p (b1) ! 3573: || JUMP_LABEL (b1) == 0) ! 3574: continue; ! 3575: ! 3576: bzero (modified_regs, max_reg * sizeof (char)); ! 3577: modified_mem = 0; ! 3578: ! 3579: bcopy (all_reset, same_regs, max_reg * sizeof (short)); ! 3580: num_same_regs = 0; ! 3581: ! 3582: label = JUMP_LABEL (b1); ! 3583: ! 3584: /* Look for a branch after the target. Record any registers and ! 3585: memory modified between the target and the branch. Stop when we ! 3586: get to a label since we can't know what was changed there. */ ! 3587: for (b2 = NEXT_INSN (label); b2; b2 = NEXT_INSN (b2)) ! 3588: { ! 3589: if (GET_CODE (b2) == CODE_LABEL) ! 3590: break; ! 3591: ! 3592: else if (GET_CODE (b2) == JUMP_INSN) ! 3593: { ! 3594: /* If this is an unconditional jump and is the only use of ! 3595: its target label, we can follow it. */ ! 3596: if (simplejump_p (b2) ! 3597: && JUMP_LABEL (b2) != 0 ! 3598: && LABEL_NUSES (JUMP_LABEL (b2)) == 1) ! 3599: { ! 3600: b2 = JUMP_LABEL (b2); ! 3601: continue; ! 3602: } ! 3603: else ! 3604: break; ! 3605: } ! 3606: ! 3607: if (GET_CODE (b2) != CALL_INSN && GET_CODE (b2) != INSN) ! 3608: continue; ! 3609: ! 3610: if (GET_CODE (b2) == CALL_INSN) ! 3611: { ! 3612: modified_mem = 1; ! 3613: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 3614: if (call_used_regs[i] && ! fixed_regs[i] ! 3615: && i != STACK_POINTER_REGNUM ! 3616: && i != FRAME_POINTER_REGNUM ! 3617: && i != ARG_POINTER_REGNUM) ! 3618: modified_regs[i] = 1; ! 3619: } ! 3620: ! 3621: note_stores (PATTERN (b2), mark_modified_reg); ! 3622: } ! 3623: ! 3624: /* Check the next candidate branch insn from the label ! 3625: of the first. */ ! 3626: if (b2 == 0 ! 3627: || GET_CODE (b2) != JUMP_INSN ! 3628: || b2 == b1 ! 3629: || ! condjump_p (b2) ! 3630: || simplejump_p (b2)) ! 3631: continue; ! 3632: ! 3633: /* Get the comparison codes and operands, reversing the ! 3634: codes if appropriate. If we don't have comparison codes, ! 3635: we can't do anything. */ ! 3636: b1op0 = XEXP (XEXP (SET_SRC (PATTERN (b1)), 0), 0); ! 3637: b1op1 = XEXP (XEXP (SET_SRC (PATTERN (b1)), 0), 1); ! 3638: code1 = GET_CODE (XEXP (SET_SRC (PATTERN (b1)), 0)); ! 3639: if (XEXP (SET_SRC (PATTERN (b1)), 1) == pc_rtx) ! 3640: code1 = reverse_condition (code1); ! 3641: ! 3642: b2op0 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 0); ! 3643: b2op1 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 1); ! 3644: code2 = GET_CODE (XEXP (SET_SRC (PATTERN (b2)), 0)); ! 3645: if (XEXP (SET_SRC (PATTERN (b2)), 1) == pc_rtx) ! 3646: code2 = reverse_condition (code2); ! 3647: ! 3648: /* If they test the same things and knowing that B1 branches ! 3649: tells us whether or not B2 branches, check if we ! 3650: can thread the branch. */ ! 3651: if (rtx_equal_for_thread_p (b1op0, b2op0, b2) ! 3652: && rtx_equal_for_thread_p (b1op1, b2op1, b2) ! 3653: && (comparison_dominates_p (code1, code2) ! 3654: || comparison_dominates_p (code1, reverse_condition (code2)))) ! 3655: { ! 3656: t1 = prev_nonnote_insn (b1); ! 3657: t2 = prev_nonnote_insn (b2); ! 3658: ! 3659: while (t1 != 0 && t2 != 0) ! 3660: { ! 3661: if (t1 == 0 || t2 == 0) ! 3662: break; ! 3663: ! 3664: if (t2 == label) ! 3665: { ! 3666: /* We have reached the target of the first branch. ! 3667: If there are no pending register equivalents, ! 3668: we know that this branch will either always ! 3669: succeed (if the senses of the two branches are ! 3670: the same) or always fail (if not). */ ! 3671: rtx new_label; ! 3672: ! 3673: if (num_same_regs != 0) ! 3674: break; ! 3675: ! 3676: if (comparison_dominates_p (code1, code2)) ! 3677: new_label = JUMP_LABEL (b2); ! 3678: else ! 3679: new_label = get_label_after (b2); ! 3680: ! 3681: if (JUMP_LABEL (b1) != new_label ! 3682: && redirect_jump (b1, new_label)) ! 3683: changed = 1; ! 3684: break; ! 3685: } ! 3686: ! 3687: /* If either of these is not a normal insn (it might be ! 3688: a JUMP_INSN, CALL_INSN, or CODE_LABEL) we fail. (NOTEs ! 3689: have already been skipped above.) Similarly, fail ! 3690: if the insns are different. */ ! 3691: if (GET_CODE (t1) != INSN || GET_CODE (t2) != INSN ! 3692: || recog_memoized (t1) != recog_memoized (t2) ! 3693: || ! rtx_equal_for_thread_p (PATTERN (t1), ! 3694: PATTERN (t2), t2)) ! 3695: break; ! 3696: ! 3697: t1 = prev_nonnote_insn (t1); ! 3698: t2 = prev_nonnote_insn (t2); ! 3699: } ! 3700: } ! 3701: } ! 3702: } ! 3703: } ! 3704: ! 3705: /* This is like RTX_EQUAL_P except that it knows about our handling of ! 3706: possibly equivalent registers and knows to consider volatile and ! 3707: modified objects as not equal. ! 3708: ! 3709: YINSN is the insn containing Y. */ ! 3710: ! 3711: int ! 3712: rtx_equal_for_thread_p (x, y, yinsn) ! 3713: rtx x, y; ! 3714: rtx yinsn; ! 3715: { ! 3716: register int i; ! 3717: register int j; ! 3718: register enum rtx_code code; ! 3719: register char *fmt; ! 3720: ! 3721: code = GET_CODE (x); ! 3722: /* Rtx's of different codes cannot be equal. */ ! 3723: if (code != GET_CODE (y)) ! 3724: return 0; ! 3725: ! 3726: /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. ! 3727: (REG:SI x) and (REG:HI x) are NOT equivalent. */ ! 3728: ! 3729: if (GET_MODE (x) != GET_MODE (y)) ! 3730: return 0; ! 3731: ! 3732: /* Handle special-cases first. */ ! 3733: switch (code) ! 3734: { ! 3735: case REG: ! 3736: if (REGNO (x) == REGNO (y) && ! modified_regs[REGNO (x)]) ! 3737: return 1; ! 3738: ! 3739: /* If neither is user variable or hard register, check for possible ! 3740: equivalence. */ ! 3741: if (REG_USERVAR_P (x) || REG_USERVAR_P (y) ! 3742: || REGNO (x) < FIRST_PSEUDO_REGISTER ! 3743: || REGNO (y) < FIRST_PSEUDO_REGISTER) ! 3744: return 0; ! 3745: ! 3746: if (same_regs[REGNO (x)] == -1) ! 3747: { ! 3748: same_regs[REGNO (x)] = REGNO (y); ! 3749: num_same_regs++; ! 3750: ! 3751: /* If this is the first time we are seeing a register on the `Y' ! 3752: side, see if it is the last use. If not, we can't thread the ! 3753: jump, so mark it as not equivalent. */ ! 3754: if (regno_last_uid[REGNO (y)] != INSN_UID (yinsn)) ! 3755: return 0; ! 3756: ! 3757: return 1; ! 3758: } ! 3759: else ! 3760: return (same_regs[REGNO (x)] == REGNO (y)); ! 3761: ! 3762: break; ! 3763: ! 3764: case MEM: ! 3765: /* If memory modified or either volatile, not eqivalent. ! 3766: Else, check address. */ ! 3767: if (modified_mem || MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y)) ! 3768: return 0; ! 3769: ! 3770: return rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn); ! 3771: ! 3772: case ASM_INPUT: ! 3773: if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y)) ! 3774: return 0; ! 3775: ! 3776: break; ! 3777: ! 3778: case SET: ! 3779: /* Cancel a pending `same_regs' if setting equivalenced registers. ! 3780: Then process source. */ ! 3781: if (GET_CODE (SET_DEST (x)) == REG ! 3782: && GET_CODE (SET_DEST (y)) == REG) ! 3783: { ! 3784: if (same_regs[REGNO (SET_DEST (x))] == REGNO (SET_DEST (y))) ! 3785: { ! 3786: same_regs[REGNO (SET_DEST (x))] = -1; ! 3787: num_same_regs--; ! 3788: } ! 3789: else if (REGNO (SET_DEST (x)) != REGNO (SET_DEST (y))) ! 3790: return 0; ! 3791: } ! 3792: else ! 3793: if (rtx_equal_for_thread_p (SET_DEST (x), SET_DEST (y), yinsn) == 0) ! 3794: return 0; ! 3795: ! 3796: return rtx_equal_for_thread_p (SET_SRC (x), SET_SRC (y), yinsn); ! 3797: ! 3798: case LABEL_REF: ! 3799: return XEXP (x, 0) == XEXP (y, 0); ! 3800: ! 3801: case SYMBOL_REF: ! 3802: return XSTR (x, 0) == XSTR (y, 0); ! 3803: } ! 3804: ! 3805: if (x == y) ! 3806: return 1; ! 3807: ! 3808: fmt = GET_RTX_FORMAT (code); ! 3809: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 3810: { ! 3811: switch (fmt[i]) ! 3812: { ! 3813: case 'n': ! 3814: case 'i': ! 3815: if (XINT (x, i) != XINT (y, i)) ! 3816: return 0; ! 3817: break; ! 3818: ! 3819: case 'V': ! 3820: case 'E': ! 3821: /* Two vectors must have the same length. */ ! 3822: if (XVECLEN (x, i) != XVECLEN (y, i)) ! 3823: return 0; ! 3824: ! 3825: /* And the corresponding elements must match. */ ! 3826: for (j = 0; j < XVECLEN (x, i); j++) ! 3827: if (rtx_equal_for_thread_p (XVECEXP (x, i, j), ! 3828: XVECEXP (y, i, j), yinsn) == 0) ! 3829: return 0; ! 3830: break; ! 3831: ! 3832: case 'e': ! 3833: if (rtx_equal_for_thread_p (XEXP (x, i), XEXP (y, i), yinsn) == 0) ! 3834: return 0; ! 3835: break; ! 3836: ! 3837: case 'S': ! 3838: case 's': ! 3839: if (strcmp (XSTR (x, i), XSTR (y, i))) ! 3840: return 0; ! 3841: break; ! 3842: ! 3843: case 'u': ! 3844: /* These are just backpointers, so they don't matter. */ ! 3845: break; ! 3846: ! 3847: case '0': ! 3848: break; ! 3849: ! 3850: /* It is believed that rtx's at this level will never ! 3851: contain anything but integers and other rtx's, ! 3852: except for within LABEL_REFs and SYMBOL_REFs. */ ! 3853: default: ! 3854: abort (); ! 3855: } ! 3856: } ! 3857: return 1; ! 3858: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.