1*e4b17023SJohn Marino /* Perform simple optimizations to clean up the result of reload. 2*e4b17023SJohn Marino Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 3*e4b17023SJohn Marino 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 4*e4b17023SJohn Marino 2010, 2011 Free Software Foundation, Inc. 5*e4b17023SJohn Marino 6*e4b17023SJohn Marino This file is part of GCC. 7*e4b17023SJohn Marino 8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later 11*e4b17023SJohn Marino version. 12*e4b17023SJohn Marino 13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16*e4b17023SJohn Marino for more details. 17*e4b17023SJohn Marino 18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 21*e4b17023SJohn Marino 22*e4b17023SJohn Marino #include "config.h" 23*e4b17023SJohn Marino #include "system.h" 24*e4b17023SJohn Marino #include "coretypes.h" 25*e4b17023SJohn Marino #include "tm.h" 26*e4b17023SJohn Marino 27*e4b17023SJohn Marino #include "machmode.h" 28*e4b17023SJohn Marino #include "hard-reg-set.h" 29*e4b17023SJohn Marino #include "rtl.h" 30*e4b17023SJohn Marino #include "tm_p.h" 31*e4b17023SJohn Marino #include "obstack.h" 32*e4b17023SJohn Marino #include "insn-config.h" 33*e4b17023SJohn Marino #include "flags.h" 34*e4b17023SJohn Marino #include "function.h" 35*e4b17023SJohn Marino #include "expr.h" 36*e4b17023SJohn Marino #include "optabs.h" 37*e4b17023SJohn Marino #include "regs.h" 38*e4b17023SJohn Marino #include "basic-block.h" 39*e4b17023SJohn Marino #include "reload.h" 40*e4b17023SJohn Marino #include "recog.h" 41*e4b17023SJohn Marino #include "output.h" 42*e4b17023SJohn Marino #include "cselib.h" 43*e4b17023SJohn Marino #include "diagnostic-core.h" 44*e4b17023SJohn Marino #include "except.h" 45*e4b17023SJohn Marino #include "tree.h" 46*e4b17023SJohn Marino #include "target.h" 47*e4b17023SJohn Marino #include "timevar.h" 48*e4b17023SJohn Marino #include "tree-pass.h" 49*e4b17023SJohn Marino #include "df.h" 50*e4b17023SJohn Marino #include "dbgcnt.h" 51*e4b17023SJohn Marino 52*e4b17023SJohn Marino static int reload_cse_noop_set_p (rtx); 53*e4b17023SJohn Marino static void reload_cse_simplify (rtx, rtx); 54*e4b17023SJohn Marino static void reload_cse_regs_1 (rtx); 55*e4b17023SJohn Marino static int reload_cse_simplify_set (rtx, rtx); 56*e4b17023SJohn Marino static int reload_cse_simplify_operands (rtx, rtx); 57*e4b17023SJohn Marino 58*e4b17023SJohn Marino static void reload_combine (void); 59*e4b17023SJohn Marino static void reload_combine_note_use (rtx *, rtx, int, rtx); 60*e4b17023SJohn Marino static void reload_combine_note_store (rtx, const_rtx, void *); 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino static bool reload_cse_move2add (rtx); 63*e4b17023SJohn Marino static void move2add_note_store (rtx, const_rtx, void *); 64*e4b17023SJohn Marino 65*e4b17023SJohn Marino /* Call cse / combine like post-reload optimization phases. 66*e4b17023SJohn Marino FIRST is the first instruction. */ 67*e4b17023SJohn Marino void 68*e4b17023SJohn Marino reload_cse_regs (rtx first ATTRIBUTE_UNUSED) 69*e4b17023SJohn Marino { 70*e4b17023SJohn Marino bool moves_converted; 71*e4b17023SJohn Marino reload_cse_regs_1 (first); 72*e4b17023SJohn Marino reload_combine (); 73*e4b17023SJohn Marino moves_converted = reload_cse_move2add (first); 74*e4b17023SJohn Marino if (flag_expensive_optimizations) 75*e4b17023SJohn Marino { 76*e4b17023SJohn Marino if (moves_converted) 77*e4b17023SJohn Marino reload_combine (); 78*e4b17023SJohn Marino reload_cse_regs_1 (first); 79*e4b17023SJohn Marino } 80*e4b17023SJohn Marino } 81*e4b17023SJohn Marino 82*e4b17023SJohn Marino /* See whether a single set SET is a noop. */ 83*e4b17023SJohn Marino static int 84*e4b17023SJohn Marino reload_cse_noop_set_p (rtx set) 85*e4b17023SJohn Marino { 86*e4b17023SJohn Marino if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set))) 87*e4b17023SJohn Marino return 0; 88*e4b17023SJohn Marino 89*e4b17023SJohn Marino return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set)); 90*e4b17023SJohn Marino } 91*e4b17023SJohn Marino 92*e4b17023SJohn Marino /* Try to simplify INSN. */ 93*e4b17023SJohn Marino static void 94*e4b17023SJohn Marino reload_cse_simplify (rtx insn, rtx testreg) 95*e4b17023SJohn Marino { 96*e4b17023SJohn Marino rtx body = PATTERN (insn); 97*e4b17023SJohn Marino 98*e4b17023SJohn Marino if (GET_CODE (body) == SET) 99*e4b17023SJohn Marino { 100*e4b17023SJohn Marino int count = 0; 101*e4b17023SJohn Marino 102*e4b17023SJohn Marino /* Simplify even if we may think it is a no-op. 103*e4b17023SJohn Marino We may think a memory load of a value smaller than WORD_SIZE 104*e4b17023SJohn Marino is redundant because we haven't taken into account possible 105*e4b17023SJohn Marino implicit extension. reload_cse_simplify_set() will bring 106*e4b17023SJohn Marino this out, so it's safer to simplify before we delete. */ 107*e4b17023SJohn Marino count += reload_cse_simplify_set (body, insn); 108*e4b17023SJohn Marino 109*e4b17023SJohn Marino if (!count && reload_cse_noop_set_p (body)) 110*e4b17023SJohn Marino { 111*e4b17023SJohn Marino rtx value = SET_DEST (body); 112*e4b17023SJohn Marino if (REG_P (value) 113*e4b17023SJohn Marino && ! REG_FUNCTION_VALUE_P (value)) 114*e4b17023SJohn Marino value = 0; 115*e4b17023SJohn Marino if (check_for_inc_dec (insn)) 116*e4b17023SJohn Marino delete_insn_and_edges (insn); 117*e4b17023SJohn Marino return; 118*e4b17023SJohn Marino } 119*e4b17023SJohn Marino 120*e4b17023SJohn Marino if (count > 0) 121*e4b17023SJohn Marino apply_change_group (); 122*e4b17023SJohn Marino else 123*e4b17023SJohn Marino reload_cse_simplify_operands (insn, testreg); 124*e4b17023SJohn Marino } 125*e4b17023SJohn Marino else if (GET_CODE (body) == PARALLEL) 126*e4b17023SJohn Marino { 127*e4b17023SJohn Marino int i; 128*e4b17023SJohn Marino int count = 0; 129*e4b17023SJohn Marino rtx value = NULL_RTX; 130*e4b17023SJohn Marino 131*e4b17023SJohn Marino /* Registers mentioned in the clobber list for an asm cannot be reused 132*e4b17023SJohn Marino within the body of the asm. Invalidate those registers now so that 133*e4b17023SJohn Marino we don't try to substitute values for them. */ 134*e4b17023SJohn Marino if (asm_noperands (body) >= 0) 135*e4b17023SJohn Marino { 136*e4b17023SJohn Marino for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 137*e4b17023SJohn Marino { 138*e4b17023SJohn Marino rtx part = XVECEXP (body, 0, i); 139*e4b17023SJohn Marino if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0))) 140*e4b17023SJohn Marino cselib_invalidate_rtx (XEXP (part, 0)); 141*e4b17023SJohn Marino } 142*e4b17023SJohn Marino } 143*e4b17023SJohn Marino 144*e4b17023SJohn Marino /* If every action in a PARALLEL is a noop, we can delete 145*e4b17023SJohn Marino the entire PARALLEL. */ 146*e4b17023SJohn Marino for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 147*e4b17023SJohn Marino { 148*e4b17023SJohn Marino rtx part = XVECEXP (body, 0, i); 149*e4b17023SJohn Marino if (GET_CODE (part) == SET) 150*e4b17023SJohn Marino { 151*e4b17023SJohn Marino if (! reload_cse_noop_set_p (part)) 152*e4b17023SJohn Marino break; 153*e4b17023SJohn Marino if (REG_P (SET_DEST (part)) 154*e4b17023SJohn Marino && REG_FUNCTION_VALUE_P (SET_DEST (part))) 155*e4b17023SJohn Marino { 156*e4b17023SJohn Marino if (value) 157*e4b17023SJohn Marino break; 158*e4b17023SJohn Marino value = SET_DEST (part); 159*e4b17023SJohn Marino } 160*e4b17023SJohn Marino } 161*e4b17023SJohn Marino else if (GET_CODE (part) != CLOBBER) 162*e4b17023SJohn Marino break; 163*e4b17023SJohn Marino } 164*e4b17023SJohn Marino 165*e4b17023SJohn Marino if (i < 0) 166*e4b17023SJohn Marino { 167*e4b17023SJohn Marino if (check_for_inc_dec (insn)) 168*e4b17023SJohn Marino delete_insn_and_edges (insn); 169*e4b17023SJohn Marino /* We're done with this insn. */ 170*e4b17023SJohn Marino return; 171*e4b17023SJohn Marino } 172*e4b17023SJohn Marino 173*e4b17023SJohn Marino /* It's not a no-op, but we can try to simplify it. */ 174*e4b17023SJohn Marino for (i = XVECLEN (body, 0) - 1; i >= 0; --i) 175*e4b17023SJohn Marino if (GET_CODE (XVECEXP (body, 0, i)) == SET) 176*e4b17023SJohn Marino count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn); 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino if (count > 0) 179*e4b17023SJohn Marino apply_change_group (); 180*e4b17023SJohn Marino else 181*e4b17023SJohn Marino reload_cse_simplify_operands (insn, testreg); 182*e4b17023SJohn Marino } 183*e4b17023SJohn Marino } 184*e4b17023SJohn Marino 185*e4b17023SJohn Marino /* Do a very simple CSE pass over the hard registers. 186*e4b17023SJohn Marino 187*e4b17023SJohn Marino This function detects no-op moves where we happened to assign two 188*e4b17023SJohn Marino different pseudo-registers to the same hard register, and then 189*e4b17023SJohn Marino copied one to the other. Reload will generate a useless 190*e4b17023SJohn Marino instruction copying a register to itself. 191*e4b17023SJohn Marino 192*e4b17023SJohn Marino This function also detects cases where we load a value from memory 193*e4b17023SJohn Marino into two different registers, and (if memory is more expensive than 194*e4b17023SJohn Marino registers) changes it to simply copy the first register into the 195*e4b17023SJohn Marino second register. 196*e4b17023SJohn Marino 197*e4b17023SJohn Marino Another optimization is performed that scans the operands of each 198*e4b17023SJohn Marino instruction to see whether the value is already available in a 199*e4b17023SJohn Marino hard register. It then replaces the operand with the hard register 200*e4b17023SJohn Marino if possible, much like an optional reload would. */ 201*e4b17023SJohn Marino 202*e4b17023SJohn Marino static void 203*e4b17023SJohn Marino reload_cse_regs_1 (rtx first) 204*e4b17023SJohn Marino { 205*e4b17023SJohn Marino rtx insn; 206*e4b17023SJohn Marino rtx testreg = gen_rtx_REG (VOIDmode, -1); 207*e4b17023SJohn Marino 208*e4b17023SJohn Marino cselib_init (CSELIB_RECORD_MEMORY); 209*e4b17023SJohn Marino init_alias_analysis (); 210*e4b17023SJohn Marino 211*e4b17023SJohn Marino for (insn = first; insn; insn = NEXT_INSN (insn)) 212*e4b17023SJohn Marino { 213*e4b17023SJohn Marino if (INSN_P (insn)) 214*e4b17023SJohn Marino reload_cse_simplify (insn, testreg); 215*e4b17023SJohn Marino 216*e4b17023SJohn Marino cselib_process_insn (insn); 217*e4b17023SJohn Marino } 218*e4b17023SJohn Marino 219*e4b17023SJohn Marino /* Clean up. */ 220*e4b17023SJohn Marino end_alias_analysis (); 221*e4b17023SJohn Marino cselib_finish (); 222*e4b17023SJohn Marino } 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino /* Try to simplify a single SET instruction. SET is the set pattern. 225*e4b17023SJohn Marino INSN is the instruction it came from. 226*e4b17023SJohn Marino This function only handles one case: if we set a register to a value 227*e4b17023SJohn Marino which is not a register, we try to find that value in some other register 228*e4b17023SJohn Marino and change the set into a register copy. */ 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino static int 231*e4b17023SJohn Marino reload_cse_simplify_set (rtx set, rtx insn) 232*e4b17023SJohn Marino { 233*e4b17023SJohn Marino int did_change = 0; 234*e4b17023SJohn Marino int dreg; 235*e4b17023SJohn Marino rtx src; 236*e4b17023SJohn Marino reg_class_t dclass; 237*e4b17023SJohn Marino int old_cost; 238*e4b17023SJohn Marino cselib_val *val; 239*e4b17023SJohn Marino struct elt_loc_list *l; 240*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 241*e4b17023SJohn Marino enum rtx_code extend_op = UNKNOWN; 242*e4b17023SJohn Marino #endif 243*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 244*e4b17023SJohn Marino 245*e4b17023SJohn Marino dreg = true_regnum (SET_DEST (set)); 246*e4b17023SJohn Marino if (dreg < 0) 247*e4b17023SJohn Marino return 0; 248*e4b17023SJohn Marino 249*e4b17023SJohn Marino src = SET_SRC (set); 250*e4b17023SJohn Marino if (side_effects_p (src) || true_regnum (src) >= 0) 251*e4b17023SJohn Marino return 0; 252*e4b17023SJohn Marino 253*e4b17023SJohn Marino dclass = REGNO_REG_CLASS (dreg); 254*e4b17023SJohn Marino 255*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 256*e4b17023SJohn Marino /* When replacing a memory with a register, we need to honor assumptions 257*e4b17023SJohn Marino that combine made wrt the contents of sign bits. We'll do this by 258*e4b17023SJohn Marino generating an extend instruction instead of a reg->reg copy. Thus 259*e4b17023SJohn Marino the destination must be a register that we can widen. */ 260*e4b17023SJohn Marino if (MEM_P (src) 261*e4b17023SJohn Marino && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD 262*e4b17023SJohn Marino && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN 263*e4b17023SJohn Marino && !REG_P (SET_DEST (set))) 264*e4b17023SJohn Marino return 0; 265*e4b17023SJohn Marino #endif 266*e4b17023SJohn Marino 267*e4b17023SJohn Marino val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode); 268*e4b17023SJohn Marino if (! val) 269*e4b17023SJohn Marino return 0; 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino /* If memory loads are cheaper than register copies, don't change them. */ 272*e4b17023SJohn Marino if (MEM_P (src)) 273*e4b17023SJohn Marino old_cost = memory_move_cost (GET_MODE (src), dclass, true); 274*e4b17023SJohn Marino else if (REG_P (src)) 275*e4b17023SJohn Marino old_cost = register_move_cost (GET_MODE (src), 276*e4b17023SJohn Marino REGNO_REG_CLASS (REGNO (src)), dclass); 277*e4b17023SJohn Marino else 278*e4b17023SJohn Marino old_cost = set_src_cost (src, speed); 279*e4b17023SJohn Marino 280*e4b17023SJohn Marino for (l = val->locs; l; l = l->next) 281*e4b17023SJohn Marino { 282*e4b17023SJohn Marino rtx this_rtx = l->loc; 283*e4b17023SJohn Marino int this_cost; 284*e4b17023SJohn Marino 285*e4b17023SJohn Marino if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0)) 286*e4b17023SJohn Marino { 287*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 288*e4b17023SJohn Marino if (extend_op != UNKNOWN) 289*e4b17023SJohn Marino { 290*e4b17023SJohn Marino HOST_WIDE_INT this_val; 291*e4b17023SJohn Marino 292*e4b17023SJohn Marino /* ??? I'm lazy and don't wish to handle CONST_DOUBLE. Other 293*e4b17023SJohn Marino constants, such as SYMBOL_REF, cannot be extended. */ 294*e4b17023SJohn Marino if (!CONST_INT_P (this_rtx)) 295*e4b17023SJohn Marino continue; 296*e4b17023SJohn Marino 297*e4b17023SJohn Marino this_val = INTVAL (this_rtx); 298*e4b17023SJohn Marino switch (extend_op) 299*e4b17023SJohn Marino { 300*e4b17023SJohn Marino case ZERO_EXTEND: 301*e4b17023SJohn Marino this_val &= GET_MODE_MASK (GET_MODE (src)); 302*e4b17023SJohn Marino break; 303*e4b17023SJohn Marino case SIGN_EXTEND: 304*e4b17023SJohn Marino /* ??? In theory we're already extended. */ 305*e4b17023SJohn Marino if (this_val == trunc_int_for_mode (this_val, GET_MODE (src))) 306*e4b17023SJohn Marino break; 307*e4b17023SJohn Marino default: 308*e4b17023SJohn Marino gcc_unreachable (); 309*e4b17023SJohn Marino } 310*e4b17023SJohn Marino this_rtx = GEN_INT (this_val); 311*e4b17023SJohn Marino } 312*e4b17023SJohn Marino #endif 313*e4b17023SJohn Marino this_cost = set_src_cost (this_rtx, speed); 314*e4b17023SJohn Marino } 315*e4b17023SJohn Marino else if (REG_P (this_rtx)) 316*e4b17023SJohn Marino { 317*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 318*e4b17023SJohn Marino if (extend_op != UNKNOWN) 319*e4b17023SJohn Marino { 320*e4b17023SJohn Marino this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx); 321*e4b17023SJohn Marino this_cost = set_src_cost (this_rtx, speed); 322*e4b17023SJohn Marino } 323*e4b17023SJohn Marino else 324*e4b17023SJohn Marino #endif 325*e4b17023SJohn Marino this_cost = register_move_cost (GET_MODE (this_rtx), 326*e4b17023SJohn Marino REGNO_REG_CLASS (REGNO (this_rtx)), 327*e4b17023SJohn Marino dclass); 328*e4b17023SJohn Marino } 329*e4b17023SJohn Marino else 330*e4b17023SJohn Marino continue; 331*e4b17023SJohn Marino 332*e4b17023SJohn Marino /* If equal costs, prefer registers over anything else. That 333*e4b17023SJohn Marino tends to lead to smaller instructions on some machines. */ 334*e4b17023SJohn Marino if (this_cost < old_cost 335*e4b17023SJohn Marino || (this_cost == old_cost 336*e4b17023SJohn Marino && REG_P (this_rtx) 337*e4b17023SJohn Marino && !REG_P (SET_SRC (set)))) 338*e4b17023SJohn Marino { 339*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 340*e4b17023SJohn Marino if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD 341*e4b17023SJohn Marino && extend_op != UNKNOWN 342*e4b17023SJohn Marino #ifdef CANNOT_CHANGE_MODE_CLASS 343*e4b17023SJohn Marino && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)), 344*e4b17023SJohn Marino word_mode, 345*e4b17023SJohn Marino REGNO_REG_CLASS (REGNO (SET_DEST (set)))) 346*e4b17023SJohn Marino #endif 347*e4b17023SJohn Marino ) 348*e4b17023SJohn Marino { 349*e4b17023SJohn Marino rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set))); 350*e4b17023SJohn Marino ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set)); 351*e4b17023SJohn Marino validate_change (insn, &SET_DEST (set), wide_dest, 1); 352*e4b17023SJohn Marino } 353*e4b17023SJohn Marino #endif 354*e4b17023SJohn Marino 355*e4b17023SJohn Marino validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1); 356*e4b17023SJohn Marino old_cost = this_cost, did_change = 1; 357*e4b17023SJohn Marino } 358*e4b17023SJohn Marino } 359*e4b17023SJohn Marino 360*e4b17023SJohn Marino return did_change; 361*e4b17023SJohn Marino } 362*e4b17023SJohn Marino 363*e4b17023SJohn Marino /* Try to replace operands in INSN with equivalent values that are already 364*e4b17023SJohn Marino in registers. This can be viewed as optional reloading. 365*e4b17023SJohn Marino 366*e4b17023SJohn Marino For each non-register operand in the insn, see if any hard regs are 367*e4b17023SJohn Marino known to be equivalent to that operand. Record the alternatives which 368*e4b17023SJohn Marino can accept these hard registers. Among all alternatives, select the 369*e4b17023SJohn Marino ones which are better or equal to the one currently matching, where 370*e4b17023SJohn Marino "better" is in terms of '?' and '!' constraints. Among the remaining 371*e4b17023SJohn Marino alternatives, select the one which replaces most operands with 372*e4b17023SJohn Marino hard registers. */ 373*e4b17023SJohn Marino 374*e4b17023SJohn Marino static int 375*e4b17023SJohn Marino reload_cse_simplify_operands (rtx insn, rtx testreg) 376*e4b17023SJohn Marino { 377*e4b17023SJohn Marino int i, j; 378*e4b17023SJohn Marino 379*e4b17023SJohn Marino /* For each operand, all registers that are equivalent to it. */ 380*e4b17023SJohn Marino HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS]; 381*e4b17023SJohn Marino 382*e4b17023SJohn Marino const char *constraints[MAX_RECOG_OPERANDS]; 383*e4b17023SJohn Marino 384*e4b17023SJohn Marino /* Vector recording how bad an alternative is. */ 385*e4b17023SJohn Marino int *alternative_reject; 386*e4b17023SJohn Marino /* Vector recording how many registers can be introduced by choosing 387*e4b17023SJohn Marino this alternative. */ 388*e4b17023SJohn Marino int *alternative_nregs; 389*e4b17023SJohn Marino /* Array of vectors recording, for each operand and each alternative, 390*e4b17023SJohn Marino which hard register to substitute, or -1 if the operand should be 391*e4b17023SJohn Marino left as it is. */ 392*e4b17023SJohn Marino int *op_alt_regno[MAX_RECOG_OPERANDS]; 393*e4b17023SJohn Marino /* Array of alternatives, sorted in order of decreasing desirability. */ 394*e4b17023SJohn Marino int *alternative_order; 395*e4b17023SJohn Marino 396*e4b17023SJohn Marino extract_insn (insn); 397*e4b17023SJohn Marino 398*e4b17023SJohn Marino if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0) 399*e4b17023SJohn Marino return 0; 400*e4b17023SJohn Marino 401*e4b17023SJohn Marino /* Figure out which alternative currently matches. */ 402*e4b17023SJohn Marino if (! constrain_operands (1)) 403*e4b17023SJohn Marino fatal_insn_not_found (insn); 404*e4b17023SJohn Marino 405*e4b17023SJohn Marino alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives); 406*e4b17023SJohn Marino alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives); 407*e4b17023SJohn Marino alternative_order = XALLOCAVEC (int, recog_data.n_alternatives); 408*e4b17023SJohn Marino memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int)); 409*e4b17023SJohn Marino memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int)); 410*e4b17023SJohn Marino 411*e4b17023SJohn Marino /* For each operand, find out which regs are equivalent. */ 412*e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++) 413*e4b17023SJohn Marino { 414*e4b17023SJohn Marino cselib_val *v; 415*e4b17023SJohn Marino struct elt_loc_list *l; 416*e4b17023SJohn Marino rtx op; 417*e4b17023SJohn Marino 418*e4b17023SJohn Marino CLEAR_HARD_REG_SET (equiv_regs[i]); 419*e4b17023SJohn Marino 420*e4b17023SJohn Marino /* cselib blows up on CODE_LABELs. Trying to fix that doesn't seem 421*e4b17023SJohn Marino right, so avoid the problem here. Likewise if we have a constant 422*e4b17023SJohn Marino and the insn pattern doesn't tell us the mode we need. */ 423*e4b17023SJohn Marino if (LABEL_P (recog_data.operand[i]) 424*e4b17023SJohn Marino || (CONSTANT_P (recog_data.operand[i]) 425*e4b17023SJohn Marino && recog_data.operand_mode[i] == VOIDmode)) 426*e4b17023SJohn Marino continue; 427*e4b17023SJohn Marino 428*e4b17023SJohn Marino op = recog_data.operand[i]; 429*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 430*e4b17023SJohn Marino if (MEM_P (op) 431*e4b17023SJohn Marino && GET_MODE_BITSIZE (GET_MODE (op)) < BITS_PER_WORD 432*e4b17023SJohn Marino && LOAD_EXTEND_OP (GET_MODE (op)) != UNKNOWN) 433*e4b17023SJohn Marino { 434*e4b17023SJohn Marino rtx set = single_set (insn); 435*e4b17023SJohn Marino 436*e4b17023SJohn Marino /* We might have multiple sets, some of which do implicit 437*e4b17023SJohn Marino extension. Punt on this for now. */ 438*e4b17023SJohn Marino if (! set) 439*e4b17023SJohn Marino continue; 440*e4b17023SJohn Marino /* If the destination is also a MEM or a STRICT_LOW_PART, no 441*e4b17023SJohn Marino extension applies. 442*e4b17023SJohn Marino Also, if there is an explicit extension, we don't have to 443*e4b17023SJohn Marino worry about an implicit one. */ 444*e4b17023SJohn Marino else if (MEM_P (SET_DEST (set)) 445*e4b17023SJohn Marino || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART 446*e4b17023SJohn Marino || GET_CODE (SET_SRC (set)) == ZERO_EXTEND 447*e4b17023SJohn Marino || GET_CODE (SET_SRC (set)) == SIGN_EXTEND) 448*e4b17023SJohn Marino ; /* Continue ordinary processing. */ 449*e4b17023SJohn Marino #ifdef CANNOT_CHANGE_MODE_CLASS 450*e4b17023SJohn Marino /* If the register cannot change mode to word_mode, it follows that 451*e4b17023SJohn Marino it cannot have been used in word_mode. */ 452*e4b17023SJohn Marino else if (REG_P (SET_DEST (set)) 453*e4b17023SJohn Marino && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)), 454*e4b17023SJohn Marino word_mode, 455*e4b17023SJohn Marino REGNO_REG_CLASS (REGNO (SET_DEST (set))))) 456*e4b17023SJohn Marino ; /* Continue ordinary processing. */ 457*e4b17023SJohn Marino #endif 458*e4b17023SJohn Marino /* If this is a straight load, make the extension explicit. */ 459*e4b17023SJohn Marino else if (REG_P (SET_DEST (set)) 460*e4b17023SJohn Marino && recog_data.n_operands == 2 461*e4b17023SJohn Marino && SET_SRC (set) == op 462*e4b17023SJohn Marino && SET_DEST (set) == recog_data.operand[1-i]) 463*e4b17023SJohn Marino { 464*e4b17023SJohn Marino validate_change (insn, recog_data.operand_loc[i], 465*e4b17023SJohn Marino gen_rtx_fmt_e (LOAD_EXTEND_OP (GET_MODE (op)), 466*e4b17023SJohn Marino word_mode, op), 467*e4b17023SJohn Marino 1); 468*e4b17023SJohn Marino validate_change (insn, recog_data.operand_loc[1-i], 469*e4b17023SJohn Marino gen_rtx_REG (word_mode, REGNO (SET_DEST (set))), 470*e4b17023SJohn Marino 1); 471*e4b17023SJohn Marino if (! apply_change_group ()) 472*e4b17023SJohn Marino return 0; 473*e4b17023SJohn Marino return reload_cse_simplify_operands (insn, testreg); 474*e4b17023SJohn Marino } 475*e4b17023SJohn Marino else 476*e4b17023SJohn Marino /* ??? There might be arithmetic operations with memory that are 477*e4b17023SJohn Marino safe to optimize, but is it worth the trouble? */ 478*e4b17023SJohn Marino continue; 479*e4b17023SJohn Marino } 480*e4b17023SJohn Marino #endif /* LOAD_EXTEND_OP */ 481*e4b17023SJohn Marino if (side_effects_p (op)) 482*e4b17023SJohn Marino continue; 483*e4b17023SJohn Marino v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode); 484*e4b17023SJohn Marino if (! v) 485*e4b17023SJohn Marino continue; 486*e4b17023SJohn Marino 487*e4b17023SJohn Marino for (l = v->locs; l; l = l->next) 488*e4b17023SJohn Marino if (REG_P (l->loc)) 489*e4b17023SJohn Marino SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc)); 490*e4b17023SJohn Marino } 491*e4b17023SJohn Marino 492*e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++) 493*e4b17023SJohn Marino { 494*e4b17023SJohn Marino enum machine_mode mode; 495*e4b17023SJohn Marino int regno; 496*e4b17023SJohn Marino const char *p; 497*e4b17023SJohn Marino 498*e4b17023SJohn Marino op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives); 499*e4b17023SJohn Marino for (j = 0; j < recog_data.n_alternatives; j++) 500*e4b17023SJohn Marino op_alt_regno[i][j] = -1; 501*e4b17023SJohn Marino 502*e4b17023SJohn Marino p = constraints[i] = recog_data.constraints[i]; 503*e4b17023SJohn Marino mode = recog_data.operand_mode[i]; 504*e4b17023SJohn Marino 505*e4b17023SJohn Marino /* Add the reject values for each alternative given by the constraints 506*e4b17023SJohn Marino for this operand. */ 507*e4b17023SJohn Marino j = 0; 508*e4b17023SJohn Marino while (*p != '\0') 509*e4b17023SJohn Marino { 510*e4b17023SJohn Marino char c = *p++; 511*e4b17023SJohn Marino if (c == ',') 512*e4b17023SJohn Marino j++; 513*e4b17023SJohn Marino else if (c == '?') 514*e4b17023SJohn Marino alternative_reject[j] += 3; 515*e4b17023SJohn Marino else if (c == '!') 516*e4b17023SJohn Marino alternative_reject[j] += 300; 517*e4b17023SJohn Marino } 518*e4b17023SJohn Marino 519*e4b17023SJohn Marino /* We won't change operands which are already registers. We 520*e4b17023SJohn Marino also don't want to modify output operands. */ 521*e4b17023SJohn Marino regno = true_regnum (recog_data.operand[i]); 522*e4b17023SJohn Marino if (regno >= 0 523*e4b17023SJohn Marino || constraints[i][0] == '=' 524*e4b17023SJohn Marino || constraints[i][0] == '+') 525*e4b17023SJohn Marino continue; 526*e4b17023SJohn Marino 527*e4b17023SJohn Marino for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 528*e4b17023SJohn Marino { 529*e4b17023SJohn Marino enum reg_class rclass = NO_REGS; 530*e4b17023SJohn Marino 531*e4b17023SJohn Marino if (! TEST_HARD_REG_BIT (equiv_regs[i], regno)) 532*e4b17023SJohn Marino continue; 533*e4b17023SJohn Marino 534*e4b17023SJohn Marino SET_REGNO_RAW (testreg, regno); 535*e4b17023SJohn Marino PUT_MODE (testreg, mode); 536*e4b17023SJohn Marino 537*e4b17023SJohn Marino /* We found a register equal to this operand. Now look for all 538*e4b17023SJohn Marino alternatives that can accept this register and have not been 539*e4b17023SJohn Marino assigned a register they can use yet. */ 540*e4b17023SJohn Marino j = 0; 541*e4b17023SJohn Marino p = constraints[i]; 542*e4b17023SJohn Marino for (;;) 543*e4b17023SJohn Marino { 544*e4b17023SJohn Marino char c = *p; 545*e4b17023SJohn Marino 546*e4b17023SJohn Marino switch (c) 547*e4b17023SJohn Marino { 548*e4b17023SJohn Marino case '=': case '+': case '?': 549*e4b17023SJohn Marino case '#': case '&': case '!': 550*e4b17023SJohn Marino case '*': case '%': 551*e4b17023SJohn Marino case '0': case '1': case '2': case '3': case '4': 552*e4b17023SJohn Marino case '5': case '6': case '7': case '8': case '9': 553*e4b17023SJohn Marino case '<': case '>': case 'V': case 'o': 554*e4b17023SJohn Marino case 'E': case 'F': case 'G': case 'H': 555*e4b17023SJohn Marino case 's': case 'i': case 'n': 556*e4b17023SJohn Marino case 'I': case 'J': case 'K': case 'L': 557*e4b17023SJohn Marino case 'M': case 'N': case 'O': case 'P': 558*e4b17023SJohn Marino case 'p': case 'X': case TARGET_MEM_CONSTRAINT: 559*e4b17023SJohn Marino /* These don't say anything we care about. */ 560*e4b17023SJohn Marino break; 561*e4b17023SJohn Marino 562*e4b17023SJohn Marino case 'g': case 'r': 563*e4b17023SJohn Marino rclass = reg_class_subunion[(int) rclass][(int) GENERAL_REGS]; 564*e4b17023SJohn Marino break; 565*e4b17023SJohn Marino 566*e4b17023SJohn Marino default: 567*e4b17023SJohn Marino rclass 568*e4b17023SJohn Marino = (reg_class_subunion 569*e4b17023SJohn Marino [(int) rclass] 570*e4b17023SJohn Marino [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]); 571*e4b17023SJohn Marino break; 572*e4b17023SJohn Marino 573*e4b17023SJohn Marino case ',': case '\0': 574*e4b17023SJohn Marino /* See if REGNO fits this alternative, and set it up as the 575*e4b17023SJohn Marino replacement register if we don't have one for this 576*e4b17023SJohn Marino alternative yet and the operand being replaced is not 577*e4b17023SJohn Marino a cheap CONST_INT. */ 578*e4b17023SJohn Marino if (op_alt_regno[i][j] == -1 579*e4b17023SJohn Marino && recog_data.alternative_enabled_p[j] 580*e4b17023SJohn Marino && reg_fits_class_p (testreg, rclass, 0, mode) 581*e4b17023SJohn Marino && (!CONST_INT_P (recog_data.operand[i]) 582*e4b17023SJohn Marino || (set_src_cost (recog_data.operand[i], 583*e4b17023SJohn Marino optimize_bb_for_speed_p 584*e4b17023SJohn Marino (BLOCK_FOR_INSN (insn))) 585*e4b17023SJohn Marino > set_src_cost (testreg, 586*e4b17023SJohn Marino optimize_bb_for_speed_p 587*e4b17023SJohn Marino (BLOCK_FOR_INSN (insn)))))) 588*e4b17023SJohn Marino { 589*e4b17023SJohn Marino alternative_nregs[j]++; 590*e4b17023SJohn Marino op_alt_regno[i][j] = regno; 591*e4b17023SJohn Marino } 592*e4b17023SJohn Marino j++; 593*e4b17023SJohn Marino rclass = NO_REGS; 594*e4b17023SJohn Marino break; 595*e4b17023SJohn Marino } 596*e4b17023SJohn Marino p += CONSTRAINT_LEN (c, p); 597*e4b17023SJohn Marino 598*e4b17023SJohn Marino if (c == '\0') 599*e4b17023SJohn Marino break; 600*e4b17023SJohn Marino } 601*e4b17023SJohn Marino } 602*e4b17023SJohn Marino } 603*e4b17023SJohn Marino 604*e4b17023SJohn Marino /* Record all alternatives which are better or equal to the currently 605*e4b17023SJohn Marino matching one in the alternative_order array. */ 606*e4b17023SJohn Marino for (i = j = 0; i < recog_data.n_alternatives; i++) 607*e4b17023SJohn Marino if (alternative_reject[i] <= alternative_reject[which_alternative]) 608*e4b17023SJohn Marino alternative_order[j++] = i; 609*e4b17023SJohn Marino recog_data.n_alternatives = j; 610*e4b17023SJohn Marino 611*e4b17023SJohn Marino /* Sort it. Given a small number of alternatives, a dumb algorithm 612*e4b17023SJohn Marino won't hurt too much. */ 613*e4b17023SJohn Marino for (i = 0; i < recog_data.n_alternatives - 1; i++) 614*e4b17023SJohn Marino { 615*e4b17023SJohn Marino int best = i; 616*e4b17023SJohn Marino int best_reject = alternative_reject[alternative_order[i]]; 617*e4b17023SJohn Marino int best_nregs = alternative_nregs[alternative_order[i]]; 618*e4b17023SJohn Marino int tmp; 619*e4b17023SJohn Marino 620*e4b17023SJohn Marino for (j = i + 1; j < recog_data.n_alternatives; j++) 621*e4b17023SJohn Marino { 622*e4b17023SJohn Marino int this_reject = alternative_reject[alternative_order[j]]; 623*e4b17023SJohn Marino int this_nregs = alternative_nregs[alternative_order[j]]; 624*e4b17023SJohn Marino 625*e4b17023SJohn Marino if (this_reject < best_reject 626*e4b17023SJohn Marino || (this_reject == best_reject && this_nregs > best_nregs)) 627*e4b17023SJohn Marino { 628*e4b17023SJohn Marino best = j; 629*e4b17023SJohn Marino best_reject = this_reject; 630*e4b17023SJohn Marino best_nregs = this_nregs; 631*e4b17023SJohn Marino } 632*e4b17023SJohn Marino } 633*e4b17023SJohn Marino 634*e4b17023SJohn Marino tmp = alternative_order[best]; 635*e4b17023SJohn Marino alternative_order[best] = alternative_order[i]; 636*e4b17023SJohn Marino alternative_order[i] = tmp; 637*e4b17023SJohn Marino } 638*e4b17023SJohn Marino 639*e4b17023SJohn Marino /* Substitute the operands as determined by op_alt_regno for the best 640*e4b17023SJohn Marino alternative. */ 641*e4b17023SJohn Marino j = alternative_order[0]; 642*e4b17023SJohn Marino 643*e4b17023SJohn Marino for (i = 0; i < recog_data.n_operands; i++) 644*e4b17023SJohn Marino { 645*e4b17023SJohn Marino enum machine_mode mode = recog_data.operand_mode[i]; 646*e4b17023SJohn Marino if (op_alt_regno[i][j] == -1) 647*e4b17023SJohn Marino continue; 648*e4b17023SJohn Marino 649*e4b17023SJohn Marino validate_change (insn, recog_data.operand_loc[i], 650*e4b17023SJohn Marino gen_rtx_REG (mode, op_alt_regno[i][j]), 1); 651*e4b17023SJohn Marino } 652*e4b17023SJohn Marino 653*e4b17023SJohn Marino for (i = recog_data.n_dups - 1; i >= 0; i--) 654*e4b17023SJohn Marino { 655*e4b17023SJohn Marino int op = recog_data.dup_num[i]; 656*e4b17023SJohn Marino enum machine_mode mode = recog_data.operand_mode[op]; 657*e4b17023SJohn Marino 658*e4b17023SJohn Marino if (op_alt_regno[op][j] == -1) 659*e4b17023SJohn Marino continue; 660*e4b17023SJohn Marino 661*e4b17023SJohn Marino validate_change (insn, recog_data.dup_loc[i], 662*e4b17023SJohn Marino gen_rtx_REG (mode, op_alt_regno[op][j]), 1); 663*e4b17023SJohn Marino } 664*e4b17023SJohn Marino 665*e4b17023SJohn Marino return apply_change_group (); 666*e4b17023SJohn Marino } 667*e4b17023SJohn Marino 668*e4b17023SJohn Marino /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg 669*e4b17023SJohn Marino addressing now. 670*e4b17023SJohn Marino This code might also be useful when reload gave up on reg+reg addressing 671*e4b17023SJohn Marino because of clashes between the return register and INDEX_REG_CLASS. */ 672*e4b17023SJohn Marino 673*e4b17023SJohn Marino /* The maximum number of uses of a register we can keep track of to 674*e4b17023SJohn Marino replace them with reg+reg addressing. */ 675*e4b17023SJohn Marino #define RELOAD_COMBINE_MAX_USES 16 676*e4b17023SJohn Marino 677*e4b17023SJohn Marino /* Describes a recorded use of a register. */ 678*e4b17023SJohn Marino struct reg_use 679*e4b17023SJohn Marino { 680*e4b17023SJohn Marino /* The insn where a register has been used. */ 681*e4b17023SJohn Marino rtx insn; 682*e4b17023SJohn Marino /* Points to the memory reference enclosing the use, if any, NULL_RTX 683*e4b17023SJohn Marino otherwise. */ 684*e4b17023SJohn Marino rtx containing_mem; 685*e4b17023SJohn Marino /* Location of the register withing INSN. */ 686*e4b17023SJohn Marino rtx *usep; 687*e4b17023SJohn Marino /* The reverse uid of the insn. */ 688*e4b17023SJohn Marino int ruid; 689*e4b17023SJohn Marino }; 690*e4b17023SJohn Marino 691*e4b17023SJohn Marino /* If the register is used in some unknown fashion, USE_INDEX is negative. 692*e4b17023SJohn Marino If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID 693*e4b17023SJohn Marino indicates where it is first set or clobbered. 694*e4b17023SJohn Marino Otherwise, USE_INDEX is the index of the last encountered use of the 695*e4b17023SJohn Marino register (which is first among these we have seen since we scan backwards). 696*e4b17023SJohn Marino USE_RUID indicates the first encountered, i.e. last, of these uses. 697*e4b17023SJohn Marino If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS 698*e4b17023SJohn Marino with a constant offset; OFFSET contains this constant in that case. 699*e4b17023SJohn Marino STORE_RUID is always meaningful if we only want to use a value in a 700*e4b17023SJohn Marino register in a different place: it denotes the next insn in the insn 701*e4b17023SJohn Marino stream (i.e. the last encountered) that sets or clobbers the register. 702*e4b17023SJohn Marino REAL_STORE_RUID is similar, but clobbers are ignored when updating it. */ 703*e4b17023SJohn Marino static struct 704*e4b17023SJohn Marino { 705*e4b17023SJohn Marino struct reg_use reg_use[RELOAD_COMBINE_MAX_USES]; 706*e4b17023SJohn Marino rtx offset; 707*e4b17023SJohn Marino int use_index; 708*e4b17023SJohn Marino int store_ruid; 709*e4b17023SJohn Marino int real_store_ruid; 710*e4b17023SJohn Marino int use_ruid; 711*e4b17023SJohn Marino bool all_offsets_match; 712*e4b17023SJohn Marino } reg_state[FIRST_PSEUDO_REGISTER]; 713*e4b17023SJohn Marino 714*e4b17023SJohn Marino /* Reverse linear uid. This is increased in reload_combine while scanning 715*e4b17023SJohn Marino the instructions from last to first. It is used to set last_label_ruid 716*e4b17023SJohn Marino and the store_ruid / use_ruid fields in reg_state. */ 717*e4b17023SJohn Marino static int reload_combine_ruid; 718*e4b17023SJohn Marino 719*e4b17023SJohn Marino /* The RUID of the last label we encountered in reload_combine. */ 720*e4b17023SJohn Marino static int last_label_ruid; 721*e4b17023SJohn Marino 722*e4b17023SJohn Marino /* The RUID of the last jump we encountered in reload_combine. */ 723*e4b17023SJohn Marino static int last_jump_ruid; 724*e4b17023SJohn Marino 725*e4b17023SJohn Marino /* The register numbers of the first and last index register. A value of 726*e4b17023SJohn Marino -1 in LAST_INDEX_REG indicates that we've previously computed these 727*e4b17023SJohn Marino values and found no suitable index registers. */ 728*e4b17023SJohn Marino static int first_index_reg = -1; 729*e4b17023SJohn Marino static int last_index_reg; 730*e4b17023SJohn Marino 731*e4b17023SJohn Marino #define LABEL_LIVE(LABEL) \ 732*e4b17023SJohn Marino (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno]) 733*e4b17023SJohn Marino 734*e4b17023SJohn Marino /* Subroutine of reload_combine_split_ruids, called to fix up a single 735*e4b17023SJohn Marino ruid pointed to by *PRUID if it is higher than SPLIT_RUID. */ 736*e4b17023SJohn Marino 737*e4b17023SJohn Marino static inline void 738*e4b17023SJohn Marino reload_combine_split_one_ruid (int *pruid, int split_ruid) 739*e4b17023SJohn Marino { 740*e4b17023SJohn Marino if (*pruid > split_ruid) 741*e4b17023SJohn Marino (*pruid)++; 742*e4b17023SJohn Marino } 743*e4b17023SJohn Marino 744*e4b17023SJohn Marino /* Called when we insert a new insn in a position we've already passed in 745*e4b17023SJohn Marino the scan. Examine all our state, increasing all ruids that are higher 746*e4b17023SJohn Marino than SPLIT_RUID by one in order to make room for a new insn. */ 747*e4b17023SJohn Marino 748*e4b17023SJohn Marino static void 749*e4b17023SJohn Marino reload_combine_split_ruids (int split_ruid) 750*e4b17023SJohn Marino { 751*e4b17023SJohn Marino unsigned i; 752*e4b17023SJohn Marino 753*e4b17023SJohn Marino reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid); 754*e4b17023SJohn Marino reload_combine_split_one_ruid (&last_label_ruid, split_ruid); 755*e4b17023SJohn Marino reload_combine_split_one_ruid (&last_jump_ruid, split_ruid); 756*e4b17023SJohn Marino 757*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 758*e4b17023SJohn Marino { 759*e4b17023SJohn Marino int j, idx = reg_state[i].use_index; 760*e4b17023SJohn Marino reload_combine_split_one_ruid (®_state[i].use_ruid, split_ruid); 761*e4b17023SJohn Marino reload_combine_split_one_ruid (®_state[i].store_ruid, split_ruid); 762*e4b17023SJohn Marino reload_combine_split_one_ruid (®_state[i].real_store_ruid, 763*e4b17023SJohn Marino split_ruid); 764*e4b17023SJohn Marino if (idx < 0) 765*e4b17023SJohn Marino continue; 766*e4b17023SJohn Marino for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++) 767*e4b17023SJohn Marino { 768*e4b17023SJohn Marino reload_combine_split_one_ruid (®_state[i].reg_use[j].ruid, 769*e4b17023SJohn Marino split_ruid); 770*e4b17023SJohn Marino } 771*e4b17023SJohn Marino } 772*e4b17023SJohn Marino } 773*e4b17023SJohn Marino 774*e4b17023SJohn Marino /* Called when we are about to rescan a previously encountered insn with 775*e4b17023SJohn Marino reload_combine_note_use after modifying some part of it. This clears all 776*e4b17023SJohn Marino information about uses in that particular insn. */ 777*e4b17023SJohn Marino 778*e4b17023SJohn Marino static void 779*e4b17023SJohn Marino reload_combine_purge_insn_uses (rtx insn) 780*e4b17023SJohn Marino { 781*e4b17023SJohn Marino unsigned i; 782*e4b17023SJohn Marino 783*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 784*e4b17023SJohn Marino { 785*e4b17023SJohn Marino int j, k, idx = reg_state[i].use_index; 786*e4b17023SJohn Marino if (idx < 0) 787*e4b17023SJohn Marino continue; 788*e4b17023SJohn Marino j = k = RELOAD_COMBINE_MAX_USES; 789*e4b17023SJohn Marino while (j-- > idx) 790*e4b17023SJohn Marino { 791*e4b17023SJohn Marino if (reg_state[i].reg_use[j].insn != insn) 792*e4b17023SJohn Marino { 793*e4b17023SJohn Marino k--; 794*e4b17023SJohn Marino if (k != j) 795*e4b17023SJohn Marino reg_state[i].reg_use[k] = reg_state[i].reg_use[j]; 796*e4b17023SJohn Marino } 797*e4b17023SJohn Marino } 798*e4b17023SJohn Marino reg_state[i].use_index = k; 799*e4b17023SJohn Marino } 800*e4b17023SJohn Marino } 801*e4b17023SJohn Marino 802*e4b17023SJohn Marino /* Called when we need to forget about all uses of REGNO after an insn 803*e4b17023SJohn Marino which is identified by RUID. */ 804*e4b17023SJohn Marino 805*e4b17023SJohn Marino static void 806*e4b17023SJohn Marino reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid) 807*e4b17023SJohn Marino { 808*e4b17023SJohn Marino int j, k, idx = reg_state[regno].use_index; 809*e4b17023SJohn Marino if (idx < 0) 810*e4b17023SJohn Marino return; 811*e4b17023SJohn Marino j = k = RELOAD_COMBINE_MAX_USES; 812*e4b17023SJohn Marino while (j-- > idx) 813*e4b17023SJohn Marino { 814*e4b17023SJohn Marino if (reg_state[regno].reg_use[j].ruid >= ruid) 815*e4b17023SJohn Marino { 816*e4b17023SJohn Marino k--; 817*e4b17023SJohn Marino if (k != j) 818*e4b17023SJohn Marino reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j]; 819*e4b17023SJohn Marino } 820*e4b17023SJohn Marino } 821*e4b17023SJohn Marino reg_state[regno].use_index = k; 822*e4b17023SJohn Marino } 823*e4b17023SJohn Marino 824*e4b17023SJohn Marino /* Find the use of REGNO with the ruid that is highest among those 825*e4b17023SJohn Marino lower than RUID_LIMIT, and return it if it is the only use of this 826*e4b17023SJohn Marino reg in the insn. Return NULL otherwise. */ 827*e4b17023SJohn Marino 828*e4b17023SJohn Marino static struct reg_use * 829*e4b17023SJohn Marino reload_combine_closest_single_use (unsigned regno, int ruid_limit) 830*e4b17023SJohn Marino { 831*e4b17023SJohn Marino int i, best_ruid = 0; 832*e4b17023SJohn Marino int use_idx = reg_state[regno].use_index; 833*e4b17023SJohn Marino struct reg_use *retval; 834*e4b17023SJohn Marino 835*e4b17023SJohn Marino if (use_idx < 0) 836*e4b17023SJohn Marino return NULL; 837*e4b17023SJohn Marino retval = NULL; 838*e4b17023SJohn Marino for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++) 839*e4b17023SJohn Marino { 840*e4b17023SJohn Marino struct reg_use *use = reg_state[regno].reg_use + i; 841*e4b17023SJohn Marino int this_ruid = use->ruid; 842*e4b17023SJohn Marino if (this_ruid >= ruid_limit) 843*e4b17023SJohn Marino continue; 844*e4b17023SJohn Marino if (this_ruid > best_ruid) 845*e4b17023SJohn Marino { 846*e4b17023SJohn Marino best_ruid = this_ruid; 847*e4b17023SJohn Marino retval = use; 848*e4b17023SJohn Marino } 849*e4b17023SJohn Marino else if (this_ruid == best_ruid) 850*e4b17023SJohn Marino retval = NULL; 851*e4b17023SJohn Marino } 852*e4b17023SJohn Marino if (last_label_ruid >= best_ruid) 853*e4b17023SJohn Marino return NULL; 854*e4b17023SJohn Marino return retval; 855*e4b17023SJohn Marino } 856*e4b17023SJohn Marino 857*e4b17023SJohn Marino /* After we've moved an add insn, fix up any debug insns that occur 858*e4b17023SJohn Marino between the old location of the add and the new location. REG is 859*e4b17023SJohn Marino the destination register of the add insn; REPLACEMENT is the 860*e4b17023SJohn Marino SET_SRC of the add. FROM and TO specify the range in which we 861*e4b17023SJohn Marino should make this change on debug insns. */ 862*e4b17023SJohn Marino 863*e4b17023SJohn Marino static void 864*e4b17023SJohn Marino fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to) 865*e4b17023SJohn Marino { 866*e4b17023SJohn Marino rtx insn; 867*e4b17023SJohn Marino for (insn = from; insn != to; insn = NEXT_INSN (insn)) 868*e4b17023SJohn Marino { 869*e4b17023SJohn Marino rtx t; 870*e4b17023SJohn Marino 871*e4b17023SJohn Marino if (!DEBUG_INSN_P (insn)) 872*e4b17023SJohn Marino continue; 873*e4b17023SJohn Marino 874*e4b17023SJohn Marino t = INSN_VAR_LOCATION_LOC (insn); 875*e4b17023SJohn Marino t = simplify_replace_rtx (t, reg, replacement); 876*e4b17023SJohn Marino validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0); 877*e4b17023SJohn Marino } 878*e4b17023SJohn Marino } 879*e4b17023SJohn Marino 880*e4b17023SJohn Marino /* Subroutine of reload_combine_recognize_const_pattern. Try to replace REG 881*e4b17023SJohn Marino with SRC in the insn described by USE, taking costs into account. Return 882*e4b17023SJohn Marino true if we made the replacement. */ 883*e4b17023SJohn Marino 884*e4b17023SJohn Marino static bool 885*e4b17023SJohn Marino try_replace_in_use (struct reg_use *use, rtx reg, rtx src) 886*e4b17023SJohn Marino { 887*e4b17023SJohn Marino rtx use_insn = use->insn; 888*e4b17023SJohn Marino rtx mem = use->containing_mem; 889*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); 890*e4b17023SJohn Marino 891*e4b17023SJohn Marino if (mem != NULL_RTX) 892*e4b17023SJohn Marino { 893*e4b17023SJohn Marino addr_space_t as = MEM_ADDR_SPACE (mem); 894*e4b17023SJohn Marino rtx oldaddr = XEXP (mem, 0); 895*e4b17023SJohn Marino rtx newaddr = NULL_RTX; 896*e4b17023SJohn Marino int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed); 897*e4b17023SJohn Marino int new_cost; 898*e4b17023SJohn Marino 899*e4b17023SJohn Marino newaddr = simplify_replace_rtx (oldaddr, reg, src); 900*e4b17023SJohn Marino if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as)) 901*e4b17023SJohn Marino { 902*e4b17023SJohn Marino XEXP (mem, 0) = newaddr; 903*e4b17023SJohn Marino new_cost = address_cost (newaddr, GET_MODE (mem), as, speed); 904*e4b17023SJohn Marino XEXP (mem, 0) = oldaddr; 905*e4b17023SJohn Marino if (new_cost <= old_cost 906*e4b17023SJohn Marino && validate_change (use_insn, 907*e4b17023SJohn Marino &XEXP (mem, 0), newaddr, 0)) 908*e4b17023SJohn Marino return true; 909*e4b17023SJohn Marino } 910*e4b17023SJohn Marino } 911*e4b17023SJohn Marino else 912*e4b17023SJohn Marino { 913*e4b17023SJohn Marino rtx new_set = single_set (use_insn); 914*e4b17023SJohn Marino if (new_set 915*e4b17023SJohn Marino && REG_P (SET_DEST (new_set)) 916*e4b17023SJohn Marino && GET_CODE (SET_SRC (new_set)) == PLUS 917*e4b17023SJohn Marino && REG_P (XEXP (SET_SRC (new_set), 0)) 918*e4b17023SJohn Marino && CONSTANT_P (XEXP (SET_SRC (new_set), 1))) 919*e4b17023SJohn Marino { 920*e4b17023SJohn Marino rtx new_src; 921*e4b17023SJohn Marino int old_cost = set_src_cost (SET_SRC (new_set), speed); 922*e4b17023SJohn Marino 923*e4b17023SJohn Marino gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg)); 924*e4b17023SJohn Marino new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src); 925*e4b17023SJohn Marino 926*e4b17023SJohn Marino if (set_src_cost (new_src, speed) <= old_cost 927*e4b17023SJohn Marino && validate_change (use_insn, &SET_SRC (new_set), 928*e4b17023SJohn Marino new_src, 0)) 929*e4b17023SJohn Marino return true; 930*e4b17023SJohn Marino } 931*e4b17023SJohn Marino } 932*e4b17023SJohn Marino return false; 933*e4b17023SJohn Marino } 934*e4b17023SJohn Marino 935*e4b17023SJohn Marino /* Called by reload_combine when scanning INSN. This function tries to detect 936*e4b17023SJohn Marino patterns where a constant is added to a register, and the result is used 937*e4b17023SJohn Marino in an address. 938*e4b17023SJohn Marino Return true if no further processing is needed on INSN; false if it wasn't 939*e4b17023SJohn Marino recognized and should be handled normally. */ 940*e4b17023SJohn Marino 941*e4b17023SJohn Marino static bool 942*e4b17023SJohn Marino reload_combine_recognize_const_pattern (rtx insn) 943*e4b17023SJohn Marino { 944*e4b17023SJohn Marino int from_ruid = reload_combine_ruid; 945*e4b17023SJohn Marino rtx set, pat, reg, src, addreg; 946*e4b17023SJohn Marino unsigned int regno; 947*e4b17023SJohn Marino struct reg_use *use; 948*e4b17023SJohn Marino bool must_move_add; 949*e4b17023SJohn Marino rtx add_moved_after_insn = NULL_RTX; 950*e4b17023SJohn Marino int add_moved_after_ruid = 0; 951*e4b17023SJohn Marino int clobbered_regno = -1; 952*e4b17023SJohn Marino 953*e4b17023SJohn Marino set = single_set (insn); 954*e4b17023SJohn Marino if (set == NULL_RTX) 955*e4b17023SJohn Marino return false; 956*e4b17023SJohn Marino 957*e4b17023SJohn Marino reg = SET_DEST (set); 958*e4b17023SJohn Marino src = SET_SRC (set); 959*e4b17023SJohn Marino if (!REG_P (reg) 960*e4b17023SJohn Marino || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1 961*e4b17023SJohn Marino || GET_MODE (reg) != Pmode 962*e4b17023SJohn Marino || reg == stack_pointer_rtx) 963*e4b17023SJohn Marino return false; 964*e4b17023SJohn Marino 965*e4b17023SJohn Marino regno = REGNO (reg); 966*e4b17023SJohn Marino 967*e4b17023SJohn Marino /* We look for a REG1 = REG2 + CONSTANT insn, followed by either 968*e4b17023SJohn Marino uses of REG1 inside an address, or inside another add insn. If 969*e4b17023SJohn Marino possible and profitable, merge the addition into subsequent 970*e4b17023SJohn Marino uses. */ 971*e4b17023SJohn Marino if (GET_CODE (src) != PLUS 972*e4b17023SJohn Marino || !REG_P (XEXP (src, 0)) 973*e4b17023SJohn Marino || !CONSTANT_P (XEXP (src, 1))) 974*e4b17023SJohn Marino return false; 975*e4b17023SJohn Marino 976*e4b17023SJohn Marino addreg = XEXP (src, 0); 977*e4b17023SJohn Marino must_move_add = rtx_equal_p (reg, addreg); 978*e4b17023SJohn Marino 979*e4b17023SJohn Marino pat = PATTERN (insn); 980*e4b17023SJohn Marino if (must_move_add && set != pat) 981*e4b17023SJohn Marino { 982*e4b17023SJohn Marino /* We have to be careful when moving the add; apart from the 983*e4b17023SJohn Marino single_set there may also be clobbers. Recognize one special 984*e4b17023SJohn Marino case, that of one clobber alongside the set (likely a clobber 985*e4b17023SJohn Marino of the CC register). */ 986*e4b17023SJohn Marino gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL); 987*e4b17023SJohn Marino if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set 988*e4b17023SJohn Marino || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER 989*e4b17023SJohn Marino || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0))) 990*e4b17023SJohn Marino return false; 991*e4b17023SJohn Marino clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0)); 992*e4b17023SJohn Marino } 993*e4b17023SJohn Marino 994*e4b17023SJohn Marino do 995*e4b17023SJohn Marino { 996*e4b17023SJohn Marino use = reload_combine_closest_single_use (regno, from_ruid); 997*e4b17023SJohn Marino 998*e4b17023SJohn Marino if (use) 999*e4b17023SJohn Marino /* Start the search for the next use from here. */ 1000*e4b17023SJohn Marino from_ruid = use->ruid; 1001*e4b17023SJohn Marino 1002*e4b17023SJohn Marino if (use && GET_MODE (*use->usep) == Pmode) 1003*e4b17023SJohn Marino { 1004*e4b17023SJohn Marino bool delete_add = false; 1005*e4b17023SJohn Marino rtx use_insn = use->insn; 1006*e4b17023SJohn Marino int use_ruid = use->ruid; 1007*e4b17023SJohn Marino 1008*e4b17023SJohn Marino /* Avoid moving the add insn past a jump. */ 1009*e4b17023SJohn Marino if (must_move_add && use_ruid <= last_jump_ruid) 1010*e4b17023SJohn Marino break; 1011*e4b17023SJohn Marino 1012*e4b17023SJohn Marino /* If the add clobbers another hard reg in parallel, don't move 1013*e4b17023SJohn Marino it past a real set of this hard reg. */ 1014*e4b17023SJohn Marino if (must_move_add && clobbered_regno >= 0 1015*e4b17023SJohn Marino && reg_state[clobbered_regno].real_store_ruid >= use_ruid) 1016*e4b17023SJohn Marino break; 1017*e4b17023SJohn Marino 1018*e4b17023SJohn Marino #ifdef HAVE_cc0 1019*e4b17023SJohn Marino /* Do not separate cc0 setter and cc0 user on HAVE_cc0 targets. */ 1020*e4b17023SJohn Marino if (must_move_add && sets_cc0_p (PATTERN (use_insn))) 1021*e4b17023SJohn Marino break; 1022*e4b17023SJohn Marino #endif 1023*e4b17023SJohn Marino 1024*e4b17023SJohn Marino gcc_assert (reg_state[regno].store_ruid <= use_ruid); 1025*e4b17023SJohn Marino /* Avoid moving a use of ADDREG past a point where it is stored. */ 1026*e4b17023SJohn Marino if (reg_state[REGNO (addreg)].store_ruid > use_ruid) 1027*e4b17023SJohn Marino break; 1028*e4b17023SJohn Marino 1029*e4b17023SJohn Marino /* We also must not move the addition past an insn that sets 1030*e4b17023SJohn Marino the same register, unless we can combine two add insns. */ 1031*e4b17023SJohn Marino if (must_move_add && reg_state[regno].store_ruid == use_ruid) 1032*e4b17023SJohn Marino { 1033*e4b17023SJohn Marino if (use->containing_mem == NULL_RTX) 1034*e4b17023SJohn Marino delete_add = true; 1035*e4b17023SJohn Marino else 1036*e4b17023SJohn Marino break; 1037*e4b17023SJohn Marino } 1038*e4b17023SJohn Marino 1039*e4b17023SJohn Marino if (try_replace_in_use (use, reg, src)) 1040*e4b17023SJohn Marino { 1041*e4b17023SJohn Marino reload_combine_purge_insn_uses (use_insn); 1042*e4b17023SJohn Marino reload_combine_note_use (&PATTERN (use_insn), use_insn, 1043*e4b17023SJohn Marino use_ruid, NULL_RTX); 1044*e4b17023SJohn Marino 1045*e4b17023SJohn Marino if (delete_add) 1046*e4b17023SJohn Marino { 1047*e4b17023SJohn Marino fixup_debug_insns (reg, src, insn, use_insn); 1048*e4b17023SJohn Marino delete_insn (insn); 1049*e4b17023SJohn Marino return true; 1050*e4b17023SJohn Marino } 1051*e4b17023SJohn Marino if (must_move_add) 1052*e4b17023SJohn Marino { 1053*e4b17023SJohn Marino add_moved_after_insn = use_insn; 1054*e4b17023SJohn Marino add_moved_after_ruid = use_ruid; 1055*e4b17023SJohn Marino } 1056*e4b17023SJohn Marino continue; 1057*e4b17023SJohn Marino } 1058*e4b17023SJohn Marino } 1059*e4b17023SJohn Marino /* If we get here, we couldn't handle this use. */ 1060*e4b17023SJohn Marino if (must_move_add) 1061*e4b17023SJohn Marino break; 1062*e4b17023SJohn Marino } 1063*e4b17023SJohn Marino while (use); 1064*e4b17023SJohn Marino 1065*e4b17023SJohn Marino if (!must_move_add || add_moved_after_insn == NULL_RTX) 1066*e4b17023SJohn Marino /* Process the add normally. */ 1067*e4b17023SJohn Marino return false; 1068*e4b17023SJohn Marino 1069*e4b17023SJohn Marino fixup_debug_insns (reg, src, insn, add_moved_after_insn); 1070*e4b17023SJohn Marino 1071*e4b17023SJohn Marino reorder_insns (insn, insn, add_moved_after_insn); 1072*e4b17023SJohn Marino reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid); 1073*e4b17023SJohn Marino reload_combine_split_ruids (add_moved_after_ruid - 1); 1074*e4b17023SJohn Marino reload_combine_note_use (&PATTERN (insn), insn, 1075*e4b17023SJohn Marino add_moved_after_ruid, NULL_RTX); 1076*e4b17023SJohn Marino reg_state[regno].store_ruid = add_moved_after_ruid; 1077*e4b17023SJohn Marino 1078*e4b17023SJohn Marino return true; 1079*e4b17023SJohn Marino } 1080*e4b17023SJohn Marino 1081*e4b17023SJohn Marino /* Called by reload_combine when scanning INSN. Try to detect a pattern we 1082*e4b17023SJohn Marino can handle and improve. Return true if no further processing is needed on 1083*e4b17023SJohn Marino INSN; false if it wasn't recognized and should be handled normally. */ 1084*e4b17023SJohn Marino 1085*e4b17023SJohn Marino static bool 1086*e4b17023SJohn Marino reload_combine_recognize_pattern (rtx insn) 1087*e4b17023SJohn Marino { 1088*e4b17023SJohn Marino rtx set, reg, src; 1089*e4b17023SJohn Marino unsigned int regno; 1090*e4b17023SJohn Marino 1091*e4b17023SJohn Marino set = single_set (insn); 1092*e4b17023SJohn Marino if (set == NULL_RTX) 1093*e4b17023SJohn Marino return false; 1094*e4b17023SJohn Marino 1095*e4b17023SJohn Marino reg = SET_DEST (set); 1096*e4b17023SJohn Marino src = SET_SRC (set); 1097*e4b17023SJohn Marino if (!REG_P (reg) 1098*e4b17023SJohn Marino || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1) 1099*e4b17023SJohn Marino return false; 1100*e4b17023SJohn Marino 1101*e4b17023SJohn Marino regno = REGNO (reg); 1102*e4b17023SJohn Marino 1103*e4b17023SJohn Marino /* Look for (set (REGX) (CONST_INT)) 1104*e4b17023SJohn Marino (set (REGX) (PLUS (REGX) (REGY))) 1105*e4b17023SJohn Marino ... 1106*e4b17023SJohn Marino ... (MEM (REGX)) ... 1107*e4b17023SJohn Marino and convert it to 1108*e4b17023SJohn Marino (set (REGZ) (CONST_INT)) 1109*e4b17023SJohn Marino ... 1110*e4b17023SJohn Marino ... (MEM (PLUS (REGZ) (REGY)))... . 1111*e4b17023SJohn Marino 1112*e4b17023SJohn Marino First, check that we have (set (REGX) (PLUS (REGX) (REGY))) 1113*e4b17023SJohn Marino and that we know all uses of REGX before it dies. 1114*e4b17023SJohn Marino Also, explicitly check that REGX != REGY; our life information 1115*e4b17023SJohn Marino does not yet show whether REGY changes in this insn. */ 1116*e4b17023SJohn Marino 1117*e4b17023SJohn Marino if (GET_CODE (src) == PLUS 1118*e4b17023SJohn Marino && reg_state[regno].all_offsets_match 1119*e4b17023SJohn Marino && last_index_reg != -1 1120*e4b17023SJohn Marino && REG_P (XEXP (src, 1)) 1121*e4b17023SJohn Marino && rtx_equal_p (XEXP (src, 0), reg) 1122*e4b17023SJohn Marino && !rtx_equal_p (XEXP (src, 1), reg) 1123*e4b17023SJohn Marino && reg_state[regno].use_index >= 0 1124*e4b17023SJohn Marino && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES 1125*e4b17023SJohn Marino && last_label_ruid < reg_state[regno].use_ruid) 1126*e4b17023SJohn Marino { 1127*e4b17023SJohn Marino rtx base = XEXP (src, 1); 1128*e4b17023SJohn Marino rtx prev = prev_nonnote_nondebug_insn (insn); 1129*e4b17023SJohn Marino rtx prev_set = prev ? single_set (prev) : NULL_RTX; 1130*e4b17023SJohn Marino rtx index_reg = NULL_RTX; 1131*e4b17023SJohn Marino rtx reg_sum = NULL_RTX; 1132*e4b17023SJohn Marino int i; 1133*e4b17023SJohn Marino 1134*e4b17023SJohn Marino /* Now we need to set INDEX_REG to an index register (denoted as 1135*e4b17023SJohn Marino REGZ in the illustration above) and REG_SUM to the expression 1136*e4b17023SJohn Marino register+register that we want to use to substitute uses of REG 1137*e4b17023SJohn Marino (typically in MEMs) with. First check REG and BASE for being 1138*e4b17023SJohn Marino index registers; we can use them even if they are not dead. */ 1139*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) 1140*e4b17023SJohn Marino || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], 1141*e4b17023SJohn Marino REGNO (base))) 1142*e4b17023SJohn Marino { 1143*e4b17023SJohn Marino index_reg = reg; 1144*e4b17023SJohn Marino reg_sum = src; 1145*e4b17023SJohn Marino } 1146*e4b17023SJohn Marino else 1147*e4b17023SJohn Marino { 1148*e4b17023SJohn Marino /* Otherwise, look for a free index register. Since we have 1149*e4b17023SJohn Marino checked above that neither REG nor BASE are index registers, 1150*e4b17023SJohn Marino if we find anything at all, it will be different from these 1151*e4b17023SJohn Marino two registers. */ 1152*e4b17023SJohn Marino for (i = first_index_reg; i <= last_index_reg; i++) 1153*e4b17023SJohn Marino { 1154*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i) 1155*e4b17023SJohn Marino && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES 1156*e4b17023SJohn Marino && reg_state[i].store_ruid <= reg_state[regno].use_ruid 1157*e4b17023SJohn Marino && (call_used_regs[i] || df_regs_ever_live_p (i)) 1158*e4b17023SJohn Marino && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM) 1159*e4b17023SJohn Marino && !fixed_regs[i] && !global_regs[i] 1160*e4b17023SJohn Marino && hard_regno_nregs[i][GET_MODE (reg)] == 1 1161*e4b17023SJohn Marino && targetm.hard_regno_scratch_ok (i)) 1162*e4b17023SJohn Marino { 1163*e4b17023SJohn Marino index_reg = gen_rtx_REG (GET_MODE (reg), i); 1164*e4b17023SJohn Marino reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); 1165*e4b17023SJohn Marino break; 1166*e4b17023SJohn Marino } 1167*e4b17023SJohn Marino } 1168*e4b17023SJohn Marino } 1169*e4b17023SJohn Marino 1170*e4b17023SJohn Marino /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that 1171*e4b17023SJohn Marino (REGY), i.e. BASE, is not clobbered before the last use we'll 1172*e4b17023SJohn Marino create. */ 1173*e4b17023SJohn Marino if (reg_sum 1174*e4b17023SJohn Marino && prev_set 1175*e4b17023SJohn Marino && CONST_INT_P (SET_SRC (prev_set)) 1176*e4b17023SJohn Marino && rtx_equal_p (SET_DEST (prev_set), reg) 1177*e4b17023SJohn Marino && (reg_state[REGNO (base)].store_ruid 1178*e4b17023SJohn Marino <= reg_state[regno].use_ruid)) 1179*e4b17023SJohn Marino { 1180*e4b17023SJohn Marino /* Change destination register and, if necessary, the constant 1181*e4b17023SJohn Marino value in PREV, the constant loading instruction. */ 1182*e4b17023SJohn Marino validate_change (prev, &SET_DEST (prev_set), index_reg, 1); 1183*e4b17023SJohn Marino if (reg_state[regno].offset != const0_rtx) 1184*e4b17023SJohn Marino validate_change (prev, 1185*e4b17023SJohn Marino &SET_SRC (prev_set), 1186*e4b17023SJohn Marino GEN_INT (INTVAL (SET_SRC (prev_set)) 1187*e4b17023SJohn Marino + INTVAL (reg_state[regno].offset)), 1188*e4b17023SJohn Marino 1); 1189*e4b17023SJohn Marino 1190*e4b17023SJohn Marino /* Now for every use of REG that we have recorded, replace REG 1191*e4b17023SJohn Marino with REG_SUM. */ 1192*e4b17023SJohn Marino for (i = reg_state[regno].use_index; 1193*e4b17023SJohn Marino i < RELOAD_COMBINE_MAX_USES; i++) 1194*e4b17023SJohn Marino validate_unshare_change (reg_state[regno].reg_use[i].insn, 1195*e4b17023SJohn Marino reg_state[regno].reg_use[i].usep, 1196*e4b17023SJohn Marino /* Each change must have its own 1197*e4b17023SJohn Marino replacement. */ 1198*e4b17023SJohn Marino reg_sum, 1); 1199*e4b17023SJohn Marino 1200*e4b17023SJohn Marino if (apply_change_group ()) 1201*e4b17023SJohn Marino { 1202*e4b17023SJohn Marino struct reg_use *lowest_ruid = NULL; 1203*e4b17023SJohn Marino 1204*e4b17023SJohn Marino /* For every new use of REG_SUM, we have to record the use 1205*e4b17023SJohn Marino of BASE therein, i.e. operand 1. */ 1206*e4b17023SJohn Marino for (i = reg_state[regno].use_index; 1207*e4b17023SJohn Marino i < RELOAD_COMBINE_MAX_USES; i++) 1208*e4b17023SJohn Marino { 1209*e4b17023SJohn Marino struct reg_use *use = reg_state[regno].reg_use + i; 1210*e4b17023SJohn Marino reload_combine_note_use (&XEXP (*use->usep, 1), use->insn, 1211*e4b17023SJohn Marino use->ruid, use->containing_mem); 1212*e4b17023SJohn Marino if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid) 1213*e4b17023SJohn Marino lowest_ruid = use; 1214*e4b17023SJohn Marino } 1215*e4b17023SJohn Marino 1216*e4b17023SJohn Marino fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn); 1217*e4b17023SJohn Marino 1218*e4b17023SJohn Marino /* Delete the reg-reg addition. */ 1219*e4b17023SJohn Marino delete_insn (insn); 1220*e4b17023SJohn Marino 1221*e4b17023SJohn Marino if (reg_state[regno].offset != const0_rtx) 1222*e4b17023SJohn Marino /* Previous REG_EQUIV / REG_EQUAL notes for PREV 1223*e4b17023SJohn Marino are now invalid. */ 1224*e4b17023SJohn Marino remove_reg_equal_equiv_notes (prev); 1225*e4b17023SJohn Marino 1226*e4b17023SJohn Marino reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; 1227*e4b17023SJohn Marino return true; 1228*e4b17023SJohn Marino } 1229*e4b17023SJohn Marino } 1230*e4b17023SJohn Marino } 1231*e4b17023SJohn Marino return false; 1232*e4b17023SJohn Marino } 1233*e4b17023SJohn Marino 1234*e4b17023SJohn Marino static void 1235*e4b17023SJohn Marino reload_combine (void) 1236*e4b17023SJohn Marino { 1237*e4b17023SJohn Marino rtx insn, prev; 1238*e4b17023SJohn Marino basic_block bb; 1239*e4b17023SJohn Marino unsigned int r; 1240*e4b17023SJohn Marino int min_labelno, n_labels; 1241*e4b17023SJohn Marino HARD_REG_SET ever_live_at_start, *label_live; 1242*e4b17023SJohn Marino 1243*e4b17023SJohn Marino /* To avoid wasting too much time later searching for an index register, 1244*e4b17023SJohn Marino determine the minimum and maximum index register numbers. */ 1245*e4b17023SJohn Marino if (INDEX_REG_CLASS == NO_REGS) 1246*e4b17023SJohn Marino last_index_reg = -1; 1247*e4b17023SJohn Marino else if (first_index_reg == -1 && last_index_reg == 0) 1248*e4b17023SJohn Marino { 1249*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1250*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) 1251*e4b17023SJohn Marino { 1252*e4b17023SJohn Marino if (first_index_reg == -1) 1253*e4b17023SJohn Marino first_index_reg = r; 1254*e4b17023SJohn Marino 1255*e4b17023SJohn Marino last_index_reg = r; 1256*e4b17023SJohn Marino } 1257*e4b17023SJohn Marino 1258*e4b17023SJohn Marino /* If no index register is available, we can quit now. Set LAST_INDEX_REG 1259*e4b17023SJohn Marino to -1 so we'll know to quit early the next time we get here. */ 1260*e4b17023SJohn Marino if (first_index_reg == -1) 1261*e4b17023SJohn Marino { 1262*e4b17023SJohn Marino last_index_reg = -1; 1263*e4b17023SJohn Marino return; 1264*e4b17023SJohn Marino } 1265*e4b17023SJohn Marino } 1266*e4b17023SJohn Marino 1267*e4b17023SJohn Marino /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime 1268*e4b17023SJohn Marino information is a bit fuzzy immediately after reload, but it's 1269*e4b17023SJohn Marino still good enough to determine which registers are live at a jump 1270*e4b17023SJohn Marino destination. */ 1271*e4b17023SJohn Marino min_labelno = get_first_label_num (); 1272*e4b17023SJohn Marino n_labels = max_label_num () - min_labelno; 1273*e4b17023SJohn Marino label_live = XNEWVEC (HARD_REG_SET, n_labels); 1274*e4b17023SJohn Marino CLEAR_HARD_REG_SET (ever_live_at_start); 1275*e4b17023SJohn Marino 1276*e4b17023SJohn Marino FOR_EACH_BB_REVERSE (bb) 1277*e4b17023SJohn Marino { 1278*e4b17023SJohn Marino insn = BB_HEAD (bb); 1279*e4b17023SJohn Marino if (LABEL_P (insn)) 1280*e4b17023SJohn Marino { 1281*e4b17023SJohn Marino HARD_REG_SET live; 1282*e4b17023SJohn Marino bitmap live_in = df_get_live_in (bb); 1283*e4b17023SJohn Marino 1284*e4b17023SJohn Marino REG_SET_TO_HARD_REG_SET (live, live_in); 1285*e4b17023SJohn Marino compute_use_by_pseudos (&live, live_in); 1286*e4b17023SJohn Marino COPY_HARD_REG_SET (LABEL_LIVE (insn), live); 1287*e4b17023SJohn Marino IOR_HARD_REG_SET (ever_live_at_start, live); 1288*e4b17023SJohn Marino } 1289*e4b17023SJohn Marino } 1290*e4b17023SJohn Marino 1291*e4b17023SJohn Marino /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ 1292*e4b17023SJohn Marino last_label_ruid = last_jump_ruid = reload_combine_ruid = 0; 1293*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1294*e4b17023SJohn Marino { 1295*e4b17023SJohn Marino reg_state[r].store_ruid = 0; 1296*e4b17023SJohn Marino reg_state[r].real_store_ruid = 0; 1297*e4b17023SJohn Marino if (fixed_regs[r]) 1298*e4b17023SJohn Marino reg_state[r].use_index = -1; 1299*e4b17023SJohn Marino else 1300*e4b17023SJohn Marino reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 1301*e4b17023SJohn Marino } 1302*e4b17023SJohn Marino 1303*e4b17023SJohn Marino for (insn = get_last_insn (); insn; insn = prev) 1304*e4b17023SJohn Marino { 1305*e4b17023SJohn Marino bool control_flow_insn; 1306*e4b17023SJohn Marino rtx note; 1307*e4b17023SJohn Marino 1308*e4b17023SJohn Marino prev = PREV_INSN (insn); 1309*e4b17023SJohn Marino 1310*e4b17023SJohn Marino /* We cannot do our optimization across labels. Invalidating all the use 1311*e4b17023SJohn Marino information we have would be costly, so we just note where the label 1312*e4b17023SJohn Marino is and then later disable any optimization that would cross it. */ 1313*e4b17023SJohn Marino if (LABEL_P (insn)) 1314*e4b17023SJohn Marino last_label_ruid = reload_combine_ruid; 1315*e4b17023SJohn Marino else if (BARRIER_P (insn)) 1316*e4b17023SJohn Marino { 1317*e4b17023SJohn Marino /* Crossing a barrier resets all the use information. */ 1318*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1319*e4b17023SJohn Marino if (! fixed_regs[r]) 1320*e4b17023SJohn Marino reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 1321*e4b17023SJohn Marino } 1322*e4b17023SJohn Marino else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn))) 1323*e4b17023SJohn Marino /* Optimizations across insns being marked as volatile must be 1324*e4b17023SJohn Marino prevented. All the usage information is invalidated 1325*e4b17023SJohn Marino here. */ 1326*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1327*e4b17023SJohn Marino if (! fixed_regs[r] 1328*e4b17023SJohn Marino && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES) 1329*e4b17023SJohn Marino reg_state[r].use_index = -1; 1330*e4b17023SJohn Marino 1331*e4b17023SJohn Marino if (! NONDEBUG_INSN_P (insn)) 1332*e4b17023SJohn Marino continue; 1333*e4b17023SJohn Marino 1334*e4b17023SJohn Marino reload_combine_ruid++; 1335*e4b17023SJohn Marino 1336*e4b17023SJohn Marino control_flow_insn = control_flow_insn_p (insn); 1337*e4b17023SJohn Marino if (control_flow_insn) 1338*e4b17023SJohn Marino last_jump_ruid = reload_combine_ruid; 1339*e4b17023SJohn Marino 1340*e4b17023SJohn Marino if (reload_combine_recognize_const_pattern (insn) 1341*e4b17023SJohn Marino || reload_combine_recognize_pattern (insn)) 1342*e4b17023SJohn Marino continue; 1343*e4b17023SJohn Marino 1344*e4b17023SJohn Marino note_stores (PATTERN (insn), reload_combine_note_store, NULL); 1345*e4b17023SJohn Marino 1346*e4b17023SJohn Marino if (CALL_P (insn)) 1347*e4b17023SJohn Marino { 1348*e4b17023SJohn Marino rtx link; 1349*e4b17023SJohn Marino 1350*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1351*e4b17023SJohn Marino if (call_used_regs[r]) 1352*e4b17023SJohn Marino { 1353*e4b17023SJohn Marino reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; 1354*e4b17023SJohn Marino reg_state[r].store_ruid = reload_combine_ruid; 1355*e4b17023SJohn Marino } 1356*e4b17023SJohn Marino 1357*e4b17023SJohn Marino for (link = CALL_INSN_FUNCTION_USAGE (insn); link; 1358*e4b17023SJohn Marino link = XEXP (link, 1)) 1359*e4b17023SJohn Marino { 1360*e4b17023SJohn Marino rtx usage_rtx = XEXP (XEXP (link, 0), 0); 1361*e4b17023SJohn Marino if (REG_P (usage_rtx)) 1362*e4b17023SJohn Marino { 1363*e4b17023SJohn Marino unsigned int i; 1364*e4b17023SJohn Marino unsigned int start_reg = REGNO (usage_rtx); 1365*e4b17023SJohn Marino unsigned int num_regs 1366*e4b17023SJohn Marino = hard_regno_nregs[start_reg][GET_MODE (usage_rtx)]; 1367*e4b17023SJohn Marino unsigned int end_reg = start_reg + num_regs - 1; 1368*e4b17023SJohn Marino for (i = start_reg; i <= end_reg; i++) 1369*e4b17023SJohn Marino if (GET_CODE (XEXP (link, 0)) == CLOBBER) 1370*e4b17023SJohn Marino { 1371*e4b17023SJohn Marino reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; 1372*e4b17023SJohn Marino reg_state[i].store_ruid = reload_combine_ruid; 1373*e4b17023SJohn Marino } 1374*e4b17023SJohn Marino else 1375*e4b17023SJohn Marino reg_state[i].use_index = -1; 1376*e4b17023SJohn Marino } 1377*e4b17023SJohn Marino } 1378*e4b17023SJohn Marino } 1379*e4b17023SJohn Marino 1380*e4b17023SJohn Marino if (control_flow_insn && GET_CODE (PATTERN (insn)) != RETURN) 1381*e4b17023SJohn Marino { 1382*e4b17023SJohn Marino /* Non-spill registers might be used at the call destination in 1383*e4b17023SJohn Marino some unknown fashion, so we have to mark the unknown use. */ 1384*e4b17023SJohn Marino HARD_REG_SET *live; 1385*e4b17023SJohn Marino 1386*e4b17023SJohn Marino if ((condjump_p (insn) || condjump_in_parallel_p (insn)) 1387*e4b17023SJohn Marino && JUMP_LABEL (insn)) 1388*e4b17023SJohn Marino live = &LABEL_LIVE (JUMP_LABEL (insn)); 1389*e4b17023SJohn Marino else 1390*e4b17023SJohn Marino live = &ever_live_at_start; 1391*e4b17023SJohn Marino 1392*e4b17023SJohn Marino for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) 1393*e4b17023SJohn Marino if (TEST_HARD_REG_BIT (*live, r)) 1394*e4b17023SJohn Marino reg_state[r].use_index = -1; 1395*e4b17023SJohn Marino } 1396*e4b17023SJohn Marino 1397*e4b17023SJohn Marino reload_combine_note_use (&PATTERN (insn), insn, reload_combine_ruid, 1398*e4b17023SJohn Marino NULL_RTX); 1399*e4b17023SJohn Marino 1400*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 1401*e4b17023SJohn Marino { 1402*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0))) 1403*e4b17023SJohn Marino { 1404*e4b17023SJohn Marino int regno = REGNO (XEXP (note, 0)); 1405*e4b17023SJohn Marino reg_state[regno].store_ruid = reload_combine_ruid; 1406*e4b17023SJohn Marino reg_state[regno].real_store_ruid = reload_combine_ruid; 1407*e4b17023SJohn Marino reg_state[regno].use_index = -1; 1408*e4b17023SJohn Marino } 1409*e4b17023SJohn Marino } 1410*e4b17023SJohn Marino } 1411*e4b17023SJohn Marino 1412*e4b17023SJohn Marino free (label_live); 1413*e4b17023SJohn Marino } 1414*e4b17023SJohn Marino 1415*e4b17023SJohn Marino /* Check if DST is a register or a subreg of a register; if it is, 1416*e4b17023SJohn Marino update store_ruid, real_store_ruid and use_index in the reg_state 1417*e4b17023SJohn Marino structure accordingly. Called via note_stores from reload_combine. */ 1418*e4b17023SJohn Marino 1419*e4b17023SJohn Marino static void 1420*e4b17023SJohn Marino reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED) 1421*e4b17023SJohn Marino { 1422*e4b17023SJohn Marino int regno = 0; 1423*e4b17023SJohn Marino int i; 1424*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (dst); 1425*e4b17023SJohn Marino 1426*e4b17023SJohn Marino if (GET_CODE (dst) == SUBREG) 1427*e4b17023SJohn Marino { 1428*e4b17023SJohn Marino regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)), 1429*e4b17023SJohn Marino GET_MODE (SUBREG_REG (dst)), 1430*e4b17023SJohn Marino SUBREG_BYTE (dst), 1431*e4b17023SJohn Marino GET_MODE (dst)); 1432*e4b17023SJohn Marino dst = SUBREG_REG (dst); 1433*e4b17023SJohn Marino } 1434*e4b17023SJohn Marino 1435*e4b17023SJohn Marino /* Some targets do argument pushes without adding REG_INC notes. */ 1436*e4b17023SJohn Marino 1437*e4b17023SJohn Marino if (MEM_P (dst)) 1438*e4b17023SJohn Marino { 1439*e4b17023SJohn Marino dst = XEXP (dst, 0); 1440*e4b17023SJohn Marino if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC 1441*e4b17023SJohn Marino || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC 1442*e4b17023SJohn Marino || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY) 1443*e4b17023SJohn Marino { 1444*e4b17023SJohn Marino regno = REGNO (XEXP (dst, 0)); 1445*e4b17023SJohn Marino mode = GET_MODE (XEXP (dst, 0)); 1446*e4b17023SJohn Marino for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) 1447*e4b17023SJohn Marino { 1448*e4b17023SJohn Marino /* We could probably do better, but for now mark the register 1449*e4b17023SJohn Marino as used in an unknown fashion and set/clobbered at this 1450*e4b17023SJohn Marino insn. */ 1451*e4b17023SJohn Marino reg_state[i].use_index = -1; 1452*e4b17023SJohn Marino reg_state[i].store_ruid = reload_combine_ruid; 1453*e4b17023SJohn Marino reg_state[i].real_store_ruid = reload_combine_ruid; 1454*e4b17023SJohn Marino } 1455*e4b17023SJohn Marino } 1456*e4b17023SJohn Marino else 1457*e4b17023SJohn Marino return; 1458*e4b17023SJohn Marino } 1459*e4b17023SJohn Marino 1460*e4b17023SJohn Marino if (!REG_P (dst)) 1461*e4b17023SJohn Marino return; 1462*e4b17023SJohn Marino regno += REGNO (dst); 1463*e4b17023SJohn Marino 1464*e4b17023SJohn Marino /* note_stores might have stripped a STRICT_LOW_PART, so we have to be 1465*e4b17023SJohn Marino careful with registers / register parts that are not full words. 1466*e4b17023SJohn Marino Similarly for ZERO_EXTRACT. */ 1467*e4b17023SJohn Marino if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT 1468*e4b17023SJohn Marino || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART) 1469*e4b17023SJohn Marino { 1470*e4b17023SJohn Marino for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) 1471*e4b17023SJohn Marino { 1472*e4b17023SJohn Marino reg_state[i].use_index = -1; 1473*e4b17023SJohn Marino reg_state[i].store_ruid = reload_combine_ruid; 1474*e4b17023SJohn Marino reg_state[i].real_store_ruid = reload_combine_ruid; 1475*e4b17023SJohn Marino } 1476*e4b17023SJohn Marino } 1477*e4b17023SJohn Marino else 1478*e4b17023SJohn Marino { 1479*e4b17023SJohn Marino for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) 1480*e4b17023SJohn Marino { 1481*e4b17023SJohn Marino reg_state[i].store_ruid = reload_combine_ruid; 1482*e4b17023SJohn Marino if (GET_CODE (set) == SET) 1483*e4b17023SJohn Marino reg_state[i].real_store_ruid = reload_combine_ruid; 1484*e4b17023SJohn Marino reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; 1485*e4b17023SJohn Marino } 1486*e4b17023SJohn Marino } 1487*e4b17023SJohn Marino } 1488*e4b17023SJohn Marino 1489*e4b17023SJohn Marino /* XP points to a piece of rtl that has to be checked for any uses of 1490*e4b17023SJohn Marino registers. 1491*e4b17023SJohn Marino *XP is the pattern of INSN, or a part of it. 1492*e4b17023SJohn Marino Called from reload_combine, and recursively by itself. */ 1493*e4b17023SJohn Marino static void 1494*e4b17023SJohn Marino reload_combine_note_use (rtx *xp, rtx insn, int ruid, rtx containing_mem) 1495*e4b17023SJohn Marino { 1496*e4b17023SJohn Marino rtx x = *xp; 1497*e4b17023SJohn Marino enum rtx_code code = x->code; 1498*e4b17023SJohn Marino const char *fmt; 1499*e4b17023SJohn Marino int i, j; 1500*e4b17023SJohn Marino rtx offset = const0_rtx; /* For the REG case below. */ 1501*e4b17023SJohn Marino 1502*e4b17023SJohn Marino switch (code) 1503*e4b17023SJohn Marino { 1504*e4b17023SJohn Marino case SET: 1505*e4b17023SJohn Marino if (REG_P (SET_DEST (x))) 1506*e4b17023SJohn Marino { 1507*e4b17023SJohn Marino reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX); 1508*e4b17023SJohn Marino return; 1509*e4b17023SJohn Marino } 1510*e4b17023SJohn Marino break; 1511*e4b17023SJohn Marino 1512*e4b17023SJohn Marino case USE: 1513*e4b17023SJohn Marino /* If this is the USE of a return value, we can't change it. */ 1514*e4b17023SJohn Marino if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0))) 1515*e4b17023SJohn Marino { 1516*e4b17023SJohn Marino /* Mark the return register as used in an unknown fashion. */ 1517*e4b17023SJohn Marino rtx reg = XEXP (x, 0); 1518*e4b17023SJohn Marino int regno = REGNO (reg); 1519*e4b17023SJohn Marino int nregs = hard_regno_nregs[regno][GET_MODE (reg)]; 1520*e4b17023SJohn Marino 1521*e4b17023SJohn Marino while (--nregs >= 0) 1522*e4b17023SJohn Marino reg_state[regno + nregs].use_index = -1; 1523*e4b17023SJohn Marino return; 1524*e4b17023SJohn Marino } 1525*e4b17023SJohn Marino break; 1526*e4b17023SJohn Marino 1527*e4b17023SJohn Marino case CLOBBER: 1528*e4b17023SJohn Marino if (REG_P (SET_DEST (x))) 1529*e4b17023SJohn Marino { 1530*e4b17023SJohn Marino /* No spurious CLOBBERs of pseudo registers may remain. */ 1531*e4b17023SJohn Marino gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER); 1532*e4b17023SJohn Marino return; 1533*e4b17023SJohn Marino } 1534*e4b17023SJohn Marino break; 1535*e4b17023SJohn Marino 1536*e4b17023SJohn Marino case PLUS: 1537*e4b17023SJohn Marino /* We are interested in (plus (reg) (const_int)) . */ 1538*e4b17023SJohn Marino if (!REG_P (XEXP (x, 0)) 1539*e4b17023SJohn Marino || !CONST_INT_P (XEXP (x, 1))) 1540*e4b17023SJohn Marino break; 1541*e4b17023SJohn Marino offset = XEXP (x, 1); 1542*e4b17023SJohn Marino x = XEXP (x, 0); 1543*e4b17023SJohn Marino /* Fall through. */ 1544*e4b17023SJohn Marino case REG: 1545*e4b17023SJohn Marino { 1546*e4b17023SJohn Marino int regno = REGNO (x); 1547*e4b17023SJohn Marino int use_index; 1548*e4b17023SJohn Marino int nregs; 1549*e4b17023SJohn Marino 1550*e4b17023SJohn Marino /* No spurious USEs of pseudo registers may remain. */ 1551*e4b17023SJohn Marino gcc_assert (regno < FIRST_PSEUDO_REGISTER); 1552*e4b17023SJohn Marino 1553*e4b17023SJohn Marino nregs = hard_regno_nregs[regno][GET_MODE (x)]; 1554*e4b17023SJohn Marino 1555*e4b17023SJohn Marino /* We can't substitute into multi-hard-reg uses. */ 1556*e4b17023SJohn Marino if (nregs > 1) 1557*e4b17023SJohn Marino { 1558*e4b17023SJohn Marino while (--nregs >= 0) 1559*e4b17023SJohn Marino reg_state[regno + nregs].use_index = -1; 1560*e4b17023SJohn Marino return; 1561*e4b17023SJohn Marino } 1562*e4b17023SJohn Marino 1563*e4b17023SJohn Marino /* We may be called to update uses in previously seen insns. 1564*e4b17023SJohn Marino Don't add uses beyond the last store we saw. */ 1565*e4b17023SJohn Marino if (ruid < reg_state[regno].store_ruid) 1566*e4b17023SJohn Marino return; 1567*e4b17023SJohn Marino 1568*e4b17023SJohn Marino /* If this register is already used in some unknown fashion, we 1569*e4b17023SJohn Marino can't do anything. 1570*e4b17023SJohn Marino If we decrement the index from zero to -1, we can't store more 1571*e4b17023SJohn Marino uses, so this register becomes used in an unknown fashion. */ 1572*e4b17023SJohn Marino use_index = --reg_state[regno].use_index; 1573*e4b17023SJohn Marino if (use_index < 0) 1574*e4b17023SJohn Marino return; 1575*e4b17023SJohn Marino 1576*e4b17023SJohn Marino if (use_index == RELOAD_COMBINE_MAX_USES - 1) 1577*e4b17023SJohn Marino { 1578*e4b17023SJohn Marino /* This is the first use of this register we have seen since we 1579*e4b17023SJohn Marino marked it as dead. */ 1580*e4b17023SJohn Marino reg_state[regno].offset = offset; 1581*e4b17023SJohn Marino reg_state[regno].all_offsets_match = true; 1582*e4b17023SJohn Marino reg_state[regno].use_ruid = ruid; 1583*e4b17023SJohn Marino } 1584*e4b17023SJohn Marino else 1585*e4b17023SJohn Marino { 1586*e4b17023SJohn Marino if (reg_state[regno].use_ruid > ruid) 1587*e4b17023SJohn Marino reg_state[regno].use_ruid = ruid; 1588*e4b17023SJohn Marino 1589*e4b17023SJohn Marino if (! rtx_equal_p (offset, reg_state[regno].offset)) 1590*e4b17023SJohn Marino reg_state[regno].all_offsets_match = false; 1591*e4b17023SJohn Marino } 1592*e4b17023SJohn Marino 1593*e4b17023SJohn Marino reg_state[regno].reg_use[use_index].insn = insn; 1594*e4b17023SJohn Marino reg_state[regno].reg_use[use_index].ruid = ruid; 1595*e4b17023SJohn Marino reg_state[regno].reg_use[use_index].containing_mem = containing_mem; 1596*e4b17023SJohn Marino reg_state[regno].reg_use[use_index].usep = xp; 1597*e4b17023SJohn Marino return; 1598*e4b17023SJohn Marino } 1599*e4b17023SJohn Marino 1600*e4b17023SJohn Marino case MEM: 1601*e4b17023SJohn Marino containing_mem = x; 1602*e4b17023SJohn Marino break; 1603*e4b17023SJohn Marino 1604*e4b17023SJohn Marino default: 1605*e4b17023SJohn Marino break; 1606*e4b17023SJohn Marino } 1607*e4b17023SJohn Marino 1608*e4b17023SJohn Marino /* Recursively process the components of X. */ 1609*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code); 1610*e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 1611*e4b17023SJohn Marino { 1612*e4b17023SJohn Marino if (fmt[i] == 'e') 1613*e4b17023SJohn Marino reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem); 1614*e4b17023SJohn Marino else if (fmt[i] == 'E') 1615*e4b17023SJohn Marino { 1616*e4b17023SJohn Marino for (j = XVECLEN (x, i) - 1; j >= 0; j--) 1617*e4b17023SJohn Marino reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid, 1618*e4b17023SJohn Marino containing_mem); 1619*e4b17023SJohn Marino } 1620*e4b17023SJohn Marino } 1621*e4b17023SJohn Marino } 1622*e4b17023SJohn Marino 1623*e4b17023SJohn Marino /* See if we can reduce the cost of a constant by replacing a move 1624*e4b17023SJohn Marino with an add. We track situations in which a register is set to a 1625*e4b17023SJohn Marino constant or to a register plus a constant. */ 1626*e4b17023SJohn Marino /* We cannot do our optimization across labels. Invalidating all the 1627*e4b17023SJohn Marino information about register contents we have would be costly, so we 1628*e4b17023SJohn Marino use move2add_last_label_luid to note where the label is and then 1629*e4b17023SJohn Marino later disable any optimization that would cross it. 1630*e4b17023SJohn Marino reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n] 1631*e4b17023SJohn Marino are only valid if reg_set_luid[n] is greater than 1632*e4b17023SJohn Marino move2add_last_label_luid. */ 1633*e4b17023SJohn Marino static int reg_set_luid[FIRST_PSEUDO_REGISTER]; 1634*e4b17023SJohn Marino 1635*e4b17023SJohn Marino /* If reg_base_reg[n] is negative, register n has been set to 1636*e4b17023SJohn Marino reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n]. 1637*e4b17023SJohn Marino If reg_base_reg[n] is non-negative, register n has been set to the 1638*e4b17023SJohn Marino sum of reg_offset[n] and the value of register reg_base_reg[n] 1639*e4b17023SJohn Marino before reg_set_luid[n], calculated in mode reg_mode[n] . */ 1640*e4b17023SJohn Marino static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER]; 1641*e4b17023SJohn Marino static int reg_base_reg[FIRST_PSEUDO_REGISTER]; 1642*e4b17023SJohn Marino static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER]; 1643*e4b17023SJohn Marino static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER]; 1644*e4b17023SJohn Marino 1645*e4b17023SJohn Marino /* move2add_luid is linearly increased while scanning the instructions 1646*e4b17023SJohn Marino from first to last. It is used to set reg_set_luid in 1647*e4b17023SJohn Marino reload_cse_move2add and move2add_note_store. */ 1648*e4b17023SJohn Marino static int move2add_luid; 1649*e4b17023SJohn Marino 1650*e4b17023SJohn Marino /* move2add_last_label_luid is set whenever a label is found. Labels 1651*e4b17023SJohn Marino invalidate all previously collected reg_offset data. */ 1652*e4b17023SJohn Marino static int move2add_last_label_luid; 1653*e4b17023SJohn Marino 1654*e4b17023SJohn Marino /* ??? We don't know how zero / sign extension is handled, hence we 1655*e4b17023SJohn Marino can't go from a narrower to a wider mode. */ 1656*e4b17023SJohn Marino #define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \ 1657*e4b17023SJohn Marino (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \ 1658*e4b17023SJohn Marino || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \ 1659*e4b17023SJohn Marino && TRULY_NOOP_TRUNCATION_MODES_P (OUTMODE, INMODE))) 1660*e4b17023SJohn Marino 1661*e4b17023SJohn Marino /* This function is called with INSN that sets REG to (SYM + OFF), 1662*e4b17023SJohn Marino while REG is known to already have value (SYM + offset). 1663*e4b17023SJohn Marino This function tries to change INSN into an add instruction 1664*e4b17023SJohn Marino (set (REG) (plus (REG) (OFF - offset))) using the known value. 1665*e4b17023SJohn Marino It also updates the information about REG's known value. 1666*e4b17023SJohn Marino Return true if we made a change. */ 1667*e4b17023SJohn Marino 1668*e4b17023SJohn Marino static bool 1669*e4b17023SJohn Marino move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn) 1670*e4b17023SJohn Marino { 1671*e4b17023SJohn Marino rtx pat = PATTERN (insn); 1672*e4b17023SJohn Marino rtx src = SET_SRC (pat); 1673*e4b17023SJohn Marino int regno = REGNO (reg); 1674*e4b17023SJohn Marino rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[regno], 1675*e4b17023SJohn Marino GET_MODE (reg)); 1676*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 1677*e4b17023SJohn Marino bool changed = false; 1678*e4b17023SJohn Marino 1679*e4b17023SJohn Marino /* (set (reg) (plus (reg) (const_int 0))) is not canonical; 1680*e4b17023SJohn Marino use (set (reg) (reg)) instead. 1681*e4b17023SJohn Marino We don't delete this insn, nor do we convert it into a 1682*e4b17023SJohn Marino note, to avoid losing register notes or the return 1683*e4b17023SJohn Marino value flag. jump2 already knows how to get rid of 1684*e4b17023SJohn Marino no-op moves. */ 1685*e4b17023SJohn Marino if (new_src == const0_rtx) 1686*e4b17023SJohn Marino { 1687*e4b17023SJohn Marino /* If the constants are different, this is a 1688*e4b17023SJohn Marino truncation, that, if turned into (set (reg) 1689*e4b17023SJohn Marino (reg)), would be discarded. Maybe we should 1690*e4b17023SJohn Marino try a truncMN pattern? */ 1691*e4b17023SJohn Marino if (INTVAL (off) == reg_offset [regno]) 1692*e4b17023SJohn Marino changed = validate_change (insn, &SET_SRC (pat), reg, 0); 1693*e4b17023SJohn Marino } 1694*e4b17023SJohn Marino else 1695*e4b17023SJohn Marino { 1696*e4b17023SJohn Marino struct full_rtx_costs oldcst, newcst; 1697*e4b17023SJohn Marino rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); 1698*e4b17023SJohn Marino 1699*e4b17023SJohn Marino get_full_set_rtx_cost (pat, &oldcst); 1700*e4b17023SJohn Marino SET_SRC (pat) = tem; 1701*e4b17023SJohn Marino get_full_set_rtx_cost (pat, &newcst); 1702*e4b17023SJohn Marino SET_SRC (pat) = src; 1703*e4b17023SJohn Marino 1704*e4b17023SJohn Marino if (costs_lt_p (&newcst, &oldcst, speed) 1705*e4b17023SJohn Marino && have_add2_insn (reg, new_src)) 1706*e4b17023SJohn Marino changed = validate_change (insn, &SET_SRC (pat), tem, 0); 1707*e4b17023SJohn Marino else if (sym == NULL_RTX && GET_MODE (reg) != BImode) 1708*e4b17023SJohn Marino { 1709*e4b17023SJohn Marino enum machine_mode narrow_mode; 1710*e4b17023SJohn Marino for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); 1711*e4b17023SJohn Marino narrow_mode != VOIDmode 1712*e4b17023SJohn Marino && narrow_mode != GET_MODE (reg); 1713*e4b17023SJohn Marino narrow_mode = GET_MODE_WIDER_MODE (narrow_mode)) 1714*e4b17023SJohn Marino { 1715*e4b17023SJohn Marino if (have_insn_for (STRICT_LOW_PART, narrow_mode) 1716*e4b17023SJohn Marino && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode)) 1717*e4b17023SJohn Marino == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode)))) 1718*e4b17023SJohn Marino { 1719*e4b17023SJohn Marino rtx narrow_reg = gen_rtx_REG (narrow_mode, 1720*e4b17023SJohn Marino REGNO (reg)); 1721*e4b17023SJohn Marino rtx narrow_src = gen_int_mode (INTVAL (off), 1722*e4b17023SJohn Marino narrow_mode); 1723*e4b17023SJohn Marino rtx new_set 1724*e4b17023SJohn Marino = gen_rtx_SET (VOIDmode, 1725*e4b17023SJohn Marino gen_rtx_STRICT_LOW_PART (VOIDmode, 1726*e4b17023SJohn Marino narrow_reg), 1727*e4b17023SJohn Marino narrow_src); 1728*e4b17023SJohn Marino changed = validate_change (insn, &PATTERN (insn), 1729*e4b17023SJohn Marino new_set, 0); 1730*e4b17023SJohn Marino if (changed) 1731*e4b17023SJohn Marino break; 1732*e4b17023SJohn Marino } 1733*e4b17023SJohn Marino } 1734*e4b17023SJohn Marino } 1735*e4b17023SJohn Marino } 1736*e4b17023SJohn Marino reg_set_luid[regno] = move2add_luid; 1737*e4b17023SJohn Marino reg_base_reg[regno] = -1; 1738*e4b17023SJohn Marino reg_mode[regno] = GET_MODE (reg); 1739*e4b17023SJohn Marino reg_symbol_ref[regno] = sym; 1740*e4b17023SJohn Marino reg_offset[regno] = INTVAL (off); 1741*e4b17023SJohn Marino return changed; 1742*e4b17023SJohn Marino } 1743*e4b17023SJohn Marino 1744*e4b17023SJohn Marino 1745*e4b17023SJohn Marino /* This function is called with INSN that sets REG to (SYM + OFF), 1746*e4b17023SJohn Marino but REG doesn't have known value (SYM + offset). This function 1747*e4b17023SJohn Marino tries to find another register which is known to already have 1748*e4b17023SJohn Marino value (SYM + offset) and change INSN into an add instruction 1749*e4b17023SJohn Marino (set (REG) (plus (the found register) (OFF - offset))) if such 1750*e4b17023SJohn Marino a register is found. It also updates the information about 1751*e4b17023SJohn Marino REG's known value. 1752*e4b17023SJohn Marino Return true iff we made a change. */ 1753*e4b17023SJohn Marino 1754*e4b17023SJohn Marino static bool 1755*e4b17023SJohn Marino move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn) 1756*e4b17023SJohn Marino { 1757*e4b17023SJohn Marino rtx pat = PATTERN (insn); 1758*e4b17023SJohn Marino rtx src = SET_SRC (pat); 1759*e4b17023SJohn Marino int regno = REGNO (reg); 1760*e4b17023SJohn Marino int min_regno = 0; 1761*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 1762*e4b17023SJohn Marino int i; 1763*e4b17023SJohn Marino bool changed = false; 1764*e4b17023SJohn Marino struct full_rtx_costs oldcst, newcst, mincst; 1765*e4b17023SJohn Marino rtx plus_expr; 1766*e4b17023SJohn Marino 1767*e4b17023SJohn Marino init_costs_to_max (&mincst); 1768*e4b17023SJohn Marino get_full_set_rtx_cost (pat, &oldcst); 1769*e4b17023SJohn Marino 1770*e4b17023SJohn Marino plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx); 1771*e4b17023SJohn Marino SET_SRC (pat) = plus_expr; 1772*e4b17023SJohn Marino 1773*e4b17023SJohn Marino for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1774*e4b17023SJohn Marino if (reg_set_luid[i] > move2add_last_label_luid 1775*e4b17023SJohn Marino && reg_mode[i] == GET_MODE (reg) 1776*e4b17023SJohn Marino && reg_base_reg[i] < 0 1777*e4b17023SJohn Marino && reg_symbol_ref[i] != NULL_RTX 1778*e4b17023SJohn Marino && rtx_equal_p (sym, reg_symbol_ref[i])) 1779*e4b17023SJohn Marino { 1780*e4b17023SJohn Marino rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[i], 1781*e4b17023SJohn Marino GET_MODE (reg)); 1782*e4b17023SJohn Marino /* (set (reg) (plus (reg) (const_int 0))) is not canonical; 1783*e4b17023SJohn Marino use (set (reg) (reg)) instead. 1784*e4b17023SJohn Marino We don't delete this insn, nor do we convert it into a 1785*e4b17023SJohn Marino note, to avoid losing register notes or the return 1786*e4b17023SJohn Marino value flag. jump2 already knows how to get rid of 1787*e4b17023SJohn Marino no-op moves. */ 1788*e4b17023SJohn Marino if (new_src == const0_rtx) 1789*e4b17023SJohn Marino { 1790*e4b17023SJohn Marino init_costs_to_zero (&mincst); 1791*e4b17023SJohn Marino min_regno = i; 1792*e4b17023SJohn Marino break; 1793*e4b17023SJohn Marino } 1794*e4b17023SJohn Marino else 1795*e4b17023SJohn Marino { 1796*e4b17023SJohn Marino XEXP (plus_expr, 1) = new_src; 1797*e4b17023SJohn Marino get_full_set_rtx_cost (pat, &newcst); 1798*e4b17023SJohn Marino 1799*e4b17023SJohn Marino if (costs_lt_p (&newcst, &mincst, speed)) 1800*e4b17023SJohn Marino { 1801*e4b17023SJohn Marino mincst = newcst; 1802*e4b17023SJohn Marino min_regno = i; 1803*e4b17023SJohn Marino } 1804*e4b17023SJohn Marino } 1805*e4b17023SJohn Marino } 1806*e4b17023SJohn Marino SET_SRC (pat) = src; 1807*e4b17023SJohn Marino 1808*e4b17023SJohn Marino if (costs_lt_p (&mincst, &oldcst, speed)) 1809*e4b17023SJohn Marino { 1810*e4b17023SJohn Marino rtx tem; 1811*e4b17023SJohn Marino 1812*e4b17023SJohn Marino tem = gen_rtx_REG (GET_MODE (reg), min_regno); 1813*e4b17023SJohn Marino if (i != min_regno) 1814*e4b17023SJohn Marino { 1815*e4b17023SJohn Marino rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[min_regno], 1816*e4b17023SJohn Marino GET_MODE (reg)); 1817*e4b17023SJohn Marino tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src); 1818*e4b17023SJohn Marino } 1819*e4b17023SJohn Marino if (validate_change (insn, &SET_SRC (pat), tem, 0)) 1820*e4b17023SJohn Marino changed = true; 1821*e4b17023SJohn Marino } 1822*e4b17023SJohn Marino reg_set_luid[regno] = move2add_luid; 1823*e4b17023SJohn Marino reg_base_reg[regno] = -1; 1824*e4b17023SJohn Marino reg_mode[regno] = GET_MODE (reg); 1825*e4b17023SJohn Marino reg_symbol_ref[regno] = sym; 1826*e4b17023SJohn Marino reg_offset[regno] = INTVAL (off); 1827*e4b17023SJohn Marino return changed; 1828*e4b17023SJohn Marino } 1829*e4b17023SJohn Marino 1830*e4b17023SJohn Marino /* Convert move insns with constant inputs to additions if they are cheaper. 1831*e4b17023SJohn Marino Return true if any changes were made. */ 1832*e4b17023SJohn Marino static bool 1833*e4b17023SJohn Marino reload_cse_move2add (rtx first) 1834*e4b17023SJohn Marino { 1835*e4b17023SJohn Marino int i; 1836*e4b17023SJohn Marino rtx insn; 1837*e4b17023SJohn Marino bool changed = false; 1838*e4b17023SJohn Marino 1839*e4b17023SJohn Marino for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) 1840*e4b17023SJohn Marino { 1841*e4b17023SJohn Marino reg_set_luid[i] = 0; 1842*e4b17023SJohn Marino reg_offset[i] = 0; 1843*e4b17023SJohn Marino reg_base_reg[i] = 0; 1844*e4b17023SJohn Marino reg_symbol_ref[i] = NULL_RTX; 1845*e4b17023SJohn Marino reg_mode[i] = VOIDmode; 1846*e4b17023SJohn Marino } 1847*e4b17023SJohn Marino 1848*e4b17023SJohn Marino move2add_last_label_luid = 0; 1849*e4b17023SJohn Marino move2add_luid = 2; 1850*e4b17023SJohn Marino for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++) 1851*e4b17023SJohn Marino { 1852*e4b17023SJohn Marino rtx pat, note; 1853*e4b17023SJohn Marino 1854*e4b17023SJohn Marino if (LABEL_P (insn)) 1855*e4b17023SJohn Marino { 1856*e4b17023SJohn Marino move2add_last_label_luid = move2add_luid; 1857*e4b17023SJohn Marino /* We're going to increment move2add_luid twice after a 1858*e4b17023SJohn Marino label, so that we can use move2add_last_label_luid + 1 as 1859*e4b17023SJohn Marino the luid for constants. */ 1860*e4b17023SJohn Marino move2add_luid++; 1861*e4b17023SJohn Marino continue; 1862*e4b17023SJohn Marino } 1863*e4b17023SJohn Marino if (! INSN_P (insn)) 1864*e4b17023SJohn Marino continue; 1865*e4b17023SJohn Marino pat = PATTERN (insn); 1866*e4b17023SJohn Marino /* For simplicity, we only perform this optimization on 1867*e4b17023SJohn Marino straightforward SETs. */ 1868*e4b17023SJohn Marino if (GET_CODE (pat) == SET 1869*e4b17023SJohn Marino && REG_P (SET_DEST (pat))) 1870*e4b17023SJohn Marino { 1871*e4b17023SJohn Marino rtx reg = SET_DEST (pat); 1872*e4b17023SJohn Marino int regno = REGNO (reg); 1873*e4b17023SJohn Marino rtx src = SET_SRC (pat); 1874*e4b17023SJohn Marino 1875*e4b17023SJohn Marino /* Check if we have valid information on the contents of this 1876*e4b17023SJohn Marino register in the mode of REG. */ 1877*e4b17023SJohn Marino if (reg_set_luid[regno] > move2add_last_label_luid 1878*e4b17023SJohn Marino && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]) 1879*e4b17023SJohn Marino && dbg_cnt (cse2_move2add)) 1880*e4b17023SJohn Marino { 1881*e4b17023SJohn Marino /* Try to transform (set (REGX) (CONST_INT A)) 1882*e4b17023SJohn Marino ... 1883*e4b17023SJohn Marino (set (REGX) (CONST_INT B)) 1884*e4b17023SJohn Marino to 1885*e4b17023SJohn Marino (set (REGX) (CONST_INT A)) 1886*e4b17023SJohn Marino ... 1887*e4b17023SJohn Marino (set (REGX) (plus (REGX) (CONST_INT B-A))) 1888*e4b17023SJohn Marino or 1889*e4b17023SJohn Marino (set (REGX) (CONST_INT A)) 1890*e4b17023SJohn Marino ... 1891*e4b17023SJohn Marino (set (STRICT_LOW_PART (REGX)) (CONST_INT B)) 1892*e4b17023SJohn Marino */ 1893*e4b17023SJohn Marino 1894*e4b17023SJohn Marino if (CONST_INT_P (src) 1895*e4b17023SJohn Marino && reg_base_reg[regno] < 0 1896*e4b17023SJohn Marino && reg_symbol_ref[regno] == NULL_RTX) 1897*e4b17023SJohn Marino { 1898*e4b17023SJohn Marino changed |= move2add_use_add2_insn (reg, NULL_RTX, src, insn); 1899*e4b17023SJohn Marino continue; 1900*e4b17023SJohn Marino } 1901*e4b17023SJohn Marino 1902*e4b17023SJohn Marino /* Try to transform (set (REGX) (REGY)) 1903*e4b17023SJohn Marino (set (REGX) (PLUS (REGX) (CONST_INT A))) 1904*e4b17023SJohn Marino ... 1905*e4b17023SJohn Marino (set (REGX) (REGY)) 1906*e4b17023SJohn Marino (set (REGX) (PLUS (REGX) (CONST_INT B))) 1907*e4b17023SJohn Marino to 1908*e4b17023SJohn Marino (set (REGX) (REGY)) 1909*e4b17023SJohn Marino (set (REGX) (PLUS (REGX) (CONST_INT A))) 1910*e4b17023SJohn Marino ... 1911*e4b17023SJohn Marino (set (REGX) (plus (REGX) (CONST_INT B-A))) */ 1912*e4b17023SJohn Marino else if (REG_P (src) 1913*e4b17023SJohn Marino && reg_set_luid[regno] == reg_set_luid[REGNO (src)] 1914*e4b17023SJohn Marino && reg_base_reg[regno] == reg_base_reg[REGNO (src)] 1915*e4b17023SJohn Marino && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), 1916*e4b17023SJohn Marino reg_mode[REGNO (src)])) 1917*e4b17023SJohn Marino { 1918*e4b17023SJohn Marino rtx next = next_nonnote_nondebug_insn (insn); 1919*e4b17023SJohn Marino rtx set = NULL_RTX; 1920*e4b17023SJohn Marino if (next) 1921*e4b17023SJohn Marino set = single_set (next); 1922*e4b17023SJohn Marino if (set 1923*e4b17023SJohn Marino && SET_DEST (set) == reg 1924*e4b17023SJohn Marino && GET_CODE (SET_SRC (set)) == PLUS 1925*e4b17023SJohn Marino && XEXP (SET_SRC (set), 0) == reg 1926*e4b17023SJohn Marino && CONST_INT_P (XEXP (SET_SRC (set), 1))) 1927*e4b17023SJohn Marino { 1928*e4b17023SJohn Marino rtx src3 = XEXP (SET_SRC (set), 1); 1929*e4b17023SJohn Marino HOST_WIDE_INT added_offset = INTVAL (src3); 1930*e4b17023SJohn Marino HOST_WIDE_INT base_offset = reg_offset[REGNO (src)]; 1931*e4b17023SJohn Marino HOST_WIDE_INT regno_offset = reg_offset[regno]; 1932*e4b17023SJohn Marino rtx new_src = 1933*e4b17023SJohn Marino gen_int_mode (added_offset 1934*e4b17023SJohn Marino + base_offset 1935*e4b17023SJohn Marino - regno_offset, 1936*e4b17023SJohn Marino GET_MODE (reg)); 1937*e4b17023SJohn Marino bool success = false; 1938*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 1939*e4b17023SJohn Marino 1940*e4b17023SJohn Marino if (new_src == const0_rtx) 1941*e4b17023SJohn Marino /* See above why we create (set (reg) (reg)) here. */ 1942*e4b17023SJohn Marino success 1943*e4b17023SJohn Marino = validate_change (next, &SET_SRC (set), reg, 0); 1944*e4b17023SJohn Marino else 1945*e4b17023SJohn Marino { 1946*e4b17023SJohn Marino rtx old_src = SET_SRC (set); 1947*e4b17023SJohn Marino struct full_rtx_costs oldcst, newcst; 1948*e4b17023SJohn Marino rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); 1949*e4b17023SJohn Marino 1950*e4b17023SJohn Marino get_full_set_rtx_cost (set, &oldcst); 1951*e4b17023SJohn Marino SET_SRC (set) = tem; 1952*e4b17023SJohn Marino get_full_set_src_cost (tem, &newcst); 1953*e4b17023SJohn Marino SET_SRC (set) = old_src; 1954*e4b17023SJohn Marino costs_add_n_insns (&oldcst, 1); 1955*e4b17023SJohn Marino 1956*e4b17023SJohn Marino if (costs_lt_p (&newcst, &oldcst, speed) 1957*e4b17023SJohn Marino && have_add2_insn (reg, new_src)) 1958*e4b17023SJohn Marino { 1959*e4b17023SJohn Marino rtx newpat = gen_rtx_SET (VOIDmode, reg, tem); 1960*e4b17023SJohn Marino success 1961*e4b17023SJohn Marino = validate_change (next, &PATTERN (next), 1962*e4b17023SJohn Marino newpat, 0); 1963*e4b17023SJohn Marino } 1964*e4b17023SJohn Marino } 1965*e4b17023SJohn Marino if (success) 1966*e4b17023SJohn Marino delete_insn (insn); 1967*e4b17023SJohn Marino changed |= success; 1968*e4b17023SJohn Marino insn = next; 1969*e4b17023SJohn Marino reg_mode[regno] = GET_MODE (reg); 1970*e4b17023SJohn Marino reg_offset[regno] = 1971*e4b17023SJohn Marino trunc_int_for_mode (added_offset + base_offset, 1972*e4b17023SJohn Marino GET_MODE (reg)); 1973*e4b17023SJohn Marino continue; 1974*e4b17023SJohn Marino } 1975*e4b17023SJohn Marino } 1976*e4b17023SJohn Marino } 1977*e4b17023SJohn Marino 1978*e4b17023SJohn Marino /* Try to transform 1979*e4b17023SJohn Marino (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A)))) 1980*e4b17023SJohn Marino ... 1981*e4b17023SJohn Marino (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B)))) 1982*e4b17023SJohn Marino to 1983*e4b17023SJohn Marino (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A)))) 1984*e4b17023SJohn Marino ... 1985*e4b17023SJohn Marino (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A)))) */ 1986*e4b17023SJohn Marino if ((GET_CODE (src) == SYMBOL_REF 1987*e4b17023SJohn Marino || (GET_CODE (src) == CONST 1988*e4b17023SJohn Marino && GET_CODE (XEXP (src, 0)) == PLUS 1989*e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF 1990*e4b17023SJohn Marino && CONST_INT_P (XEXP (XEXP (src, 0), 1)))) 1991*e4b17023SJohn Marino && dbg_cnt (cse2_move2add)) 1992*e4b17023SJohn Marino { 1993*e4b17023SJohn Marino rtx sym, off; 1994*e4b17023SJohn Marino 1995*e4b17023SJohn Marino if (GET_CODE (src) == SYMBOL_REF) 1996*e4b17023SJohn Marino { 1997*e4b17023SJohn Marino sym = src; 1998*e4b17023SJohn Marino off = const0_rtx; 1999*e4b17023SJohn Marino } 2000*e4b17023SJohn Marino else 2001*e4b17023SJohn Marino { 2002*e4b17023SJohn Marino sym = XEXP (XEXP (src, 0), 0); 2003*e4b17023SJohn Marino off = XEXP (XEXP (src, 0), 1); 2004*e4b17023SJohn Marino } 2005*e4b17023SJohn Marino 2006*e4b17023SJohn Marino /* If the reg already contains the value which is sum of 2007*e4b17023SJohn Marino sym and some constant value, we can use an add2 insn. */ 2008*e4b17023SJohn Marino if (reg_set_luid[regno] > move2add_last_label_luid 2009*e4b17023SJohn Marino && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]) 2010*e4b17023SJohn Marino && reg_base_reg[regno] < 0 2011*e4b17023SJohn Marino && reg_symbol_ref[regno] != NULL_RTX 2012*e4b17023SJohn Marino && rtx_equal_p (sym, reg_symbol_ref[regno])) 2013*e4b17023SJohn Marino changed |= move2add_use_add2_insn (reg, sym, off, insn); 2014*e4b17023SJohn Marino 2015*e4b17023SJohn Marino /* Otherwise, we have to find a register whose value is sum 2016*e4b17023SJohn Marino of sym and some constant value. */ 2017*e4b17023SJohn Marino else 2018*e4b17023SJohn Marino changed |= move2add_use_add3_insn (reg, sym, off, insn); 2019*e4b17023SJohn Marino 2020*e4b17023SJohn Marino continue; 2021*e4b17023SJohn Marino } 2022*e4b17023SJohn Marino } 2023*e4b17023SJohn Marino 2024*e4b17023SJohn Marino for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 2025*e4b17023SJohn Marino { 2026*e4b17023SJohn Marino if (REG_NOTE_KIND (note) == REG_INC 2027*e4b17023SJohn Marino && REG_P (XEXP (note, 0))) 2028*e4b17023SJohn Marino { 2029*e4b17023SJohn Marino /* Reset the information about this register. */ 2030*e4b17023SJohn Marino int regno = REGNO (XEXP (note, 0)); 2031*e4b17023SJohn Marino if (regno < FIRST_PSEUDO_REGISTER) 2032*e4b17023SJohn Marino reg_set_luid[regno] = 0; 2033*e4b17023SJohn Marino } 2034*e4b17023SJohn Marino } 2035*e4b17023SJohn Marino note_stores (PATTERN (insn), move2add_note_store, insn); 2036*e4b17023SJohn Marino 2037*e4b17023SJohn Marino /* If INSN is a conditional branch, we try to extract an 2038*e4b17023SJohn Marino implicit set out of it. */ 2039*e4b17023SJohn Marino if (any_condjump_p (insn)) 2040*e4b17023SJohn Marino { 2041*e4b17023SJohn Marino rtx cnd = fis_get_condition (insn); 2042*e4b17023SJohn Marino 2043*e4b17023SJohn Marino if (cnd != NULL_RTX 2044*e4b17023SJohn Marino && GET_CODE (cnd) == NE 2045*e4b17023SJohn Marino && REG_P (XEXP (cnd, 0)) 2046*e4b17023SJohn Marino && !reg_set_p (XEXP (cnd, 0), insn) 2047*e4b17023SJohn Marino /* The following two checks, which are also in 2048*e4b17023SJohn Marino move2add_note_store, are intended to reduce the 2049*e4b17023SJohn Marino number of calls to gen_rtx_SET to avoid memory 2050*e4b17023SJohn Marino allocation if possible. */ 2051*e4b17023SJohn Marino && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0))) 2052*e4b17023SJohn Marino && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1 2053*e4b17023SJohn Marino && CONST_INT_P (XEXP (cnd, 1))) 2054*e4b17023SJohn Marino { 2055*e4b17023SJohn Marino rtx implicit_set = 2056*e4b17023SJohn Marino gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1)); 2057*e4b17023SJohn Marino move2add_note_store (SET_DEST (implicit_set), implicit_set, insn); 2058*e4b17023SJohn Marino } 2059*e4b17023SJohn Marino } 2060*e4b17023SJohn Marino 2061*e4b17023SJohn Marino /* If this is a CALL_INSN, all call used registers are stored with 2062*e4b17023SJohn Marino unknown values. */ 2063*e4b17023SJohn Marino if (CALL_P (insn)) 2064*e4b17023SJohn Marino { 2065*e4b17023SJohn Marino for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) 2066*e4b17023SJohn Marino { 2067*e4b17023SJohn Marino if (call_used_regs[i]) 2068*e4b17023SJohn Marino /* Reset the information about this register. */ 2069*e4b17023SJohn Marino reg_set_luid[i] = 0; 2070*e4b17023SJohn Marino } 2071*e4b17023SJohn Marino } 2072*e4b17023SJohn Marino } 2073*e4b17023SJohn Marino return changed; 2074*e4b17023SJohn Marino } 2075*e4b17023SJohn Marino 2076*e4b17023SJohn Marino /* SET is a SET or CLOBBER that sets DST. DATA is the insn which 2077*e4b17023SJohn Marino contains SET. 2078*e4b17023SJohn Marino Update reg_set_luid, reg_offset and reg_base_reg accordingly. 2079*e4b17023SJohn Marino Called from reload_cse_move2add via note_stores. */ 2080*e4b17023SJohn Marino 2081*e4b17023SJohn Marino static void 2082*e4b17023SJohn Marino move2add_note_store (rtx dst, const_rtx set, void *data) 2083*e4b17023SJohn Marino { 2084*e4b17023SJohn Marino rtx insn = (rtx) data; 2085*e4b17023SJohn Marino unsigned int regno = 0; 2086*e4b17023SJohn Marino unsigned int nregs = 0; 2087*e4b17023SJohn Marino unsigned int i; 2088*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (dst); 2089*e4b17023SJohn Marino 2090*e4b17023SJohn Marino if (GET_CODE (dst) == SUBREG) 2091*e4b17023SJohn Marino { 2092*e4b17023SJohn Marino regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)), 2093*e4b17023SJohn Marino GET_MODE (SUBREG_REG (dst)), 2094*e4b17023SJohn Marino SUBREG_BYTE (dst), 2095*e4b17023SJohn Marino GET_MODE (dst)); 2096*e4b17023SJohn Marino nregs = subreg_nregs (dst); 2097*e4b17023SJohn Marino dst = SUBREG_REG (dst); 2098*e4b17023SJohn Marino } 2099*e4b17023SJohn Marino 2100*e4b17023SJohn Marino /* Some targets do argument pushes without adding REG_INC notes. */ 2101*e4b17023SJohn Marino 2102*e4b17023SJohn Marino if (MEM_P (dst)) 2103*e4b17023SJohn Marino { 2104*e4b17023SJohn Marino dst = XEXP (dst, 0); 2105*e4b17023SJohn Marino if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC 2106*e4b17023SJohn Marino || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC) 2107*e4b17023SJohn Marino reg_set_luid[REGNO (XEXP (dst, 0))] = 0; 2108*e4b17023SJohn Marino return; 2109*e4b17023SJohn Marino } 2110*e4b17023SJohn Marino if (!REG_P (dst)) 2111*e4b17023SJohn Marino return; 2112*e4b17023SJohn Marino 2113*e4b17023SJohn Marino regno += REGNO (dst); 2114*e4b17023SJohn Marino if (!nregs) 2115*e4b17023SJohn Marino nregs = hard_regno_nregs[regno][mode]; 2116*e4b17023SJohn Marino 2117*e4b17023SJohn Marino if (SCALAR_INT_MODE_P (GET_MODE (dst)) 2118*e4b17023SJohn Marino && nregs == 1 && GET_CODE (set) == SET) 2119*e4b17023SJohn Marino { 2120*e4b17023SJohn Marino rtx note, sym = NULL_RTX; 2121*e4b17023SJohn Marino HOST_WIDE_INT off; 2122*e4b17023SJohn Marino 2123*e4b17023SJohn Marino note = find_reg_equal_equiv_note (insn); 2124*e4b17023SJohn Marino if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF) 2125*e4b17023SJohn Marino { 2126*e4b17023SJohn Marino sym = XEXP (note, 0); 2127*e4b17023SJohn Marino off = 0; 2128*e4b17023SJohn Marino } 2129*e4b17023SJohn Marino else if (note && GET_CODE (XEXP (note, 0)) == CONST 2130*e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS 2131*e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF 2132*e4b17023SJohn Marino && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1))) 2133*e4b17023SJohn Marino { 2134*e4b17023SJohn Marino sym = XEXP (XEXP (XEXP (note, 0), 0), 0); 2135*e4b17023SJohn Marino off = INTVAL (XEXP (XEXP (XEXP (note, 0), 0), 1)); 2136*e4b17023SJohn Marino } 2137*e4b17023SJohn Marino 2138*e4b17023SJohn Marino if (sym != NULL_RTX) 2139*e4b17023SJohn Marino { 2140*e4b17023SJohn Marino reg_base_reg[regno] = -1; 2141*e4b17023SJohn Marino reg_symbol_ref[regno] = sym; 2142*e4b17023SJohn Marino reg_offset[regno] = off; 2143*e4b17023SJohn Marino reg_mode[regno] = mode; 2144*e4b17023SJohn Marino reg_set_luid[regno] = move2add_luid; 2145*e4b17023SJohn Marino return; 2146*e4b17023SJohn Marino } 2147*e4b17023SJohn Marino } 2148*e4b17023SJohn Marino 2149*e4b17023SJohn Marino if (SCALAR_INT_MODE_P (GET_MODE (dst)) 2150*e4b17023SJohn Marino && nregs == 1 && GET_CODE (set) == SET 2151*e4b17023SJohn Marino && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT 2152*e4b17023SJohn Marino && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART) 2153*e4b17023SJohn Marino { 2154*e4b17023SJohn Marino rtx src = SET_SRC (set); 2155*e4b17023SJohn Marino rtx base_reg; 2156*e4b17023SJohn Marino HOST_WIDE_INT offset; 2157*e4b17023SJohn Marino int base_regno; 2158*e4b17023SJohn Marino /* This may be different from mode, if SET_DEST (set) is a 2159*e4b17023SJohn Marino SUBREG. */ 2160*e4b17023SJohn Marino enum machine_mode dst_mode = GET_MODE (dst); 2161*e4b17023SJohn Marino 2162*e4b17023SJohn Marino switch (GET_CODE (src)) 2163*e4b17023SJohn Marino { 2164*e4b17023SJohn Marino case PLUS: 2165*e4b17023SJohn Marino if (REG_P (XEXP (src, 0))) 2166*e4b17023SJohn Marino { 2167*e4b17023SJohn Marino base_reg = XEXP (src, 0); 2168*e4b17023SJohn Marino 2169*e4b17023SJohn Marino if (CONST_INT_P (XEXP (src, 1))) 2170*e4b17023SJohn Marino offset = INTVAL (XEXP (src, 1)); 2171*e4b17023SJohn Marino else if (REG_P (XEXP (src, 1)) 2172*e4b17023SJohn Marino && (reg_set_luid[REGNO (XEXP (src, 1))] 2173*e4b17023SJohn Marino > move2add_last_label_luid) 2174*e4b17023SJohn Marino && (MODES_OK_FOR_MOVE2ADD 2175*e4b17023SJohn Marino (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))) 2176*e4b17023SJohn Marino { 2177*e4b17023SJohn Marino if (reg_base_reg[REGNO (XEXP (src, 1))] < 0 2178*e4b17023SJohn Marino && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX) 2179*e4b17023SJohn Marino offset = reg_offset[REGNO (XEXP (src, 1))]; 2180*e4b17023SJohn Marino /* Maybe the first register is known to be a 2181*e4b17023SJohn Marino constant. */ 2182*e4b17023SJohn Marino else if (reg_set_luid[REGNO (base_reg)] 2183*e4b17023SJohn Marino > move2add_last_label_luid 2184*e4b17023SJohn Marino && (MODES_OK_FOR_MOVE2ADD 2185*e4b17023SJohn Marino (dst_mode, reg_mode[REGNO (base_reg)])) 2186*e4b17023SJohn Marino && reg_base_reg[REGNO (base_reg)] < 0 2187*e4b17023SJohn Marino && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX) 2188*e4b17023SJohn Marino { 2189*e4b17023SJohn Marino offset = reg_offset[REGNO (base_reg)]; 2190*e4b17023SJohn Marino base_reg = XEXP (src, 1); 2191*e4b17023SJohn Marino } 2192*e4b17023SJohn Marino else 2193*e4b17023SJohn Marino goto invalidate; 2194*e4b17023SJohn Marino } 2195*e4b17023SJohn Marino else 2196*e4b17023SJohn Marino goto invalidate; 2197*e4b17023SJohn Marino 2198*e4b17023SJohn Marino break; 2199*e4b17023SJohn Marino } 2200*e4b17023SJohn Marino 2201*e4b17023SJohn Marino goto invalidate; 2202*e4b17023SJohn Marino 2203*e4b17023SJohn Marino case REG: 2204*e4b17023SJohn Marino base_reg = src; 2205*e4b17023SJohn Marino offset = 0; 2206*e4b17023SJohn Marino break; 2207*e4b17023SJohn Marino 2208*e4b17023SJohn Marino case CONST_INT: 2209*e4b17023SJohn Marino /* Start tracking the register as a constant. */ 2210*e4b17023SJohn Marino reg_base_reg[regno] = -1; 2211*e4b17023SJohn Marino reg_symbol_ref[regno] = NULL_RTX; 2212*e4b17023SJohn Marino reg_offset[regno] = INTVAL (SET_SRC (set)); 2213*e4b17023SJohn Marino /* We assign the same luid to all registers set to constants. */ 2214*e4b17023SJohn Marino reg_set_luid[regno] = move2add_last_label_luid + 1; 2215*e4b17023SJohn Marino reg_mode[regno] = mode; 2216*e4b17023SJohn Marino return; 2217*e4b17023SJohn Marino 2218*e4b17023SJohn Marino default: 2219*e4b17023SJohn Marino invalidate: 2220*e4b17023SJohn Marino /* Invalidate the contents of the register. */ 2221*e4b17023SJohn Marino reg_set_luid[regno] = 0; 2222*e4b17023SJohn Marino return; 2223*e4b17023SJohn Marino } 2224*e4b17023SJohn Marino 2225*e4b17023SJohn Marino base_regno = REGNO (base_reg); 2226*e4b17023SJohn Marino /* If information about the base register is not valid, set it 2227*e4b17023SJohn Marino up as a new base register, pretending its value is known 2228*e4b17023SJohn Marino starting from the current insn. */ 2229*e4b17023SJohn Marino if (reg_set_luid[base_regno] <= move2add_last_label_luid) 2230*e4b17023SJohn Marino { 2231*e4b17023SJohn Marino reg_base_reg[base_regno] = base_regno; 2232*e4b17023SJohn Marino reg_symbol_ref[base_regno] = NULL_RTX; 2233*e4b17023SJohn Marino reg_offset[base_regno] = 0; 2234*e4b17023SJohn Marino reg_set_luid[base_regno] = move2add_luid; 2235*e4b17023SJohn Marino reg_mode[base_regno] = mode; 2236*e4b17023SJohn Marino } 2237*e4b17023SJohn Marino else if (! MODES_OK_FOR_MOVE2ADD (dst_mode, 2238*e4b17023SJohn Marino reg_mode[base_regno])) 2239*e4b17023SJohn Marino goto invalidate; 2240*e4b17023SJohn Marino 2241*e4b17023SJohn Marino reg_mode[regno] = mode; 2242*e4b17023SJohn Marino 2243*e4b17023SJohn Marino /* Copy base information from our base register. */ 2244*e4b17023SJohn Marino reg_set_luid[regno] = reg_set_luid[base_regno]; 2245*e4b17023SJohn Marino reg_base_reg[regno] = reg_base_reg[base_regno]; 2246*e4b17023SJohn Marino reg_symbol_ref[regno] = reg_symbol_ref[base_regno]; 2247*e4b17023SJohn Marino 2248*e4b17023SJohn Marino /* Compute the sum of the offsets or constants. */ 2249*e4b17023SJohn Marino reg_offset[regno] = trunc_int_for_mode (offset 2250*e4b17023SJohn Marino + reg_offset[base_regno], 2251*e4b17023SJohn Marino dst_mode); 2252*e4b17023SJohn Marino } 2253*e4b17023SJohn Marino else 2254*e4b17023SJohn Marino { 2255*e4b17023SJohn Marino unsigned int endregno = regno + nregs; 2256*e4b17023SJohn Marino 2257*e4b17023SJohn Marino for (i = regno; i < endregno; i++) 2258*e4b17023SJohn Marino /* Reset the information about this register. */ 2259*e4b17023SJohn Marino reg_set_luid[i] = 0; 2260*e4b17023SJohn Marino } 2261*e4b17023SJohn Marino } 2262*e4b17023SJohn Marino 2263*e4b17023SJohn Marino static bool 2264*e4b17023SJohn Marino gate_handle_postreload (void) 2265*e4b17023SJohn Marino { 2266*e4b17023SJohn Marino return (optimize > 0 && reload_completed); 2267*e4b17023SJohn Marino } 2268*e4b17023SJohn Marino 2269*e4b17023SJohn Marino 2270*e4b17023SJohn Marino static unsigned int 2271*e4b17023SJohn Marino rest_of_handle_postreload (void) 2272*e4b17023SJohn Marino { 2273*e4b17023SJohn Marino if (!dbg_cnt (postreload_cse)) 2274*e4b17023SJohn Marino return 0; 2275*e4b17023SJohn Marino 2276*e4b17023SJohn Marino /* Do a very simple CSE pass over just the hard registers. */ 2277*e4b17023SJohn Marino reload_cse_regs (get_insns ()); 2278*e4b17023SJohn Marino /* Reload_cse_regs can eliminate potentially-trapping MEMs. 2279*e4b17023SJohn Marino Remove any EH edges associated with them. */ 2280*e4b17023SJohn Marino if (cfun->can_throw_non_call_exceptions) 2281*e4b17023SJohn Marino purge_all_dead_edges (); 2282*e4b17023SJohn Marino 2283*e4b17023SJohn Marino return 0; 2284*e4b17023SJohn Marino } 2285*e4b17023SJohn Marino 2286*e4b17023SJohn Marino struct rtl_opt_pass pass_postreload_cse = 2287*e4b17023SJohn Marino { 2288*e4b17023SJohn Marino { 2289*e4b17023SJohn Marino RTL_PASS, 2290*e4b17023SJohn Marino "postreload", /* name */ 2291*e4b17023SJohn Marino gate_handle_postreload, /* gate */ 2292*e4b17023SJohn Marino rest_of_handle_postreload, /* execute */ 2293*e4b17023SJohn Marino NULL, /* sub */ 2294*e4b17023SJohn Marino NULL, /* next */ 2295*e4b17023SJohn Marino 0, /* static_pass_number */ 2296*e4b17023SJohn Marino TV_RELOAD_CSE_REGS, /* tv_id */ 2297*e4b17023SJohn Marino 0, /* properties_required */ 2298*e4b17023SJohn Marino 0, /* properties_provided */ 2299*e4b17023SJohn Marino 0, /* properties_destroyed */ 2300*e4b17023SJohn Marino 0, /* todo_flags_start */ 2301*e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing | 2302*e4b17023SJohn Marino 0 /* todo_flags_finish */ 2303*e4b17023SJohn Marino } 2304*e4b17023SJohn Marino }; 2305