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