1132718Skan/* Perform simple optimizations to clean up the result of reload. 2132718Skan Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 4132718Skan 5132718SkanThis file is part of GCC. 6132718Skan 7132718SkanGCC is free software; you can redistribute it and/or modify it under 8132718Skanthe terms of the GNU General Public License as published by the Free 9132718SkanSoftware Foundation; either version 2, or (at your option) any later 10132718Skanversion. 11132718Skan 12132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 14132718SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15132718Skanfor more details. 16132718Skan 17132718SkanYou should have received a copy of the GNU General Public License 18132718Skanalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 21132718Skan 22132718Skan#include "config.h" 23132718Skan#include "system.h" 24132718Skan#include "coretypes.h" 25132718Skan#include "tm.h" 26132718Skan 27132718Skan#include "machmode.h" 28132718Skan#include "hard-reg-set.h" 29132718Skan#include "rtl.h" 30132718Skan#include "tm_p.h" 31132718Skan#include "obstack.h" 32132718Skan#include "insn-config.h" 33132718Skan#include "flags.h" 34132718Skan#include "function.h" 35132718Skan#include "expr.h" 36132718Skan#include "optabs.h" 37132718Skan#include "regs.h" 38132718Skan#include "basic-block.h" 39132718Skan#include "reload.h" 40132718Skan#include "recog.h" 41132718Skan#include "output.h" 42132718Skan#include "cselib.h" 43132718Skan#include "real.h" 44132718Skan#include "toplev.h" 45132718Skan#include "except.h" 46132718Skan#include "tree.h" 47169689Skan#include "timevar.h" 48169689Skan#include "tree-pass.h" 49132718Skan 50132718Skanstatic int reload_cse_noop_set_p (rtx); 51132718Skanstatic void reload_cse_simplify (rtx, rtx); 52132718Skanstatic void reload_cse_regs_1 (rtx); 53132718Skanstatic int reload_cse_simplify_set (rtx, rtx); 54132718Skanstatic int reload_cse_simplify_operands (rtx, rtx); 55132718Skan 56132718Skanstatic void reload_combine (void); 57132718Skanstatic void reload_combine_note_use (rtx *, rtx); 58132718Skanstatic void reload_combine_note_store (rtx, rtx, void *); 59132718Skan 60132718Skanstatic void reload_cse_move2add (rtx); 61132718Skanstatic void move2add_note_store (rtx, rtx, void *); 62132718Skan 63132718Skan/* Call cse / combine like post-reload optimization phases. 64132718Skan FIRST is the first instruction. */ 65132718Skanvoid 66132718Skanreload_cse_regs (rtx first ATTRIBUTE_UNUSED) 67132718Skan{ 68132718Skan reload_cse_regs_1 (first); 69132718Skan reload_combine (); 70132718Skan reload_cse_move2add (first); 71132718Skan if (flag_expensive_optimizations) 72132718Skan reload_cse_regs_1 (first); 73132718Skan} 74132718Skan 75132718Skan/* See whether a single set SET is a noop. */ 76132718Skanstatic int 77132718Skanreload_cse_noop_set_p (rtx set) 78132718Skan{ 79132718Skan if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set))) 80132718Skan return 0; 81132718Skan 82132718Skan return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set)); 83132718Skan} 84132718Skan 85132718Skan/* Try to simplify INSN. */ 86132718Skanstatic void 87132718Skanreload_cse_simplify (rtx insn, rtx testreg) 88132718Skan{ 89132718Skan rtx body = PATTERN (insn); 90132718Skan 91132718Skan if (GET_CODE (body) == SET) 92132718Skan { 93132718Skan int count = 0; 94132718Skan 95132718Skan /* Simplify even if we may think it is a no-op. 96132718Skan We may think a memory load of a value smaller than WORD_SIZE 97132718Skan is redundant because we haven't taken into account possible 98132718Skan implicit extension. reload_cse_simplify_set() will bring 99132718Skan this out, so it's safer to simplify before we delete. */ 100132718Skan count += reload_cse_simplify_set (body, insn); 101132718Skan 102132718Skan if (!count && reload_cse_noop_set_p (body)) 103132718Skan { 104132718Skan rtx value = SET_DEST (body); 105132718Skan if (REG_P (value) 106132718Skan && ! REG_FUNCTION_VALUE_P (value)) 107132718Skan value = 0; 108132718Skan delete_insn_and_edges (insn); 109132718Skan return; 110132718Skan } 111132718Skan 112132718Skan if (count > 0) 113132718Skan apply_change_group (); 114132718Skan else 115132718Skan reload_cse_simplify_operands (insn, testreg); 116132718Skan } 117132718Skan else if (GET_CODE (body) == PARALLEL) 118132718Skan { 119132718Skan int i; 120132718Skan int count = 0; 121132718Skan rtx value = NULL_RTX; 122132718Skan 123146895Skan /* Registers mentioned in the clobber list for an asm cannot be reused 124146895Skan within the body of the asm. Invalidate those registers now so that 125146895Skan we don't try to substitute values for them. */ 126146895Skan if (asm_noperands (body) >= 0) 127146895Skan { 128146895Skan for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 129146895Skan { 130146895Skan rtx part = XVECEXP (body, 0, i); 131146895Skan if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0))) 132146895Skan cselib_invalidate_rtx (XEXP (part, 0)); 133146895Skan } 134146895Skan } 135146895Skan 136132718Skan /* If every action in a PARALLEL is a noop, we can delete 137132718Skan the entire PARALLEL. */ 138132718Skan for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 139132718Skan { 140132718Skan rtx part = XVECEXP (body, 0, i); 141132718Skan if (GET_CODE (part) == SET) 142132718Skan { 143132718Skan if (! reload_cse_noop_set_p (part)) 144132718Skan break; 145132718Skan if (REG_P (SET_DEST (part)) 146132718Skan && REG_FUNCTION_VALUE_P (SET_DEST (part))) 147132718Skan { 148132718Skan if (value) 149132718Skan break; 150132718Skan value = SET_DEST (part); 151132718Skan } 152132718Skan } 153132718Skan else if (GET_CODE (part) != CLOBBER) 154132718Skan break; 155132718Skan } 156132718Skan 157132718Skan if (i < 0) 158132718Skan { 159132718Skan delete_insn_and_edges (insn); 160132718Skan /* We're done with this insn. */ 161132718Skan return; 162132718Skan } 163132718Skan 164132718Skan /* It's not a no-op, but we can try to simplify it. */ 165132718Skan for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 166132718Skan if (GET_CODE (XVECEXP (body, 0, i)) == SET) 167132718Skan count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn); 168132718Skan 169132718Skan if (count > 0) 170132718Skan apply_change_group (); 171132718Skan else 172132718Skan reload_cse_simplify_operands (insn, testreg); 173132718Skan } 174132718Skan} 175132718Skan 176132718Skan/* Do a very simple CSE pass over the hard registers. 177132718Skan 178132718Skan This function detects no-op moves where we happened to assign two 179132718Skan different pseudo-registers to the same hard register, and then 180132718Skan copied one to the other. Reload will generate a useless 181132718Skan instruction copying a register to itself. 182132718Skan 183132718Skan This function also detects cases where we load a value from memory 184132718Skan into two different registers, and (if memory is more expensive than 185132718Skan registers) changes it to simply copy the first register into the 186132718Skan second register. 187132718Skan 188132718Skan Another optimization is performed that scans the operands of each 189132718Skan instruction to see whether the value is already available in a 190132718Skan hard register. It then replaces the operand with the hard register 191132718Skan if possible, much like an optional reload would. */ 192132718Skan 193132718Skanstatic void 194132718Skanreload_cse_regs_1 (rtx first) 195132718Skan{ 196132718Skan rtx insn; 197132718Skan rtx testreg = gen_rtx_REG (VOIDmode, -1); 198132718Skan 199169689Skan cselib_init (true); 200132718Skan init_alias_analysis (); 201132718Skan 202132718Skan for (insn = first; insn; insn = NEXT_INSN (insn)) 203132718Skan { 204132718Skan if (INSN_P (insn)) 205132718Skan reload_cse_simplify (insn, testreg); 206132718Skan 207132718Skan cselib_process_insn (insn); 208132718Skan } 209132718Skan 210132718Skan /* Clean up. */ 211132718Skan end_alias_analysis (); 212132718Skan cselib_finish (); 213132718Skan} 214132718Skan 215132718Skan/* Try to simplify a single SET instruction. SET is the set pattern. 216132718Skan INSN is the instruction it came from. 217132718Skan This function only handles one case: if we set a register to a value 218132718Skan which is not a register, we try to find that value in some other register 219132718Skan and change the set into a register copy. */ 220132718Skan 221132718Skanstatic int 222132718Skanreload_cse_simplify_set (rtx set, rtx insn) 223132718Skan{ 224132718Skan int did_change = 0; 225132718Skan int dreg; 226132718Skan rtx src; 227132718Skan enum reg_class dclass; 228132718Skan int old_cost; 229132718Skan cselib_val *val; 230132718Skan struct elt_loc_list *l; 231132718Skan#ifdef LOAD_EXTEND_OP 232169689Skan enum rtx_code extend_op = UNKNOWN; 233132718Skan#endif 234132718Skan 235132718Skan dreg = true_regnum (SET_DEST (set)); 236132718Skan if (dreg < 0) 237132718Skan return 0; 238132718Skan 239132718Skan src = SET_SRC (set); 240132718Skan if (side_effects_p (src) || true_regnum (src) >= 0) 241132718Skan return 0; 242132718Skan 243132718Skan dclass = REGNO_REG_CLASS (dreg); 244132718Skan 245132718Skan#ifdef LOAD_EXTEND_OP 246132718Skan /* When replacing a memory with a register, we need to honor assumptions 247132718Skan that combine made wrt the contents of sign bits. We'll do this by 248132718Skan generating an extend instruction instead of a reg->reg copy. Thus 249132718Skan the destination must be a register that we can widen. */ 250169689Skan if (MEM_P (src) 251132718Skan && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD 252169689Skan && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN 253169689Skan && !REG_P (SET_DEST (set))) 254132718Skan return 0; 255132718Skan#endif 256132718Skan 257132718Skan val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0); 258132718Skan if (! val) 259132718Skan return 0; 260132718Skan 261132718Skan /* If memory loads are cheaper than register copies, don't change them. */ 262169689Skan if (MEM_P (src)) 263132718Skan old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1); 264169689Skan else if (REG_P (src)) 265132718Skan old_cost = REGISTER_MOVE_COST (GET_MODE (src), 266132718Skan REGNO_REG_CLASS (REGNO (src)), dclass); 267132718Skan else 268132718Skan old_cost = rtx_cost (src, SET); 269132718Skan 270132718Skan for (l = val->locs; l; l = l->next) 271132718Skan { 272132718Skan rtx this_rtx = l->loc; 273132718Skan int this_cost; 274132718Skan 275132718Skan if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0)) 276132718Skan { 277132718Skan#ifdef LOAD_EXTEND_OP 278169689Skan if (extend_op != UNKNOWN) 279132718Skan { 280132718Skan HOST_WIDE_INT this_val; 281132718Skan 282132718Skan /* ??? I'm lazy and don't wish to handle CONST_DOUBLE. Other 283132718Skan constants, such as SYMBOL_REF, cannot be extended. */ 284132718Skan if (GET_CODE (this_rtx) != CONST_INT) 285132718Skan continue; 286132718Skan 287132718Skan this_val = INTVAL (this_rtx); 288132718Skan switch (extend_op) 289132718Skan { 290132718Skan case ZERO_EXTEND: 291132718Skan this_val &= GET_MODE_MASK (GET_MODE (src)); 292132718Skan break; 293132718Skan case SIGN_EXTEND: 294132718Skan /* ??? In theory we're already extended. */ 295132718Skan if (this_val == trunc_int_for_mode (this_val, GET_MODE (src))) 296132718Skan break; 297132718Skan default: 298169689Skan gcc_unreachable (); 299132718Skan } 300132718Skan this_rtx = GEN_INT (this_val); 301132718Skan } 302132718Skan#endif 303132718Skan this_cost = rtx_cost (this_rtx, SET); 304132718Skan } 305169689Skan else if (REG_P (this_rtx)) 306132718Skan { 307132718Skan#ifdef LOAD_EXTEND_OP 308169689Skan if (extend_op != UNKNOWN) 309132718Skan { 310132718Skan this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx); 311132718Skan this_cost = rtx_cost (this_rtx, SET); 312132718Skan } 313132718Skan else 314132718Skan#endif 315132718Skan this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx), 316132718Skan REGNO_REG_CLASS (REGNO (this_rtx)), 317132718Skan dclass); 318132718Skan } 319132718Skan else 320132718Skan continue; 321132718Skan 322132718Skan /* If equal costs, prefer registers over anything else. That 323132718Skan tends to lead to smaller instructions on some machines. */ 324132718Skan if (this_cost < old_cost 325132718Skan || (this_cost == old_cost 326169689Skan && REG_P (this_rtx) 327169689Skan && !REG_P (SET_SRC (set)))) 328132718Skan { 329132718Skan#ifdef LOAD_EXTEND_OP 330132718Skan if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD 331169689Skan && extend_op != UNKNOWN 332132718Skan#ifdef CANNOT_CHANGE_MODE_CLASS 333132718Skan && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)), 334132718Skan word_mode, 335132718Skan REGNO_REG_CLASS (REGNO (SET_DEST (set)))) 336132718Skan#endif 337132718Skan ) 338132718Skan { 339132718Skan rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set))); 340132718Skan ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set)); 341132718Skan validate_change (insn, &SET_DEST (set), wide_dest, 1); 342132718Skan } 343132718Skan#endif 344132718Skan 345132718Skan validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1); 346132718Skan old_cost = this_cost, did_change = 1; 347132718Skan } 348132718Skan } 349132718Skan 350132718Skan return did_change; 351132718Skan} 352132718Skan 353132718Skan/* Try to replace operands in INSN with equivalent values that are already 354132718Skan in registers. This can be viewed as optional reloading. 355132718Skan 356132718Skan For each non-register operand in the insn, see if any hard regs are 357132718Skan known to be equivalent to that operand. Record the alternatives which 358132718Skan can accept these hard registers. Among all alternatives, select the 359132718Skan ones which are better or equal to the one currently matching, where 360132718Skan "better" is in terms of '?' and '!' constraints. Among the remaining 361132718Skan alternatives, select the one which replaces most operands with 362132718Skan hard registers. */ 363132718Skan 364132718Skanstatic int 365132718Skanreload_cse_simplify_operands (rtx insn, rtx testreg) 366132718Skan{ 367132718Skan int i, j; 368132718Skan 369132718Skan /* For each operand, all registers that are equivalent to it. */ 370132718Skan HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS]; 371132718Skan 372132718Skan const char *constraints[MAX_RECOG_OPERANDS]; 373132718Skan 374132718Skan /* Vector recording how bad an alternative is. */ 375132718Skan int *alternative_reject; 376132718Skan /* Vector recording how many registers can be introduced by choosing 377132718Skan this alternative. */ 378132718Skan int *alternative_nregs; 379132718Skan /* Array of vectors recording, for each operand and each alternative, 380132718Skan which hard register to substitute, or -1 if the operand should be 381132718Skan left as it is. */ 382132718Skan int *op_alt_regno[MAX_RECOG_OPERANDS]; 383132718Skan /* Array of alternatives, sorted in order of decreasing desirability. */ 384132718Skan int *alternative_order; 385132718Skan 386132718Skan extract_insn (insn); 387132718Skan 388132718Skan if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0) 389132718Skan return 0; 390132718Skan 391132718Skan /* Figure out which alternative currently matches. */ 392132718Skan if (! constrain_operands (1)) 393132718Skan fatal_insn_not_found (insn); 394132718Skan 395132718Skan alternative_reject = alloca (recog_data.n_alternatives * sizeof (int)); 396132718Skan alternative_nregs = alloca (recog_data.n_alternatives * sizeof (int)); 397132718Skan alternative_order = alloca (recog_data.n_alternatives * sizeof (int)); 398132718Skan memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int)); 399132718Skan memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int)); 400132718Skan 401132718Skan /* For each operand, find out which regs are equivalent. */ 402132718Skan for (i = 0; i < recog_data.n_operands; i++) 403132718Skan { 404132718Skan cselib_val *v; 405132718Skan struct elt_loc_list *l; 406132718Skan rtx op; 407132718Skan enum machine_mode mode; 408132718Skan 409132718Skan CLEAR_HARD_REG_SET (equiv_regs[i]); 410132718Skan 411132718Skan /* cselib blows up on CODE_LABELs. Trying to fix that doesn't seem 412132718Skan right, so avoid the problem here. Likewise if we have a constant 413132718Skan and the insn pattern doesn't tell us the mode we need. */ 414169689Skan if (LABEL_P (recog_data.operand[i]) 415132718Skan || (CONSTANT_P (recog_data.operand[i]) 416132718Skan && recog_data.operand_mode[i] == VOIDmode)) 417132718Skan continue; 418132718Skan 419132718Skan op = recog_data.operand[i]; 420132718Skan mode = GET_MODE (op); 421132718Skan#ifdef LOAD_EXTEND_OP 422169689Skan if (MEM_P (op) 423132718Skan && GET_MODE_BITSIZE (mode) < BITS_PER_WORD 424169689Skan && LOAD_EXTEND_OP (mode) != UNKNOWN) 425132718Skan { 426132718Skan rtx set = single_set (insn); 427132718Skan 428169689Skan /* We might have multiple sets, some of which do implicit 429132718Skan extension. Punt on this for now. */ 430132718Skan if (! set) 431132718Skan continue; 432169689Skan /* If the destination is also a MEM or a STRICT_LOW_PART, no 433132718Skan extension applies. 434132718Skan Also, if there is an explicit extension, we don't have to 435132718Skan worry about an implicit one. */ 436169689Skan else if (MEM_P (SET_DEST (set)) 437132718Skan || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART 438132718Skan || GET_CODE (SET_SRC (set)) == ZERO_EXTEND 439132718Skan || GET_CODE (SET_SRC (set)) == SIGN_EXTEND) 440132718Skan ; /* Continue ordinary processing. */ 441132718Skan#ifdef CANNOT_CHANGE_MODE_CLASS 442132718Skan /* If the register cannot change mode to word_mode, it follows that 443132718Skan it cannot have been used in word_mode. */ 444169689Skan else if (REG_P (SET_DEST (set)) 445132718Skan && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)), 446132718Skan word_mode, 447132718Skan REGNO_REG_CLASS (REGNO (SET_DEST (set))))) 448132718Skan ; /* Continue ordinary processing. */ 449132718Skan#endif 450132718Skan /* If this is a straight load, make the extension explicit. */ 451169689Skan else if (REG_P (SET_DEST (set)) 452132718Skan && recog_data.n_operands == 2 453132718Skan && SET_SRC (set) == op 454132718Skan && SET_DEST (set) == recog_data.operand[1-i]) 455132718Skan { 456132718Skan validate_change (insn, recog_data.operand_loc[i], 457132718Skan gen_rtx_fmt_e (LOAD_EXTEND_OP (mode), 458132718Skan word_mode, op), 459132718Skan 1); 460132718Skan validate_change (insn, recog_data.operand_loc[1-i], 461132718Skan gen_rtx_REG (word_mode, REGNO (SET_DEST (set))), 462132718Skan 1); 463132718Skan if (! apply_change_group ()) 464132718Skan return 0; 465132718Skan return reload_cse_simplify_operands (insn, testreg); 466132718Skan } 467132718Skan else 468132718Skan /* ??? There might be arithmetic operations with memory that are 469132718Skan safe to optimize, but is it worth the trouble? */ 470132718Skan continue; 471132718Skan } 472132718Skan#endif /* LOAD_EXTEND_OP */ 473132718Skan v = cselib_lookup (op, recog_data.operand_mode[i], 0); 474132718Skan if (! v) 475132718Skan continue; 476132718Skan 477132718Skan for (l = v->locs; l; l = l->next) 478169689Skan if (REG_P (l->loc)) 479132718Skan SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc)); 480132718Skan } 481132718Skan 482132718Skan for (i = 0; i < recog_data.n_operands; i++) 483132718Skan { 484132718Skan enum machine_mode mode; 485132718Skan int regno; 486132718Skan const char *p; 487132718Skan 488132718Skan op_alt_regno[i] = alloca (recog_data.n_alternatives * sizeof (int)); 489132718Skan for (j = 0; j < recog_data.n_alternatives; j++) 490132718Skan op_alt_regno[i][j] = -1; 491132718Skan 492132718Skan p = constraints[i] = recog_data.constraints[i]; 493132718Skan mode = recog_data.operand_mode[i]; 494132718Skan 495132718Skan /* Add the reject values for each alternative given by the constraints 496132718Skan for this operand. */ 497132718Skan j = 0; 498132718Skan while (*p != '\0') 499132718Skan { 500132718Skan char c = *p++; 501132718Skan if (c == ',') 502132718Skan j++; 503132718Skan else if (c == '?') 504132718Skan alternative_reject[j] += 3; 505132718Skan else if (c == '!') 506132718Skan alternative_reject[j] += 300; 507132718Skan } 508132718Skan 509132718Skan /* We won't change operands which are already registers. We 510132718Skan also don't want to modify output operands. */ 511132718Skan regno = true_regnum (recog_data.operand[i]); 512132718Skan if (regno >= 0 513132718Skan || constraints[i][0] == '=' 514132718Skan || constraints[i][0] == '+') 515132718Skan continue; 516132718Skan 517132718Skan for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 518132718Skan { 519132718Skan int class = (int) NO_REGS; 520132718Skan 521132718Skan if (! TEST_HARD_REG_BIT (equiv_regs[i], regno)) 522132718Skan continue; 523132718Skan 524132718Skan REGNO (testreg) = regno; 525132718Skan PUT_MODE (testreg, mode); 526132718Skan 527132718Skan /* We found a register equal to this operand. Now look for all 528132718Skan alternatives that can accept this register and have not been 529132718Skan assigned a register they can use yet. */ 530132718Skan j = 0; 531132718Skan p = constraints[i]; 532132718Skan for (;;) 533132718Skan { 534132718Skan char c = *p; 535132718Skan 536132718Skan switch (c) 537132718Skan { 538132718Skan case '=': case '+': case '?': 539132718Skan case '#': case '&': case '!': 540132718Skan case '*': case '%': 541132718Skan case '0': case '1': case '2': case '3': case '4': 542132718Skan case '5': case '6': case '7': case '8': case '9': 543132718Skan case 'm': case '<': case '>': case 'V': case 'o': 544132718Skan case 'E': case 'F': case 'G': case 'H': 545132718Skan case 's': case 'i': case 'n': 546132718Skan case 'I': case 'J': case 'K': case 'L': 547132718Skan case 'M': case 'N': case 'O': case 'P': 548132718Skan case 'p': case 'X': 549132718Skan /* These don't say anything we care about. */ 550132718Skan break; 551132718Skan 552132718Skan case 'g': case 'r': 553132718Skan class = reg_class_subunion[(int) class][(int) GENERAL_REGS]; 554132718Skan break; 555132718Skan 556132718Skan default: 557132718Skan class 558132718Skan = (reg_class_subunion 559132718Skan [(int) class] 560132718Skan [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]); 561132718Skan break; 562132718Skan 563132718Skan case ',': case '\0': 564132718Skan /* See if REGNO fits this alternative, and set it up as the 565132718Skan replacement register if we don't have one for this 566132718Skan alternative yet and the operand being replaced is not 567132718Skan a cheap CONST_INT. */ 568132718Skan if (op_alt_regno[i][j] == -1 569132718Skan && reg_fits_class_p (testreg, class, 0, mode) 570132718Skan && (GET_CODE (recog_data.operand[i]) != CONST_INT 571132718Skan || (rtx_cost (recog_data.operand[i], SET) 572132718Skan > rtx_cost (testreg, SET)))) 573132718Skan { 574132718Skan alternative_nregs[j]++; 575132718Skan op_alt_regno[i][j] = regno; 576132718Skan } 577132718Skan j++; 578169689Skan class = (int) NO_REGS; 579132718Skan break; 580132718Skan } 581132718Skan p += CONSTRAINT_LEN (c, p); 582132718Skan 583132718Skan if (c == '\0') 584132718Skan break; 585132718Skan } 586132718Skan } 587132718Skan } 588132718Skan 589132718Skan /* Record all alternatives which are better or equal to the currently 590132718Skan matching one in the alternative_order array. */ 591132718Skan for (i = j = 0; i < recog_data.n_alternatives; i++) 592132718Skan if (alternative_reject[i] <= alternative_reject[which_alternative]) 593132718Skan alternative_order[j++] = i; 594132718Skan recog_data.n_alternatives = j; 595132718Skan 596132718Skan /* Sort it. Given a small number of alternatives, a dumb algorithm 597132718Skan won't hurt too much. */ 598132718Skan for (i = 0; i < recog_data.n_alternatives - 1; i++) 599132718Skan { 600132718Skan int best = i; 601132718Skan int best_reject = alternative_reject[alternative_order[i]]; 602132718Skan int best_nregs = alternative_nregs[alternative_order[i]]; 603132718Skan int tmp; 604132718Skan 605132718Skan for (j = i + 1; j < recog_data.n_alternatives; j++) 606132718Skan { 607132718Skan int this_reject = alternative_reject[alternative_order[j]]; 608132718Skan int this_nregs = alternative_nregs[alternative_order[j]]; 609132718Skan 610132718Skan if (this_reject < best_reject 611169689Skan || (this_reject == best_reject && this_nregs > best_nregs)) 612132718Skan { 613132718Skan best = j; 614132718Skan best_reject = this_reject; 615132718Skan best_nregs = this_nregs; 616132718Skan } 617132718Skan } 618132718Skan 619132718Skan tmp = alternative_order[best]; 620132718Skan alternative_order[best] = alternative_order[i]; 621132718Skan alternative_order[i] = tmp; 622132718Skan } 623132718Skan 624132718Skan /* Substitute the operands as determined by op_alt_regno for the best 625132718Skan alternative. */ 626132718Skan j = alternative_order[0]; 627132718Skan 628132718Skan for (i = 0; i < recog_data.n_operands; i++) 629132718Skan { 630132718Skan enum machine_mode mode = recog_data.operand_mode[i]; 631132718Skan if (op_alt_regno[i][j] == -1) 632132718Skan continue; 633132718Skan 634132718Skan validate_change (insn, recog_data.operand_loc[i], 635132718Skan gen_rtx_REG (mode, op_alt_regno[i][j]), 1); 636132718Skan } 637132718Skan 638132718Skan for (i = recog_data.n_dups - 1; i >= 0; i--) 639132718Skan { 640132718Skan int op = recog_data.dup_num[i]; 641132718Skan enum machine_mode mode = recog_data.operand_mode[op]; 642132718Skan 643132718Skan if (op_alt_regno[op][j] == -1) 644132718Skan continue; 645132718Skan 646132718Skan validate_change (insn, recog_data.dup_loc[i], 647132718Skan gen_rtx_REG (mode, op_alt_regno[op][j]), 1); 648132718Skan } 649132718Skan 650132718Skan return apply_change_group (); 651132718Skan} 652132718Skan 653132718Skan/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg 654132718Skan addressing now. 655132718Skan This code might also be useful when reload gave up on reg+reg addressing 656132718Skan because of clashes between the return register and INDEX_REG_CLASS. */ 657132718Skan 658132718Skan/* The maximum number of uses of a register we can keep track of to 659132718Skan replace them with reg+reg addressing. */ 660132718Skan#define RELOAD_COMBINE_MAX_USES 6 661132718Skan 662132718Skan/* INSN is the insn where a register has ben used, and USEP points to the 663132718Skan location of the register within the rtl. */ 664132718Skanstruct reg_use { rtx insn, *usep; }; 665132718Skan 666132718Skan/* If the register is used in some unknown fashion, USE_INDEX is negative. 667132718Skan If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID 668132718Skan indicates where it becomes live again. 669132718Skan Otherwise, USE_INDEX is the index of the last encountered use of the 670132718Skan register (which is first among these we have seen since we scan backwards), 671132718Skan OFFSET contains the constant offset that is added to the register in 672132718Skan all encountered uses, and USE_RUID indicates the first encountered, i.e. 673132718Skan last, of these uses. 674132718Skan STORE_RUID is always meaningful if we only want to use a value in a 675132718Skan register in a different place: it denotes the next insn in the insn 676132718Skan stream (i.e. the last encountered) that sets or clobbers the register. */ 677132718Skanstatic struct 678132718Skan { 679132718Skan struct reg_use reg_use[RELOAD_COMBINE_MAX_USES]; 680132718Skan int use_index; 681132718Skan rtx offset; 682132718Skan int store_ruid; 683132718Skan int use_ruid; 684132718Skan } reg_state[FIRST_PSEUDO_REGISTER]; 685132718Skan 686132718Skan/* Reverse linear uid. This is increased in reload_combine while scanning 687132718Skan the instructions from last to first. It is used to set last_label_ruid 688132718Skan and the store_ruid / use_ruid fields in reg_state. */ 689132718Skanstatic int reload_combine_ruid; 690132718Skan 691132718Skan#define LABEL_LIVE(LABEL) \ 692132718Skan (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno]) 693132718Skan 694132718Skanstatic void 695132718Skanreload_combine (void) 696132718Skan{ 697132718Skan rtx insn, set; 698132718Skan int first_index_reg = -1; 699132718Skan int last_index_reg = 0; 700132718Skan int i; 701132718Skan basic_block bb; 702132718Skan unsigned int r; 703132718Skan int last_label_ruid; 704132718Skan int min_labelno, n_labels; 705132718Skan HARD_REG_SET ever_live_at_start, *label_live; 706132718Skan 707132718Skan /* If reg+reg can be used in offsetable memory addresses, the main chunk of 708132718Skan reload has already used it where appropriate, so there is no use in 709132718Skan trying to generate it now. */ 710132718Skan if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS) 711132718Skan return; 712132718Skan 713132718Skan /* To avoid wasting too much time later searching for an index register, 714132718Skan determine the minimum and maximum index register numbers. */ 715132718Skan for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 716132718Skan if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) 717132718Skan { 718132718Skan if (first_index_reg == -1) 719132718Skan first_index_reg = r; 720132718Skan 721132718Skan last_index_reg = r; 722132718Skan } 723132718Skan 724132718Skan /* If no index register is available, we can quit now. */ 725132718Skan if (first_index_reg == -1) 726132718Skan return; 727132718Skan 728132718Skan /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime 729132718Skan information is a bit fuzzy immediately after reload, but it's 730132718Skan still good enough to determine which registers are live at a jump 731132718Skan destination. */ 732132718Skan min_labelno = get_first_label_num (); 733132718Skan n_labels = max_label_num () - min_labelno; 734169689Skan label_live = XNEWVEC (HARD_REG_SET, n_labels); 735132718Skan CLEAR_HARD_REG_SET (ever_live_at_start); 736132718Skan 737132718Skan FOR_EACH_BB_REVERSE (bb) 738132718Skan { 739132718Skan insn = BB_HEAD (bb); 740169689Skan if (LABEL_P (insn)) 741132718Skan { 742132718Skan HARD_REG_SET live; 743132718Skan 744132718Skan REG_SET_TO_HARD_REG_SET (live, 745169689Skan bb->il.rtl->global_live_at_start); 746132718Skan compute_use_by_pseudos (&live, 747169689Skan bb->il.rtl->global_live_at_start); 748132718Skan COPY_HARD_REG_SET (LABEL_LIVE (insn), live); 749132718Skan IOR_HARD_REG_SET (ever_live_at_start, live); 750132718Skan } 751132718Skan } 752132718Skan 753132718Skan /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ 754132718Skan last_label_ruid = reload_combine_ruid = 0; 755132718Skan for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 756132718Skan { 757132718Skan reg_state[r].store_ruid = reload_combine_ruid; 758132718Skan if (fixed_regs[r]) 759132718Skan reg_state[r].use_index = -1; 760132718Skan else 761132718Skan reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 762132718Skan } 763132718Skan 764132718Skan for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) 765132718Skan { 766132718Skan rtx note; 767132718Skan 768132718Skan /* We cannot do our optimization across labels. Invalidating all the use 769132718Skan information we have would be costly, so we just note where the label 770132718Skan is and then later disable any optimization that would cross it. */ 771169689Skan if (LABEL_P (insn)) 772132718Skan last_label_ruid = reload_combine_ruid; 773169689Skan else if (BARRIER_P (insn)) 774132718Skan for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 775132718Skan if (! fixed_regs[r]) 776132718Skan reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 777132718Skan 778132718Skan if (! INSN_P (insn)) 779132718Skan continue; 780132718Skan 781132718Skan reload_combine_ruid++; 782132718Skan 783132718Skan /* Look for (set (REGX) (CONST_INT)) 784132718Skan (set (REGX) (PLUS (REGX) (REGY))) 785132718Skan ... 786132718Skan ... (MEM (REGX)) ... 787132718Skan and convert it to 788132718Skan (set (REGZ) (CONST_INT)) 789132718Skan ... 790132718Skan ... (MEM (PLUS (REGZ) (REGY)))... . 791132718Skan 792132718Skan First, check that we have (set (REGX) (PLUS (REGX) (REGY))) 793132718Skan and that we know all uses of REGX before it dies. 794132718Skan Also, explicitly check that REGX != REGY; our life information 795132718Skan does not yet show whether REGY changes in this insn. */ 796132718Skan set = single_set (insn); 797132718Skan if (set != NULL_RTX 798169689Skan && REG_P (SET_DEST (set)) 799169689Skan && (hard_regno_nregs[REGNO (SET_DEST (set))] 800169689Skan [GET_MODE (SET_DEST (set))] 801132718Skan == 1) 802132718Skan && GET_CODE (SET_SRC (set)) == PLUS 803169689Skan && REG_P (XEXP (SET_SRC (set), 1)) 804132718Skan && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set)) 805132718Skan && !rtx_equal_p (XEXP (SET_SRC (set), 1), SET_DEST (set)) 806132718Skan && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid) 807132718Skan { 808132718Skan rtx reg = SET_DEST (set); 809132718Skan rtx plus = SET_SRC (set); 810132718Skan rtx base = XEXP (plus, 1); 811132718Skan rtx prev = prev_nonnote_insn (insn); 812132718Skan rtx prev_set = prev ? single_set (prev) : NULL_RTX; 813132718Skan unsigned int regno = REGNO (reg); 814132718Skan rtx const_reg = NULL_RTX; 815132718Skan rtx reg_sum = NULL_RTX; 816132718Skan 817132718Skan /* Now, we need an index register. 818132718Skan We'll set index_reg to this index register, const_reg to the 819132718Skan register that is to be loaded with the constant 820132718Skan (denoted as REGZ in the substitution illustration above), 821132718Skan and reg_sum to the register-register that we want to use to 822132718Skan substitute uses of REG (typically in MEMs) with. 823132718Skan First check REG and BASE for being index registers; 824132718Skan we can use them even if they are not dead. */ 825132718Skan if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) 826132718Skan || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], 827132718Skan REGNO (base))) 828132718Skan { 829132718Skan const_reg = reg; 830132718Skan reg_sum = plus; 831132718Skan } 832132718Skan else 833132718Skan { 834132718Skan /* Otherwise, look for a free index register. Since we have 835132718Skan checked above that neither REG nor BASE are index registers, 836132718Skan if we find anything at all, it will be different from these 837132718Skan two registers. */ 838132718Skan for (i = first_index_reg; i <= last_index_reg; i++) 839132718Skan { 840132718Skan if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], 841132718Skan i) 842132718Skan && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES 843132718Skan && reg_state[i].store_ruid <= reg_state[regno].use_ruid 844169689Skan && hard_regno_nregs[i][GET_MODE (reg)] == 1) 845132718Skan { 846132718Skan rtx index_reg = gen_rtx_REG (GET_MODE (reg), i); 847132718Skan 848132718Skan const_reg = index_reg; 849132718Skan reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); 850132718Skan break; 851132718Skan } 852132718Skan } 853132718Skan } 854132718Skan 855132718Skan /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that 856132718Skan (REGY), i.e. BASE, is not clobbered before the last use we'll 857132718Skan create. */ 858132718Skan if (prev_set != 0 859132718Skan && GET_CODE (SET_SRC (prev_set)) == CONST_INT 860132718Skan && rtx_equal_p (SET_DEST (prev_set), reg) 861132718Skan && reg_state[regno].use_index >= 0 862132718Skan && (reg_state[REGNO (base)].store_ruid 863132718Skan <= reg_state[regno].use_ruid) 864132718Skan && reg_sum != 0) 865132718Skan { 866132718Skan int i; 867132718Skan 868132718Skan /* Change destination register and, if necessary, the 869132718Skan constant value in PREV, the constant loading instruction. */ 870132718Skan validate_change (prev, &SET_DEST (prev_set), const_reg, 1); 871132718Skan if (reg_state[regno].offset != const0_rtx) 872132718Skan validate_change (prev, 873132718Skan &SET_SRC (prev_set), 874132718Skan GEN_INT (INTVAL (SET_SRC (prev_set)) 875132718Skan + INTVAL (reg_state[regno].offset)), 876132718Skan 1); 877132718Skan 878132718Skan /* Now for every use of REG that we have recorded, replace REG 879132718Skan with REG_SUM. */ 880132718Skan for (i = reg_state[regno].use_index; 881132718Skan i < RELOAD_COMBINE_MAX_USES; i++) 882132718Skan validate_change (reg_state[regno].reg_use[i].insn, 883132718Skan reg_state[regno].reg_use[i].usep, 884132718Skan /* Each change must have its own 885132718Skan replacement. */ 886132718Skan copy_rtx (reg_sum), 1); 887132718Skan 888132718Skan if (apply_change_group ()) 889132718Skan { 890132718Skan rtx *np; 891132718Skan 892132718Skan /* Delete the reg-reg addition. */ 893132718Skan delete_insn (insn); 894132718Skan 895132718Skan if (reg_state[regno].offset != const0_rtx) 896132718Skan /* Previous REG_EQUIV / REG_EQUAL notes for PREV 897132718Skan are now invalid. */ 898132718Skan for (np = ®_NOTES (prev); *np;) 899132718Skan { 900132718Skan if (REG_NOTE_KIND (*np) == REG_EQUAL 901132718Skan || REG_NOTE_KIND (*np) == REG_EQUIV) 902132718Skan *np = XEXP (*np, 1); 903132718Skan else 904132718Skan np = &XEXP (*np, 1); 905132718Skan } 906132718Skan 907132718Skan reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; 908132718Skan reg_state[REGNO (const_reg)].store_ruid 909132718Skan = reload_combine_ruid; 910132718Skan continue; 911132718Skan } 912132718Skan } 913132718Skan } 914132718Skan 915132718Skan note_stores (PATTERN (insn), reload_combine_note_store, NULL); 916132718Skan 917169689Skan if (CALL_P (insn)) 918132718Skan { 919132718Skan rtx link; 920132718Skan 921132718Skan for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 922132718Skan if (call_used_regs[r]) 923132718Skan { 924132718Skan reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 925132718Skan reg_state[r].store_ruid = reload_combine_ruid; 926132718Skan } 927132718Skan 928132718Skan for (link = CALL_INSN_FUNCTION_USAGE (insn); link; 929132718Skan link = XEXP (link, 1)) 930132718Skan { 931132718Skan rtx usage_rtx = XEXP (XEXP (link, 0), 0); 932169689Skan if (REG_P (usage_rtx)) 933132718Skan { 934132718Skan unsigned int i; 935132718Skan unsigned int start_reg = REGNO (usage_rtx); 936132718Skan unsigned int num_regs = 937169689Skan hard_regno_nregs[start_reg][GET_MODE (usage_rtx)]; 938132718Skan unsigned int end_reg = start_reg + num_regs - 1; 939132718Skan for (i = start_reg; i <= end_reg; i++) 940132718Skan if (GET_CODE (XEXP (link, 0)) == CLOBBER) 941132718Skan { 942132718Skan reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; 943132718Skan reg_state[i].store_ruid = reload_combine_ruid; 944132718Skan } 945132718Skan else 946132718Skan reg_state[i].use_index = -1; 947132718Skan } 948132718Skan } 949132718Skan 950132718Skan } 951169689Skan else if (JUMP_P (insn) 952132718Skan && GET_CODE (PATTERN (insn)) != RETURN) 953132718Skan { 954132718Skan /* Non-spill registers might be used at the call destination in 955132718Skan some unknown fashion, so we have to mark the unknown use. */ 956132718Skan HARD_REG_SET *live; 957132718Skan 958132718Skan if ((condjump_p (insn) || condjump_in_parallel_p (insn)) 959132718Skan && JUMP_LABEL (insn)) 960132718Skan live = &LABEL_LIVE (JUMP_LABEL (insn)); 961132718Skan else 962132718Skan live = &ever_live_at_start; 963132718Skan 964132718Skan for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) 965132718Skan if (TEST_HARD_REG_BIT (*live, i)) 966132718Skan reg_state[i].use_index = -1; 967132718Skan } 968132718Skan 969132718Skan reload_combine_note_use (&PATTERN (insn), insn); 970132718Skan for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 971132718Skan { 972132718Skan if (REG_NOTE_KIND (note) == REG_INC 973169689Skan && REG_P (XEXP (note, 0))) 974132718Skan { 975132718Skan int regno = REGNO (XEXP (note, 0)); 976132718Skan 977132718Skan reg_state[regno].store_ruid = reload_combine_ruid; 978132718Skan reg_state[regno].use_index = -1; 979132718Skan } 980132718Skan } 981132718Skan } 982132718Skan 983132718Skan free (label_live); 984132718Skan} 985132718Skan 986132718Skan/* Check if DST is a register or a subreg of a register; if it is, 987132718Skan update reg_state[regno].store_ruid and reg_state[regno].use_index 988132718Skan accordingly. Called via note_stores from reload_combine. */ 989132718Skan 990132718Skanstatic void 991132718Skanreload_combine_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) 992132718Skan{ 993132718Skan int regno = 0; 994132718Skan int i; 995132718Skan enum machine_mode mode = GET_MODE (dst); 996132718Skan 997132718Skan if (GET_CODE (dst) == SUBREG) 998132718Skan { 999132718Skan regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)), 1000132718Skan GET_MODE (SUBREG_REG (dst)), 1001132718Skan SUBREG_BYTE (dst), 1002132718Skan GET_MODE (dst)); 1003132718Skan dst = SUBREG_REG (dst); 1004132718Skan } 1005169689Skan if (!REG_P (dst)) 1006132718Skan return; 1007132718Skan regno += REGNO (dst); 1008132718Skan 1009132718Skan /* note_stores might have stripped a STRICT_LOW_PART, so we have to be 1010132718Skan careful with registers / register parts that are not full words. 1011169689Skan Similarly for ZERO_EXTRACT. */ 1012132718Skan if (GET_CODE (set) != SET 1013132718Skan || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT 1014132718Skan || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART) 1015132718Skan { 1016169689Skan for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) 1017132718Skan { 1018132718Skan reg_state[i].use_index = -1; 1019132718Skan reg_state[i].store_ruid = reload_combine_ruid; 1020132718Skan } 1021132718Skan } 1022132718Skan else 1023132718Skan { 1024169689Skan for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) 1025132718Skan { 1026132718Skan reg_state[i].store_ruid = reload_combine_ruid; 1027132718Skan reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; 1028132718Skan } 1029132718Skan } 1030132718Skan} 1031132718Skan 1032132718Skan/* XP points to a piece of rtl that has to be checked for any uses of 1033132718Skan registers. 1034132718Skan *XP is the pattern of INSN, or a part of it. 1035132718Skan Called from reload_combine, and recursively by itself. */ 1036132718Skanstatic void 1037132718Skanreload_combine_note_use (rtx *xp, rtx insn) 1038132718Skan{ 1039132718Skan rtx x = *xp; 1040132718Skan enum rtx_code code = x->code; 1041132718Skan const char *fmt; 1042132718Skan int i, j; 1043132718Skan rtx offset = const0_rtx; /* For the REG case below. */ 1044132718Skan 1045132718Skan switch (code) 1046132718Skan { 1047132718Skan case SET: 1048169689Skan if (REG_P (SET_DEST (x))) 1049132718Skan { 1050132718Skan reload_combine_note_use (&SET_SRC (x), insn); 1051132718Skan return; 1052132718Skan } 1053132718Skan break; 1054132718Skan 1055132718Skan case USE: 1056132718Skan /* If this is the USE of a return value, we can't change it. */ 1057169689Skan if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0))) 1058132718Skan { 1059132718Skan /* Mark the return register as used in an unknown fashion. */ 1060132718Skan rtx reg = XEXP (x, 0); 1061132718Skan int regno = REGNO (reg); 1062169689Skan int nregs = hard_regno_nregs[regno][GET_MODE (reg)]; 1063132718Skan 1064132718Skan while (--nregs >= 0) 1065132718Skan reg_state[regno + nregs].use_index = -1; 1066132718Skan return; 1067132718Skan } 1068132718Skan break; 1069132718Skan 1070132718Skan case CLOBBER: 1071169689Skan if (REG_P (SET_DEST (x))) 1072132718Skan { 1073132718Skan /* No spurious CLOBBERs of pseudo registers may remain. */ 1074169689Skan gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER); 1075132718Skan return; 1076132718Skan } 1077132718Skan break; 1078132718Skan 1079132718Skan case PLUS: 1080132718Skan /* We are interested in (plus (reg) (const_int)) . */ 1081169689Skan if (!REG_P (XEXP (x, 0)) 1082132718Skan || GET_CODE (XEXP (x, 1)) != CONST_INT) 1083132718Skan break; 1084132718Skan offset = XEXP (x, 1); 1085132718Skan x = XEXP (x, 0); 1086132718Skan /* Fall through. */ 1087132718Skan case REG: 1088132718Skan { 1089132718Skan int regno = REGNO (x); 1090132718Skan int use_index; 1091132718Skan int nregs; 1092132718Skan 1093132718Skan /* No spurious USEs of pseudo registers may remain. */ 1094169689Skan gcc_assert (regno < FIRST_PSEUDO_REGISTER); 1095132718Skan 1096169689Skan nregs = hard_regno_nregs[regno][GET_MODE (x)]; 1097132718Skan 1098132718Skan /* We can't substitute into multi-hard-reg uses. */ 1099132718Skan if (nregs > 1) 1100132718Skan { 1101132718Skan while (--nregs >= 0) 1102132718Skan reg_state[regno + nregs].use_index = -1; 1103132718Skan return; 1104132718Skan } 1105132718Skan 1106132718Skan /* If this register is already used in some unknown fashion, we 1107132718Skan can't do anything. 1108132718Skan If we decrement the index from zero to -1, we can't store more 1109132718Skan uses, so this register becomes used in an unknown fashion. */ 1110132718Skan use_index = --reg_state[regno].use_index; 1111132718Skan if (use_index < 0) 1112132718Skan return; 1113132718Skan 1114132718Skan if (use_index != RELOAD_COMBINE_MAX_USES - 1) 1115132718Skan { 1116132718Skan /* We have found another use for a register that is already 1117132718Skan used later. Check if the offsets match; if not, mark the 1118132718Skan register as used in an unknown fashion. */ 1119132718Skan if (! rtx_equal_p (offset, reg_state[regno].offset)) 1120132718Skan { 1121132718Skan reg_state[regno].use_index = -1; 1122132718Skan return; 1123132718Skan } 1124132718Skan } 1125132718Skan else 1126132718Skan { 1127132718Skan /* This is the first use of this register we have seen since we 1128132718Skan marked it as dead. */ 1129132718Skan reg_state[regno].offset = offset; 1130132718Skan reg_state[regno].use_ruid = reload_combine_ruid; 1131132718Skan } 1132132718Skan reg_state[regno].reg_use[use_index].insn = insn; 1133132718Skan reg_state[regno].reg_use[use_index].usep = xp; 1134132718Skan return; 1135132718Skan } 1136132718Skan 1137132718Skan default: 1138132718Skan break; 1139132718Skan } 1140132718Skan 1141132718Skan /* Recursively process the components of X. */ 1142132718Skan fmt = GET_RTX_FORMAT (code); 1143132718Skan for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 1144132718Skan { 1145132718Skan if (fmt[i] == 'e') 1146132718Skan reload_combine_note_use (&XEXP (x, i), insn); 1147132718Skan else if (fmt[i] == 'E') 1148132718Skan { 1149132718Skan for (j = XVECLEN (x, i) - 1; j >= 0; j--) 1150132718Skan reload_combine_note_use (&XVECEXP (x, i, j), insn); 1151132718Skan } 1152132718Skan } 1153132718Skan} 1154132718Skan 1155132718Skan/* See if we can reduce the cost of a constant by replacing a move 1156132718Skan with an add. We track situations in which a register is set to a 1157132718Skan constant or to a register plus a constant. */ 1158132718Skan/* We cannot do our optimization across labels. Invalidating all the 1159132718Skan information about register contents we have would be costly, so we 1160132718Skan use move2add_last_label_luid to note where the label is and then 1161132718Skan later disable any optimization that would cross it. 1162132718Skan reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if 1163132718Skan reg_set_luid[n] is greater than move2add_last_label_luid. */ 1164132718Skanstatic int reg_set_luid[FIRST_PSEUDO_REGISTER]; 1165132718Skan 1166132718Skan/* If reg_base_reg[n] is negative, register n has been set to 1167132718Skan reg_offset[n] in mode reg_mode[n] . 1168132718Skan If reg_base_reg[n] is non-negative, register n has been set to the 1169132718Skan sum of reg_offset[n] and the value of register reg_base_reg[n] 1170132718Skan before reg_set_luid[n], calculated in mode reg_mode[n] . */ 1171132718Skanstatic HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER]; 1172132718Skanstatic int reg_base_reg[FIRST_PSEUDO_REGISTER]; 1173132718Skanstatic enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER]; 1174132718Skan 1175132718Skan/* move2add_luid is linearly increased while scanning the instructions 1176132718Skan from first to last. It is used to set reg_set_luid in 1177132718Skan reload_cse_move2add and move2add_note_store. */ 1178132718Skanstatic int move2add_luid; 1179132718Skan 1180132718Skan/* move2add_last_label_luid is set whenever a label is found. Labels 1181132718Skan invalidate all previously collected reg_offset data. */ 1182132718Skanstatic int move2add_last_label_luid; 1183132718Skan 1184132718Skan/* ??? We don't know how zero / sign extension is handled, hence we 1185132718Skan can't go from a narrower to a wider mode. */ 1186132718Skan#define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \ 1187132718Skan (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \ 1188132718Skan || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \ 1189132718Skan && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \ 1190132718Skan GET_MODE_BITSIZE (INMODE)))) 1191132718Skan 1192132718Skanstatic void 1193132718Skanreload_cse_move2add (rtx first) 1194132718Skan{ 1195132718Skan int i; 1196132718Skan rtx insn; 1197132718Skan 1198132718Skan for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) 1199132718Skan reg_set_luid[i] = 0; 1200132718Skan 1201132718Skan move2add_last_label_luid = 0; 1202132718Skan move2add_luid = 2; 1203132718Skan for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++) 1204132718Skan { 1205132718Skan rtx pat, note; 1206132718Skan 1207169689Skan if (LABEL_P (insn)) 1208132718Skan { 1209132718Skan move2add_last_label_luid = move2add_luid; 1210132718Skan /* We're going to increment move2add_luid twice after a 1211132718Skan label, so that we can use move2add_last_label_luid + 1 as 1212132718Skan the luid for constants. */ 1213132718Skan move2add_luid++; 1214132718Skan continue; 1215132718Skan } 1216132718Skan if (! INSN_P (insn)) 1217132718Skan continue; 1218132718Skan pat = PATTERN (insn); 1219132718Skan /* For simplicity, we only perform this optimization on 1220132718Skan straightforward SETs. */ 1221132718Skan if (GET_CODE (pat) == SET 1222169689Skan && REG_P (SET_DEST (pat))) 1223132718Skan { 1224132718Skan rtx reg = SET_DEST (pat); 1225132718Skan int regno = REGNO (reg); 1226132718Skan rtx src = SET_SRC (pat); 1227132718Skan 1228132718Skan /* Check if we have valid information on the contents of this 1229132718Skan register in the mode of REG. */ 1230132718Skan if (reg_set_luid[regno] > move2add_last_label_luid 1231132718Skan && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])) 1232132718Skan { 1233132718Skan /* Try to transform (set (REGX) (CONST_INT A)) 1234132718Skan ... 1235132718Skan (set (REGX) (CONST_INT B)) 1236132718Skan to 1237132718Skan (set (REGX) (CONST_INT A)) 1238132718Skan ... 1239132718Skan (set (REGX) (plus (REGX) (CONST_INT B-A))) 1240132718Skan or 1241132718Skan (set (REGX) (CONST_INT A)) 1242132718Skan ... 1243132718Skan (set (STRICT_LOW_PART (REGX)) (CONST_INT B)) 1244132718Skan */ 1245132718Skan 1246132718Skan if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0) 1247132718Skan { 1248169689Skan rtx new_src = gen_int_mode (INTVAL (src) - reg_offset[regno], 1249169689Skan GET_MODE (reg)); 1250132718Skan /* (set (reg) (plus (reg) (const_int 0))) is not canonical; 1251132718Skan use (set (reg) (reg)) instead. 1252132718Skan We don't delete this insn, nor do we convert it into a 1253132718Skan note, to avoid losing register notes or the return 1254132718Skan value flag. jump2 already knows how to get rid of 1255132718Skan no-op moves. */ 1256132718Skan if (new_src == const0_rtx) 1257132718Skan { 1258132718Skan /* If the constants are different, this is a 1259132718Skan truncation, that, if turned into (set (reg) 1260132718Skan (reg)), would be discarded. Maybe we should 1261132718Skan try a truncMN pattern? */ 1262132718Skan if (INTVAL (src) == reg_offset [regno]) 1263132718Skan validate_change (insn, &SET_SRC (pat), reg, 0); 1264132718Skan } 1265132718Skan else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET) 1266132718Skan && have_add2_insn (reg, new_src)) 1267132718Skan { 1268169689Skan rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); 1269169689Skan validate_change (insn, &SET_SRC (pat), tem, 0); 1270132718Skan } 1271169689Skan else if (GET_MODE (reg) != BImode) 1272132718Skan { 1273132718Skan enum machine_mode narrow_mode; 1274132718Skan for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 1275169689Skan narrow_mode != VOIDmode 1276169689Skan && narrow_mode != GET_MODE (reg); 1277132718Skan narrow_mode = GET_MODE_WIDER_MODE (narrow_mode)) 1278132718Skan { 1279132718Skan if (have_insn_for (STRICT_LOW_PART, narrow_mode) 1280132718Skan && ((reg_offset[regno] 1281132718Skan & ~GET_MODE_MASK (narrow_mode)) 1282132718Skan == (INTVAL (src) 1283132718Skan & ~GET_MODE_MASK (narrow_mode)))) 1284132718Skan { 1285132718Skan rtx narrow_reg = gen_rtx_REG (narrow_mode, 1286132718Skan REGNO (reg)); 1287169689Skan rtx narrow_src = gen_int_mode (INTVAL (src), 1288169689Skan narrow_mode); 1289132718Skan rtx new_set = 1290132718Skan gen_rtx_SET (VOIDmode, 1291132718Skan gen_rtx_STRICT_LOW_PART (VOIDmode, 1292132718Skan narrow_reg), 1293132718Skan narrow_src); 1294132718Skan if (validate_change (insn, &PATTERN (insn), 1295132718Skan new_set, 0)) 1296132718Skan break; 1297132718Skan } 1298132718Skan } 1299132718Skan } 1300132718Skan reg_set_luid[regno] = move2add_luid; 1301132718Skan reg_mode[regno] = GET_MODE (reg); 1302132718Skan reg_offset[regno] = INTVAL (src); 1303132718Skan continue; 1304132718Skan } 1305132718Skan 1306132718Skan /* Try to transform (set (REGX) (REGY)) 1307132718Skan (set (REGX) (PLUS (REGX) (CONST_INT A))) 1308132718Skan ... 1309132718Skan (set (REGX) (REGY)) 1310132718Skan (set (REGX) (PLUS (REGX) (CONST_INT B))) 1311132718Skan to 1312132718Skan (set (REGX) (REGY)) 1313132718Skan (set (REGX) (PLUS (REGX) (CONST_INT A))) 1314132718Skan ... 1315132718Skan (set (REGX) (plus (REGX) (CONST_INT B-A))) */ 1316169689Skan else if (REG_P (src) 1317132718Skan && reg_set_luid[regno] == reg_set_luid[REGNO (src)] 1318132718Skan && reg_base_reg[regno] == reg_base_reg[REGNO (src)] 1319132718Skan && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), 1320132718Skan reg_mode[REGNO (src)])) 1321132718Skan { 1322132718Skan rtx next = next_nonnote_insn (insn); 1323132718Skan rtx set = NULL_RTX; 1324132718Skan if (next) 1325132718Skan set = single_set (next); 1326132718Skan if (set 1327132718Skan && SET_DEST (set) == reg 1328132718Skan && GET_CODE (SET_SRC (set)) == PLUS 1329132718Skan && XEXP (SET_SRC (set), 0) == reg 1330132718Skan && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT) 1331132718Skan { 1332132718Skan rtx src3 = XEXP (SET_SRC (set), 1); 1333132718Skan HOST_WIDE_INT added_offset = INTVAL (src3); 1334132718Skan HOST_WIDE_INT base_offset = reg_offset[REGNO (src)]; 1335132718Skan HOST_WIDE_INT regno_offset = reg_offset[regno]; 1336132718Skan rtx new_src = 1337169689Skan gen_int_mode (added_offset 1338169689Skan + base_offset 1339169689Skan - regno_offset, 1340169689Skan GET_MODE (reg)); 1341132718Skan int success = 0; 1342132718Skan 1343132718Skan if (new_src == const0_rtx) 1344132718Skan /* See above why we create (set (reg) (reg)) here. */ 1345132718Skan success 1346132718Skan = validate_change (next, &SET_SRC (set), reg, 0); 1347132718Skan else if ((rtx_cost (new_src, PLUS) 1348132718Skan < COSTS_N_INSNS (1) + rtx_cost (src3, SET)) 1349132718Skan && have_add2_insn (reg, new_src)) 1350132718Skan { 1351132718Skan rtx newpat = gen_rtx_SET (VOIDmode, 1352132718Skan reg, 1353132718Skan gen_rtx_PLUS (GET_MODE (reg), 1354132718Skan reg, 1355132718Skan new_src)); 1356132718Skan success 1357132718Skan = validate_change (next, &PATTERN (next), 1358132718Skan newpat, 0); 1359132718Skan } 1360132718Skan if (success) 1361132718Skan delete_insn (insn); 1362132718Skan insn = next; 1363132718Skan reg_mode[regno] = GET_MODE (reg); 1364132718Skan reg_offset[regno] = 1365132718Skan trunc_int_for_mode (added_offset + base_offset, 1366132718Skan GET_MODE (reg)); 1367132718Skan continue; 1368132718Skan } 1369132718Skan } 1370132718Skan } 1371132718Skan } 1372132718Skan 1373132718Skan for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 1374132718Skan { 1375132718Skan if (REG_NOTE_KIND (note) == REG_INC 1376169689Skan && REG_P (XEXP (note, 0))) 1377132718Skan { 1378132718Skan /* Reset the information about this register. */ 1379132718Skan int regno = REGNO (XEXP (note, 0)); 1380132718Skan if (regno < FIRST_PSEUDO_REGISTER) 1381132718Skan reg_set_luid[regno] = 0; 1382132718Skan } 1383132718Skan } 1384132718Skan note_stores (PATTERN (insn), move2add_note_store, NULL); 1385132718Skan 1386132718Skan /* If INSN is a conditional branch, we try to extract an 1387132718Skan implicit set out of it. */ 1388169689Skan if (any_condjump_p (insn)) 1389132718Skan { 1390132718Skan rtx cnd = fis_get_condition (insn); 1391132718Skan 1392132718Skan if (cnd != NULL_RTX 1393132718Skan && GET_CODE (cnd) == NE 1394169689Skan && REG_P (XEXP (cnd, 0)) 1395169689Skan && !reg_set_p (XEXP (cnd, 0), insn) 1396132718Skan /* The following two checks, which are also in 1397132718Skan move2add_note_store, are intended to reduce the 1398132718Skan number of calls to gen_rtx_SET to avoid memory 1399132718Skan allocation if possible. */ 1400132718Skan && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0))) 1401169689Skan && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1 1402132718Skan && GET_CODE (XEXP (cnd, 1)) == CONST_INT) 1403132718Skan { 1404132718Skan rtx implicit_set = 1405132718Skan gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1)); 1406132718Skan move2add_note_store (SET_DEST (implicit_set), implicit_set, 0); 1407132718Skan } 1408132718Skan } 1409132718Skan 1410132718Skan /* If this is a CALL_INSN, all call used registers are stored with 1411132718Skan unknown values. */ 1412169689Skan if (CALL_P (insn)) 1413132718Skan { 1414132718Skan for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) 1415132718Skan { 1416132718Skan if (call_used_regs[i]) 1417132718Skan /* Reset the information about this register. */ 1418132718Skan reg_set_luid[i] = 0; 1419132718Skan } 1420132718Skan } 1421132718Skan } 1422132718Skan} 1423132718Skan 1424132718Skan/* SET is a SET or CLOBBER that sets DST. 1425132718Skan Update reg_set_luid, reg_offset and reg_base_reg accordingly. 1426132718Skan Called from reload_cse_move2add via note_stores. */ 1427132718Skan 1428132718Skanstatic void 1429132718Skanmove2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) 1430132718Skan{ 1431132718Skan unsigned int regno = 0; 1432132718Skan unsigned int i; 1433132718Skan enum machine_mode mode = GET_MODE (dst); 1434132718Skan 1435132718Skan if (GET_CODE (dst) == SUBREG) 1436132718Skan { 1437132718Skan regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)), 1438132718Skan GET_MODE (SUBREG_REG (dst)), 1439132718Skan SUBREG_BYTE (dst), 1440132718Skan GET_MODE (dst)); 1441132718Skan dst = SUBREG_REG (dst); 1442132718Skan } 1443132718Skan 1444132718Skan /* Some targets do argument pushes without adding REG_INC notes. */ 1445132718Skan 1446169689Skan if (MEM_P (dst)) 1447132718Skan { 1448132718Skan dst = XEXP (dst, 0); 1449132718Skan if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC 1450132718Skan || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC) 1451132718Skan reg_set_luid[REGNO (XEXP (dst, 0))] = 0; 1452132718Skan return; 1453132718Skan } 1454169689Skan if (!REG_P (dst)) 1455132718Skan return; 1456132718Skan 1457132718Skan regno += REGNO (dst); 1458132718Skan 1459169689Skan if (SCALAR_INT_MODE_P (GET_MODE (dst)) 1460169689Skan && hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET 1461132718Skan && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT 1462132718Skan && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART) 1463132718Skan { 1464132718Skan rtx src = SET_SRC (set); 1465132718Skan rtx base_reg; 1466132718Skan HOST_WIDE_INT offset; 1467132718Skan int base_regno; 1468132718Skan /* This may be different from mode, if SET_DEST (set) is a 1469132718Skan SUBREG. */ 1470132718Skan enum machine_mode dst_mode = GET_MODE (dst); 1471132718Skan 1472132718Skan switch (GET_CODE (src)) 1473132718Skan { 1474132718Skan case PLUS: 1475169689Skan if (REG_P (XEXP (src, 0))) 1476132718Skan { 1477132718Skan base_reg = XEXP (src, 0); 1478132718Skan 1479132718Skan if (GET_CODE (XEXP (src, 1)) == CONST_INT) 1480132718Skan offset = INTVAL (XEXP (src, 1)); 1481169689Skan else if (REG_P (XEXP (src, 1)) 1482132718Skan && (reg_set_luid[REGNO (XEXP (src, 1))] 1483132718Skan > move2add_last_label_luid) 1484132718Skan && (MODES_OK_FOR_MOVE2ADD 1485132718Skan (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))) 1486132718Skan { 1487132718Skan if (reg_base_reg[REGNO (XEXP (src, 1))] < 0) 1488132718Skan offset = reg_offset[REGNO (XEXP (src, 1))]; 1489132718Skan /* Maybe the first register is known to be a 1490132718Skan constant. */ 1491132718Skan else if (reg_set_luid[REGNO (base_reg)] 1492132718Skan > move2add_last_label_luid 1493132718Skan && (MODES_OK_FOR_MOVE2ADD 1494132718Skan (dst_mode, reg_mode[REGNO (XEXP (src, 1))])) 1495132718Skan && reg_base_reg[REGNO (base_reg)] < 0) 1496132718Skan { 1497132718Skan offset = reg_offset[REGNO (base_reg)]; 1498132718Skan base_reg = XEXP (src, 1); 1499132718Skan } 1500132718Skan else 1501132718Skan goto invalidate; 1502132718Skan } 1503132718Skan else 1504132718Skan goto invalidate; 1505132718Skan 1506132718Skan break; 1507132718Skan } 1508132718Skan 1509132718Skan goto invalidate; 1510132718Skan 1511132718Skan case REG: 1512132718Skan base_reg = src; 1513132718Skan offset = 0; 1514132718Skan break; 1515132718Skan 1516132718Skan case CONST_INT: 1517132718Skan /* Start tracking the register as a constant. */ 1518132718Skan reg_base_reg[regno] = -1; 1519132718Skan reg_offset[regno] = INTVAL (SET_SRC (set)); 1520132718Skan /* We assign the same luid to all registers set to constants. */ 1521132718Skan reg_set_luid[regno] = move2add_last_label_luid + 1; 1522132718Skan reg_mode[regno] = mode; 1523132718Skan return; 1524132718Skan 1525132718Skan default: 1526132718Skan invalidate: 1527132718Skan /* Invalidate the contents of the register. */ 1528132718Skan reg_set_luid[regno] = 0; 1529132718Skan return; 1530132718Skan } 1531132718Skan 1532132718Skan base_regno = REGNO (base_reg); 1533132718Skan /* If information about the base register is not valid, set it 1534132718Skan up as a new base register, pretending its value is known 1535132718Skan starting from the current insn. */ 1536132718Skan if (reg_set_luid[base_regno] <= move2add_last_label_luid) 1537132718Skan { 1538132718Skan reg_base_reg[base_regno] = base_regno; 1539132718Skan reg_offset[base_regno] = 0; 1540132718Skan reg_set_luid[base_regno] = move2add_luid; 1541132718Skan reg_mode[base_regno] = mode; 1542132718Skan } 1543132718Skan else if (! MODES_OK_FOR_MOVE2ADD (dst_mode, 1544132718Skan reg_mode[base_regno])) 1545132718Skan goto invalidate; 1546132718Skan 1547132718Skan reg_mode[regno] = mode; 1548132718Skan 1549132718Skan /* Copy base information from our base register. */ 1550132718Skan reg_set_luid[regno] = reg_set_luid[base_regno]; 1551132718Skan reg_base_reg[regno] = reg_base_reg[base_regno]; 1552132718Skan 1553132718Skan /* Compute the sum of the offsets or constants. */ 1554132718Skan reg_offset[regno] = trunc_int_for_mode (offset 1555132718Skan + reg_offset[base_regno], 1556132718Skan dst_mode); 1557132718Skan } 1558132718Skan else 1559132718Skan { 1560169689Skan unsigned int endregno = regno + hard_regno_nregs[regno][mode]; 1561132718Skan 1562132718Skan for (i = regno; i < endregno; i++) 1563132718Skan /* Reset the information about this register. */ 1564132718Skan reg_set_luid[i] = 0; 1565132718Skan } 1566132718Skan} 1567169689Skan 1568169689Skanstatic bool 1569169689Skangate_handle_postreload (void) 1570169689Skan{ 1571169689Skan return (optimize > 0); 1572169689Skan} 1573169689Skan 1574169689Skan 1575169689Skanstatic unsigned int 1576169689Skanrest_of_handle_postreload (void) 1577169689Skan{ 1578169689Skan /* Do a very simple CSE pass over just the hard registers. */ 1579169689Skan reload_cse_regs (get_insns ()); 1580169689Skan /* reload_cse_regs can eliminate potentially-trapping MEMs. 1581169689Skan Remove any EH edges associated with them. */ 1582169689Skan if (flag_non_call_exceptions) 1583169689Skan purge_all_dead_edges (); 1584169689Skan return 0; 1585169689Skan} 1586169689Skan 1587169689Skanstruct tree_opt_pass pass_postreload_cse = 1588169689Skan{ 1589169689Skan "postreload", /* name */ 1590169689Skan gate_handle_postreload, /* gate */ 1591169689Skan rest_of_handle_postreload, /* execute */ 1592169689Skan NULL, /* sub */ 1593169689Skan NULL, /* next */ 1594169689Skan 0, /* static_pass_number */ 1595169689Skan TV_RELOAD_CSE_REGS, /* tv_id */ 1596169689Skan 0, /* properties_required */ 1597169689Skan 0, /* properties_provided */ 1598169689Skan 0, /* properties_destroyed */ 1599169689Skan 0, /* todo_flags_start */ 1600169689Skan TODO_dump_func, /* todo_flags_finish */ 1601169689Skan 'o' /* letter */ 1602169689Skan}; 1603169689Skan 1604