|
|
1.1 ! root 1: /* Subroutines for manipulating rtx's in semantically interesting ways. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include "config.h" ! 23: #include "rtl.h" ! 24: #include "tree.h" ! 25: #include "flags.h" ! 26: #include "expr.h" ! 27: ! 28: /* Return an rtx for the sum of X and the integer C. */ ! 29: ! 30: rtx ! 31: plus_constant (x, c) ! 32: register rtx x; ! 33: register int c; ! 34: { ! 35: register RTX_CODE code = GET_CODE (x); ! 36: register enum machine_mode mode = GET_MODE (x); ! 37: int all_constant = 0; ! 38: ! 39: if (c == 0) ! 40: return x; ! 41: ! 42: if (code == CONST_INT) ! 43: return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c)); ! 44: ! 45: /* If adding to something entirely constant, set a flag ! 46: so that we can add a CONST around the result. */ ! 47: if (code == CONST) ! 48: { ! 49: x = XEXP (x, 0); ! 50: all_constant = 1; ! 51: } ! 52: else if (code == SYMBOL_REF || code == LABEL_REF) ! 53: all_constant = 1; ! 54: ! 55: /* The interesting case is adding the integer to a sum. ! 56: Look for constant term in the sum and combine ! 57: with C. For an integer constant term, we make a combined ! 58: integer. For a constant term that is not an explicit integer, ! 59: we cannot really combine, but group them together anyway. */ ! 60: ! 61: if (GET_CODE (x) == PLUS) ! 62: { ! 63: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 64: { ! 65: c += INTVAL (XEXP (x, 0)); ! 66: x = XEXP (x, 1); ! 67: } ! 68: else if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 69: { ! 70: c += INTVAL (XEXP (x, 1)); ! 71: x = XEXP (x, 0); ! 72: } ! 73: else if (CONSTANT_P (XEXP (x, 0))) ! 74: { ! 75: return gen_rtx (PLUS, mode, ! 76: plus_constant (XEXP (x, 0), c), ! 77: XEXP (x, 1)); ! 78: } ! 79: else if (CONSTANT_P (XEXP (x, 1))) ! 80: { ! 81: return gen_rtx (PLUS, mode, ! 82: XEXP (x, 0), ! 83: plus_constant (XEXP (x, 1), c)); ! 84: } ! 85: #ifdef OLD_INDEXING ! 86: /* Detect adding a constant to an indexed address ! 87: of the form (PLUS (MULT (REG) (CONST)) regs-and-constants). ! 88: Keep the (MULT ...) at the top level of addition so that ! 89: the result is still suitable for indexing and constants ! 90: are combined. */ ! 91: else if (GET_CODE (XEXP (x, 0)) == MULT) ! 92: { ! 93: return gen_rtx (PLUS, mode, XEXP (x, 0), ! 94: plus_constant (XEXP (x, 1), c)); ! 95: } ! 96: else if (GET_CODE (XEXP (x, 1)) == MULT) ! 97: { ! 98: return gen_rtx (PLUS, mode, plus_constant (XEXP (x, 0), c), ! 99: XEXP (x, 1)); ! 100: } ! 101: #endif ! 102: } ! 103: if (c != 0) ! 104: x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c)); ! 105: ! 106: if (all_constant) ! 107: return gen_rtx (CONST, mode, x); ! 108: else ! 109: return x; ! 110: } ! 111: ! 112: /* If X is a sum, return a new sum like X but lacking any constant terms. ! 113: Add all the removed constant terms into *CONSTPTR. ! 114: X itself is not altered. The result != X if and only if ! 115: it is not isomorphic to X. */ ! 116: ! 117: rtx ! 118: eliminate_constant_term (x, constptr) ! 119: rtx x; ! 120: int *constptr; ! 121: { ! 122: int c; ! 123: register rtx x0, x1; ! 124: ! 125: if (GET_CODE (x) != PLUS) ! 126: return x; ! 127: ! 128: /* First handle constants appearing at this level explicitly. */ ! 129: if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! 130: { ! 131: *constptr += INTVAL (XEXP (x, 0)); ! 132: return eliminate_constant_term (XEXP (x, 1), constptr); ! 133: } ! 134: ! 135: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 136: { ! 137: *constptr += INTVAL (XEXP (x, 1)); ! 138: return eliminate_constant_term (XEXP (x, 0), constptr); ! 139: } ! 140: ! 141: c = 0; ! 142: x0 = eliminate_constant_term (XEXP (x, 0), &c); ! 143: x1 = eliminate_constant_term (XEXP (x, 1), &c); ! 144: if (x1 != XEXP (x, 1) || x0 != XEXP (x, 0)) ! 145: { ! 146: *constptr += c; ! 147: return gen_rtx (PLUS, GET_MODE (x), x0, x1); ! 148: } ! 149: return x; ! 150: } ! 151: ! 152: /* Return an rtx for the size in bytes of the value of EXP. */ ! 153: ! 154: rtx ! 155: expr_size (exp) ! 156: tree exp; ! 157: { ! 158: return expand_expr (size_in_bytes (TREE_TYPE (exp)), 0, SImode, 0); ! 159: } ! 160: ! 161: /* Not yet really written since C does not need it. */ ! 162: ! 163: rtx ! 164: lookup_static_chain () ! 165: { ! 166: abort (); ! 167: } ! 168: ! 169: /* Return a copy of X in which all memory references ! 170: and all constants that involve symbol refs ! 171: have been replaced with new temporary registers. ! 172: Also emit code to load the memory locations and constants ! 173: into those registers. ! 174: ! 175: If X contains no such constants or memory references, ! 176: X itself (not a copy) is returned. ! 177: ! 178: X may contain no arithmetic except addition, subtraction and multiplication. ! 179: Values returned by expand_expr with 1 for sum_ok fit this constraint. */ ! 180: ! 181: static rtx ! 182: break_out_memory_refs (x) ! 183: register rtx x; ! 184: { ! 185: if (GET_CODE (x) == MEM || GET_CODE (x) == CONST ! 186: || GET_CODE (x) == SYMBOL_REF) ! 187: { ! 188: register rtx temp = force_reg (Pmode, x); ! 189: mark_reg_pointer (temp); ! 190: x = temp; ! 191: } ! 192: else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS ! 193: || GET_CODE (x) == MULT) ! 194: { ! 195: register rtx op0 = break_out_memory_refs (XEXP (x, 0)); ! 196: register rtx op1 = break_out_memory_refs (XEXP (x, 1)); ! 197: if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) ! 198: x = gen_rtx (GET_CODE (x), Pmode, op0, op1); ! 199: } ! 200: return x; ! 201: } ! 202: ! 203: /* Given a memory address or facsimile X, construct a new address, ! 204: currently equivalent, that is stable: future stores won't change it. ! 205: ! 206: X must be composed of constants, register and memory references ! 207: combined with addition, subtraction and multiplication: ! 208: in other words, just what you can get from expand_expr if sum_ok is 1. ! 209: ! 210: Works by making copies of all regs and memory locations used ! 211: by X and combining them the same way X does. ! 212: You could also stabilize the reference to this address ! 213: by copying the address to a register with copy_to_reg; ! 214: but then you wouldn't get indexed addressing in the reference. */ ! 215: ! 216: rtx ! 217: copy_all_regs (x) ! 218: register rtx x; ! 219: { ! 220: if (GET_CODE (x) == REG) ! 221: { ! 222: if (REGNO (x) != FRAME_POINTER_REGNUM) ! 223: x = copy_to_reg (x); ! 224: } ! 225: else if (GET_CODE (x) == MEM) ! 226: x = copy_to_reg (x); ! 227: else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS ! 228: || GET_CODE (x) == MULT) ! 229: { ! 230: register rtx op0 = copy_all_regs (XEXP (x, 0)); ! 231: register rtx op1 = copy_all_regs (XEXP (x, 1)); ! 232: if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1)) ! 233: x = gen_rtx (GET_CODE (x), Pmode, op0, op1); ! 234: } ! 235: return x; ! 236: } ! 237: ! 238: /* Return something equivalent to X but valid as a memory address ! 239: for something of mode MODE. When X is not itself valid, this ! 240: works by copying X or subexpressions of it into registers. */ ! 241: ! 242: rtx ! 243: memory_address (mode, x) ! 244: enum machine_mode mode; ! 245: register rtx x; ! 246: { ! 247: register rtx tem, oldx; ! 248: ! 249: /* By passing constant addresses thru registers ! 250: we get a chance to cse them. */ ! 251: if (! cse_not_expected && CONSTANT_P (x)) ! 252: return force_reg (Pmode, x); ! 253: ! 254: /* Accept a QUEUED that refers to a REG ! 255: even though that isn't a valid address. ! 256: On attempting to put this in an insn we will call protect_from_queue ! 257: which will turn it into a REG, which is valid. */ ! 258: if (GET_CODE (x) == QUEUED ! 259: && GET_CODE (QUEUED_VAR (x)) == REG) ! 260: return x; ! 261: ! 262: /* We get better cse by rejecting indirect addressing at this stage. ! 263: Let the combiner create indirect addresses where appropriate. ! 264: For now, generate the code so that the subexpressions useful to share ! 265: are visible. But not if cse won't be done! */ ! 266: oldx = x; ! 267: if (! cse_not_expected && GET_CODE (x) != REG) ! 268: x = break_out_memory_refs (x); ! 269: ! 270: /* At this point, any valid address is accepted. */ ! 271: GO_IF_LEGITIMATE_ADDRESS (mode, x, win); ! 272: ! 273: /* If it was valid before but breaking out memory refs invalidated it, ! 274: use it the old way. */ ! 275: if (memory_address_p (mode, oldx)) ! 276: goto win2; ! 277: ! 278: /* Perform machine-dependent transformations on X ! 279: in certain cases. This is not necessary since the code ! 280: below can handle all possible cases, but machine-dependent ! 281: transformations can make better code. */ ! 282: LEGITIMIZE_ADDRESS (x, oldx, mode, win); ! 283: ! 284: /* PLUS and MULT can appear in special ways ! 285: as the result of attempts to make an address usable for indexing. ! 286: Usually they are dealt with by calling force_operand, below. ! 287: But a sum containing constant terms is special ! 288: if removing them makes the sum a valid address: ! 289: then we generate that address in a register ! 290: and index off of it. We do this because it often makes ! 291: shorter code, and because the addresses thus generated ! 292: in registers often become common subexpressions. */ ! 293: if (GET_CODE (x) == PLUS) ! 294: { ! 295: int constant_term = 0; ! 296: rtx y = eliminate_constant_term (x, &constant_term); ! 297: if (constant_term == 0 ! 298: || ! memory_address_p (mode, y)) ! 299: return force_operand (x, 0); ! 300: ! 301: y = plus_constant (copy_to_reg (y), constant_term); ! 302: if (! memory_address_p (mode, y)) ! 303: return force_operand (x, 0); ! 304: return y; ! 305: } ! 306: if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS) ! 307: return force_operand (x, 0); ! 308: ! 309: /* Last resort: copy the value to a register, since ! 310: the register is a valid address. */ ! 311: return force_reg (Pmode, x); ! 312: ! 313: win2: ! 314: x = oldx; ! 315: win: ! 316: if (flag_force_addr && optimize && GET_CODE (x) != REG ! 317: /* Don't copy an addr via a reg if it is one of our stack slots. ! 318: If we did, it would cause invalid REG_EQUIV notes for parms. */ ! 319: && ! (GET_CODE (x) == PLUS ! 320: && (XEXP (x, 0) == frame_pointer_rtx ! 321: || XEXP (x, 0) == arg_pointer_rtx))) ! 322: return force_reg (Pmode, x); ! 323: return x; ! 324: } ! 325: ! 326: /* Return a modified copy of X with its memory address copied ! 327: into a temporary register to protect it from side effects. ! 328: If X is not a MEM, it is returned unchanged (and not copied). ! 329: Perhaps even if it is a MEM, if there is no need to change it. */ ! 330: ! 331: rtx ! 332: stabilize (x) ! 333: rtx x; ! 334: { ! 335: register rtx addr; ! 336: if (GET_CODE (x) != MEM) ! 337: return x; ! 338: addr = XEXP (x, 0); ! 339: if (rtx_unstable_p (addr)) ! 340: { ! 341: rtx temp = copy_all_regs (addr); ! 342: rtx mem; ! 343: if (GET_CODE (temp) != REG) ! 344: temp = copy_to_reg (temp); ! 345: mem = gen_rtx (MEM, GET_MODE (x), temp); ! 346: /* Mark returned memref with in_struct ! 347: if it's in an array or structure. */ ! 348: if (GET_CODE (addr) == PLUS || x->in_struct) ! 349: mem->in_struct = 1; ! 350: return mem; ! 351: } ! 352: return x; ! 353: } ! 354: ! 355: /* Copy the value or contents of X to a new temp reg and return that reg. */ ! 356: ! 357: rtx ! 358: copy_to_reg (x) ! 359: rtx x; ! 360: { ! 361: register rtx temp = gen_reg_rtx (GET_MODE (x)); ! 362: emit_move_insn (temp, x); ! 363: return temp; ! 364: } ! 365: ! 366: /* Like copy_to_reg but always give the new register mode Pmode ! 367: in case X is a constant. */ ! 368: ! 369: rtx ! 370: copy_addr_to_reg (x) ! 371: rtx x; ! 372: { ! 373: register rtx temp = gen_reg_rtx (Pmode); ! 374: emit_move_insn (temp, x); ! 375: return temp; ! 376: } ! 377: ! 378: /* Like copy_to_reg but always give the new register mode MODE ! 379: in case X is a constant. */ ! 380: ! 381: rtx ! 382: copy_to_mode_reg (mode, x) ! 383: enum machine_mode mode; ! 384: rtx x; ! 385: { ! 386: register rtx temp = gen_reg_rtx (mode); ! 387: if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode) ! 388: abort (); ! 389: emit_move_insn (temp, x); ! 390: return temp; ! 391: } ! 392: ! 393: /* Load X into a register if it is not already one. ! 394: Use mode MODE for the register. ! 395: X should be valid for mode MODE, but it may be a constant which ! 396: is valid for all integer modes; that's why caller must specify MODE. ! 397: ! 398: The caller must not alter the value in the register we return, ! 399: since we mark it as a "constant" register. */ ! 400: ! 401: rtx ! 402: force_reg (mode, x) ! 403: enum machine_mode mode; ! 404: rtx x; ! 405: { ! 406: register rtx temp, insn; ! 407: ! 408: if (GET_CODE (x) == REG) ! 409: return x; ! 410: temp = gen_reg_rtx (mode); ! 411: insn = emit_move_insn (temp, x); ! 412: /* Let optimizers know that TEMP's value never changes ! 413: and that X can be substituted for it. */ ! 414: if (CONSTANT_P (x)) ! 415: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, x, 0); ! 416: return temp; ! 417: } ! 418: ! 419: /* If X is a memory ref, copy its contents to a new temp reg and return ! 420: that reg. Otherwise, return X. */ ! 421: ! 422: rtx ! 423: force_not_mem (x) ! 424: rtx x; ! 425: { ! 426: register rtx temp; ! 427: if (GET_CODE (x) != MEM) ! 428: return x; ! 429: temp = gen_reg_rtx (GET_MODE (x)); ! 430: emit_move_insn (temp, x); ! 431: return temp; ! 432: } ! 433: ! 434: /* Copy X to TARGET (if it's nonzero and a reg) ! 435: or to a new temp reg and return that reg. */ ! 436: ! 437: rtx ! 438: copy_to_suggested_reg (x, target) ! 439: rtx x, target; ! 440: { ! 441: register rtx temp; ! 442: if (target && GET_CODE (target) == REG) ! 443: temp = target; ! 444: else ! 445: temp = gen_reg_rtx (GET_MODE (x)); ! 446: emit_move_insn (temp, x); ! 447: return temp; ! 448: } ! 449: ! 450: /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes). ! 451: This pops when ADJUST is positive. ADJUST need not be constant. */ ! 452: ! 453: void ! 454: adjust_stack (adjust) ! 455: rtx adjust; ! 456: { ! 457: adjust = protect_from_queue (adjust, 0); ! 458: ! 459: #ifdef STACK_GROWS_DOWNWARD ! 460: emit_insn (gen_add2_insn (stack_pointer_rtx, adjust)); ! 461: #else ! 462: emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust)); ! 463: #endif ! 464: } ! 465: ! 466: /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes). ! 467: This pushes when ADJUST is positive. ADJUST need not be constant. */ ! 468: ! 469: void ! 470: anti_adjust_stack (adjust) ! 471: rtx adjust; ! 472: { ! 473: adjust = protect_from_queue (adjust, 0); ! 474: ! 475: #ifdef STACK_GROWS_DOWNWARD ! 476: emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust)); ! 477: #else ! 478: emit_insn (gen_add2_insn (stack_pointer_rtx, adjust)); ! 479: #endif ! 480: } ! 481: ! 482: /* Round the size of a block to be pushed up to the boundary required ! 483: by this machine. SIZE is the desired size, which need not be constant. */ ! 484: ! 485: rtx ! 486: round_push (size) ! 487: rtx size; ! 488: { ! 489: #ifdef STACK_BOUNDARY ! 490: int align = STACK_BOUNDARY / BITS_PER_UNIT; ! 491: if (align == 1) ! 492: ; ! 493: if (GET_CODE (size) == CONST_INT) ! 494: { ! 495: int new = (INTVAL (size) + align - 1) / align * align; ! 496: if (INTVAL (size) != new) ! 497: size = gen_rtx (CONST_INT, VOIDmode, new); ! 498: } ! 499: else ! 500: { ! 501: size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, ! 502: gen_rtx (CONST_INT, VOIDmode, align), ! 503: 0, 1); ! 504: size = expand_mult (Pmode, size, ! 505: gen_rtx (CONST_INT, VOIDmode, align), ! 506: 0, 1); ! 507: } ! 508: #endif /* STACK_BOUNDARY */ ! 509: return size; ! 510: } ! 511: ! 512: /* Return an rtx representing the register or memory location ! 513: in which a scalar value of data type VALTYPE ! 514: was returned by a function call to function FUNC. ! 515: FUNC is a FUNCTION_DECL node if the precise function is known, ! 516: otherwise 0. */ ! 517: ! 518: rtx ! 519: hard_function_value (valtype, func) ! 520: tree valtype; ! 521: tree func; ! 522: { ! 523: return FUNCTION_VALUE (valtype, func); ! 524: } ! 525: ! 526: /* Return an rtx representing the register or memory location ! 527: in which a scalar value of mode MODE was returned by a library call. */ ! 528: ! 529: rtx ! 530: hard_libcall_value (mode) ! 531: enum machine_mode mode; ! 532: { ! 533: return LIBCALL_VALUE (mode); ! 534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.