1*e4b17023SJohn Marino /* RTL-based forward propagation pass for GNU compiler. 2*e4b17023SJohn Marino Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 3*e4b17023SJohn Marino Free Software Foundation, Inc. 4*e4b17023SJohn Marino Contributed by Paolo Bonzini and Steven Bosscher. 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 #include "diagnostic-core.h" 27*e4b17023SJohn Marino 28*e4b17023SJohn Marino #include "sparseset.h" 29*e4b17023SJohn Marino #include "timevar.h" 30*e4b17023SJohn Marino #include "rtl.h" 31*e4b17023SJohn Marino #include "tm_p.h" 32*e4b17023SJohn Marino #include "insn-config.h" 33*e4b17023SJohn Marino #include "recog.h" 34*e4b17023SJohn Marino #include "flags.h" 35*e4b17023SJohn Marino #include "obstack.h" 36*e4b17023SJohn Marino #include "basic-block.h" 37*e4b17023SJohn Marino #include "output.h" 38*e4b17023SJohn Marino #include "df.h" 39*e4b17023SJohn Marino #include "target.h" 40*e4b17023SJohn Marino #include "cfgloop.h" 41*e4b17023SJohn Marino #include "tree-pass.h" 42*e4b17023SJohn Marino #include "domwalk.h" 43*e4b17023SJohn Marino #include "emit-rtl.h" 44*e4b17023SJohn Marino 45*e4b17023SJohn Marino 46*e4b17023SJohn Marino /* This pass does simple forward propagation and simplification when an 47*e4b17023SJohn Marino operand of an insn can only come from a single def. This pass uses 48*e4b17023SJohn Marino df.c, so it is global. However, we only do limited analysis of 49*e4b17023SJohn Marino available expressions. 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino 1) The pass tries to propagate the source of the def into the use, 52*e4b17023SJohn Marino and checks if the result is independent of the substituted value. 53*e4b17023SJohn Marino For example, the high word of a (zero_extend:DI (reg:SI M)) is always 54*e4b17023SJohn Marino zero, independent of the source register. 55*e4b17023SJohn Marino 56*e4b17023SJohn Marino In particular, we propagate constants into the use site. Sometimes 57*e4b17023SJohn Marino RTL expansion did not put the constant in the same insn on purpose, 58*e4b17023SJohn Marino to satisfy a predicate, and the result will fail to be recognized; 59*e4b17023SJohn Marino but this happens rarely and in this case we can still create a 60*e4b17023SJohn Marino REG_EQUAL note. For multi-word operations, this 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino (set (subreg:SI (reg:DI 120) 0) (const_int 0)) 63*e4b17023SJohn Marino (set (subreg:SI (reg:DI 120) 4) (const_int -1)) 64*e4b17023SJohn Marino (set (subreg:SI (reg:DI 122) 0) 65*e4b17023SJohn Marino (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0))) 66*e4b17023SJohn Marino (set (subreg:SI (reg:DI 122) 4) 67*e4b17023SJohn Marino (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4))) 68*e4b17023SJohn Marino 69*e4b17023SJohn Marino can be simplified to the much simpler 70*e4b17023SJohn Marino 71*e4b17023SJohn Marino (set (subreg:SI (reg:DI 122) 0) (subreg:SI (reg:DI 119))) 72*e4b17023SJohn Marino (set (subreg:SI (reg:DI 122) 4) (const_int -1)) 73*e4b17023SJohn Marino 74*e4b17023SJohn Marino This particular propagation is also effective at putting together 75*e4b17023SJohn Marino complex addressing modes. We are more aggressive inside MEMs, in 76*e4b17023SJohn Marino that all definitions are propagated if the use is in a MEM; if the 77*e4b17023SJohn Marino result is a valid memory address we check address_cost to decide 78*e4b17023SJohn Marino whether the substitution is worthwhile. 79*e4b17023SJohn Marino 80*e4b17023SJohn Marino 2) The pass propagates register copies. This is not as effective as 81*e4b17023SJohn Marino the copy propagation done by CSE's canon_reg, which works by walking 82*e4b17023SJohn Marino the instruction chain, it can help the other transformations. 83*e4b17023SJohn Marino 84*e4b17023SJohn Marino We should consider removing this optimization, and instead reorder the 85*e4b17023SJohn Marino RTL passes, because GCSE does this transformation too. With some luck, 86*e4b17023SJohn Marino the CSE pass at the end of rest_of_handle_gcse could also go away. 87*e4b17023SJohn Marino 88*e4b17023SJohn Marino 3) The pass looks for paradoxical subregs that are actually unnecessary. 89*e4b17023SJohn Marino Things like this: 90*e4b17023SJohn Marino 91*e4b17023SJohn Marino (set (reg:QI 120) (subreg:QI (reg:SI 118) 0)) 92*e4b17023SJohn Marino (set (reg:QI 121) (subreg:QI (reg:SI 119) 0)) 93*e4b17023SJohn Marino (set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0) 94*e4b17023SJohn Marino (subreg:SI (reg:QI 121) 0))) 95*e4b17023SJohn Marino 96*e4b17023SJohn Marino are very common on machines that can only do word-sized operations. 97*e4b17023SJohn Marino For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0), 98*e4b17023SJohn Marino if it has a single def and it is (subreg:NARROW (reg:WIDE M) 0), 99*e4b17023SJohn Marino we can replace the paradoxical subreg with simply (reg:WIDE M). The 100*e4b17023SJohn Marino above will simplify this to 101*e4b17023SJohn Marino 102*e4b17023SJohn Marino (set (reg:QI 120) (subreg:QI (reg:SI 118) 0)) 103*e4b17023SJohn Marino (set (reg:QI 121) (subreg:QI (reg:SI 119) 0)) 104*e4b17023SJohn Marino (set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119))) 105*e4b17023SJohn Marino 106*e4b17023SJohn Marino where the first two insns are now dead. 107*e4b17023SJohn Marino 108*e4b17023SJohn Marino We used to use reaching definitions to find which uses have a 109*e4b17023SJohn Marino single reaching definition (sounds obvious...), but this is too 110*e4b17023SJohn Marino complex a problem in nasty testcases like PR33928. Now we use the 111*e4b17023SJohn Marino multiple definitions problem in df-problems.c. The similarity 112*e4b17023SJohn Marino between that problem and SSA form creation is taken further, in 113*e4b17023SJohn Marino that fwprop does a dominator walk to create its chains; however, 114*e4b17023SJohn Marino instead of creating a PHI function where multiple definitions meet 115*e4b17023SJohn Marino I just punt and record only singleton use-def chains, which is 116*e4b17023SJohn Marino all that is needed by fwprop. */ 117*e4b17023SJohn Marino 118*e4b17023SJohn Marino 119*e4b17023SJohn Marino static int num_changes; 120*e4b17023SJohn Marino 121*e4b17023SJohn Marino DEF_VEC_P(df_ref); 122*e4b17023SJohn Marino DEF_VEC_ALLOC_P(df_ref,heap); 123*e4b17023SJohn Marino static VEC(df_ref,heap) *use_def_ref; 124*e4b17023SJohn Marino static VEC(df_ref,heap) *reg_defs; 125*e4b17023SJohn Marino static VEC(df_ref,heap) *reg_defs_stack; 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino /* The MD bitmaps are trimmed to include only live registers to cut 128*e4b17023SJohn Marino memory usage on testcases like insn-recog.c. Track live registers 129*e4b17023SJohn Marino in the basic block and do not perform forward propagation if the 130*e4b17023SJohn Marino destination is a dead pseudo occurring in a note. */ 131*e4b17023SJohn Marino static bitmap local_md; 132*e4b17023SJohn Marino static bitmap local_lr; 133*e4b17023SJohn Marino 134*e4b17023SJohn Marino /* Return the only def in USE's use-def chain, or NULL if there is 135*e4b17023SJohn Marino more than one def in the chain. */ 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino static inline df_ref 138*e4b17023SJohn Marino get_def_for_use (df_ref use) 139*e4b17023SJohn Marino { 140*e4b17023SJohn Marino return VEC_index (df_ref, use_def_ref, DF_REF_ID (use)); 141*e4b17023SJohn Marino } 142*e4b17023SJohn Marino 143*e4b17023SJohn Marino 144*e4b17023SJohn Marino /* Update the reg_defs vector with non-partial definitions in DEF_REC. 145*e4b17023SJohn Marino TOP_FLAG says which artificials uses should be used, when DEF_REC 146*e4b17023SJohn Marino is an artificial def vector. LOCAL_MD is modified as after a 147*e4b17023SJohn Marino df_md_simulate_* function; we do more or less the same processing 148*e4b17023SJohn Marino done there, so we do not use those functions. */ 149*e4b17023SJohn Marino 150*e4b17023SJohn Marino #define DF_MD_GEN_FLAGS \ 151*e4b17023SJohn Marino (DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER) 152*e4b17023SJohn Marino 153*e4b17023SJohn Marino static void 154*e4b17023SJohn Marino process_defs (df_ref *def_rec, int top_flag) 155*e4b17023SJohn Marino { 156*e4b17023SJohn Marino df_ref def; 157*e4b17023SJohn Marino while ((def = *def_rec++) != NULL) 158*e4b17023SJohn Marino { 159*e4b17023SJohn Marino df_ref curr_def = VEC_index (df_ref, reg_defs, DF_REF_REGNO (def)); 160*e4b17023SJohn Marino unsigned int dregno; 161*e4b17023SJohn Marino 162*e4b17023SJohn Marino if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) != top_flag) 163*e4b17023SJohn Marino continue; 164*e4b17023SJohn Marino 165*e4b17023SJohn Marino dregno = DF_REF_REGNO (def); 166*e4b17023SJohn Marino if (curr_def) 167*e4b17023SJohn Marino VEC_safe_push (df_ref, heap, reg_defs_stack, curr_def); 168*e4b17023SJohn Marino else 169*e4b17023SJohn Marino { 170*e4b17023SJohn Marino /* Do not store anything if "transitioning" from NULL to NULL. But 171*e4b17023SJohn Marino otherwise, push a special entry on the stack to tell the 172*e4b17023SJohn Marino leave_block callback that the entry in reg_defs was NULL. */ 173*e4b17023SJohn Marino if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS) 174*e4b17023SJohn Marino ; 175*e4b17023SJohn Marino else 176*e4b17023SJohn Marino VEC_safe_push (df_ref, heap, reg_defs_stack, def); 177*e4b17023SJohn Marino } 178*e4b17023SJohn Marino 179*e4b17023SJohn Marino if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS) 180*e4b17023SJohn Marino { 181*e4b17023SJohn Marino bitmap_set_bit (local_md, dregno); 182*e4b17023SJohn Marino VEC_replace (df_ref, reg_defs, dregno, NULL); 183*e4b17023SJohn Marino } 184*e4b17023SJohn Marino else 185*e4b17023SJohn Marino { 186*e4b17023SJohn Marino bitmap_clear_bit (local_md, dregno); 187*e4b17023SJohn Marino VEC_replace (df_ref, reg_defs, dregno, def); 188*e4b17023SJohn Marino } 189*e4b17023SJohn Marino } 190*e4b17023SJohn Marino } 191*e4b17023SJohn Marino 192*e4b17023SJohn Marino 193*e4b17023SJohn Marino /* Fill the use_def_ref vector with values for the uses in USE_REC, 194*e4b17023SJohn Marino taking reaching definitions info from LOCAL_MD and REG_DEFS. 195*e4b17023SJohn Marino TOP_FLAG says which artificials uses should be used, when USE_REC 196*e4b17023SJohn Marino is an artificial use vector. */ 197*e4b17023SJohn Marino 198*e4b17023SJohn Marino static void 199*e4b17023SJohn Marino process_uses (df_ref *use_rec, int top_flag) 200*e4b17023SJohn Marino { 201*e4b17023SJohn Marino df_ref use; 202*e4b17023SJohn Marino while ((use = *use_rec++) != NULL) 203*e4b17023SJohn Marino if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == top_flag) 204*e4b17023SJohn Marino { 205*e4b17023SJohn Marino unsigned int uregno = DF_REF_REGNO (use); 206*e4b17023SJohn Marino if (VEC_index (df_ref, reg_defs, uregno) 207*e4b17023SJohn Marino && !bitmap_bit_p (local_md, uregno) 208*e4b17023SJohn Marino && bitmap_bit_p (local_lr, uregno)) 209*e4b17023SJohn Marino VEC_replace (df_ref, use_def_ref, DF_REF_ID (use), 210*e4b17023SJohn Marino VEC_index (df_ref, reg_defs, uregno)); 211*e4b17023SJohn Marino } 212*e4b17023SJohn Marino } 213*e4b17023SJohn Marino 214*e4b17023SJohn Marino 215*e4b17023SJohn Marino static void 216*e4b17023SJohn Marino single_def_use_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, 217*e4b17023SJohn Marino basic_block bb) 218*e4b17023SJohn Marino { 219*e4b17023SJohn Marino int bb_index = bb->index; 220*e4b17023SJohn Marino struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index); 221*e4b17023SJohn Marino struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index); 222*e4b17023SJohn Marino rtx insn; 223*e4b17023SJohn Marino 224*e4b17023SJohn Marino bitmap_copy (local_md, &md_bb_info->in); 225*e4b17023SJohn Marino bitmap_copy (local_lr, &lr_bb_info->in); 226*e4b17023SJohn Marino 227*e4b17023SJohn Marino /* Push a marker for the leave_block callback. */ 228*e4b17023SJohn Marino VEC_safe_push (df_ref, heap, reg_defs_stack, NULL); 229*e4b17023SJohn Marino 230*e4b17023SJohn Marino process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP); 231*e4b17023SJohn Marino process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP); 232*e4b17023SJohn Marino 233*e4b17023SJohn Marino /* We don't call df_simulate_initialize_forwards, as it may overestimate 234*e4b17023SJohn Marino the live registers if there are unused artificial defs. We prefer 235*e4b17023SJohn Marino liveness to be underestimated. */ 236*e4b17023SJohn Marino 237*e4b17023SJohn Marino FOR_BB_INSNS (bb, insn) 238*e4b17023SJohn Marino if (INSN_P (insn)) 239*e4b17023SJohn Marino { 240*e4b17023SJohn Marino unsigned int uid = INSN_UID (insn); 241*e4b17023SJohn Marino process_uses (DF_INSN_UID_USES (uid), 0); 242*e4b17023SJohn Marino process_uses (DF_INSN_UID_EQ_USES (uid), 0); 243*e4b17023SJohn Marino process_defs (DF_INSN_UID_DEFS (uid), 0); 244*e4b17023SJohn Marino df_simulate_one_insn_forwards (bb, insn, local_lr); 245*e4b17023SJohn Marino } 246*e4b17023SJohn Marino 247*e4b17023SJohn Marino process_uses (df_get_artificial_uses (bb_index), 0); 248*e4b17023SJohn Marino process_defs (df_get_artificial_defs (bb_index), 0); 249*e4b17023SJohn Marino } 250*e4b17023SJohn Marino 251*e4b17023SJohn Marino /* Pop the definitions created in this basic block when leaving its 252*e4b17023SJohn Marino dominated parts. */ 253*e4b17023SJohn Marino 254*e4b17023SJohn Marino static void 255*e4b17023SJohn Marino single_def_use_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, 256*e4b17023SJohn Marino basic_block bb ATTRIBUTE_UNUSED) 257*e4b17023SJohn Marino { 258*e4b17023SJohn Marino df_ref saved_def; 259*e4b17023SJohn Marino while ((saved_def = VEC_pop (df_ref, reg_defs_stack)) != NULL) 260*e4b17023SJohn Marino { 261*e4b17023SJohn Marino unsigned int dregno = DF_REF_REGNO (saved_def); 262*e4b17023SJohn Marino 263*e4b17023SJohn Marino /* See also process_defs. */ 264*e4b17023SJohn Marino if (saved_def == VEC_index (df_ref, reg_defs, dregno)) 265*e4b17023SJohn Marino VEC_replace (df_ref, reg_defs, dregno, NULL); 266*e4b17023SJohn Marino else 267*e4b17023SJohn Marino VEC_replace (df_ref, reg_defs, dregno, saved_def); 268*e4b17023SJohn Marino } 269*e4b17023SJohn Marino } 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino 272*e4b17023SJohn Marino /* Build a vector holding the reaching definitions of uses reached by a 273*e4b17023SJohn Marino single dominating definition. */ 274*e4b17023SJohn Marino 275*e4b17023SJohn Marino static void 276*e4b17023SJohn Marino build_single_def_use_links (void) 277*e4b17023SJohn Marino { 278*e4b17023SJohn Marino struct dom_walk_data walk_data; 279*e4b17023SJohn Marino 280*e4b17023SJohn Marino /* We use the multiple definitions problem to compute our restricted 281*e4b17023SJohn Marino use-def chains. */ 282*e4b17023SJohn Marino df_set_flags (DF_EQ_NOTES); 283*e4b17023SJohn Marino df_md_add_problem (); 284*e4b17023SJohn Marino df_note_add_problem (); 285*e4b17023SJohn Marino df_analyze (); 286*e4b17023SJohn Marino df_maybe_reorganize_use_refs (DF_REF_ORDER_BY_INSN_WITH_NOTES); 287*e4b17023SJohn Marino 288*e4b17023SJohn Marino use_def_ref = VEC_alloc (df_ref, heap, DF_USES_TABLE_SIZE ()); 289*e4b17023SJohn Marino VEC_safe_grow_cleared (df_ref, heap, use_def_ref, DF_USES_TABLE_SIZE ()); 290*e4b17023SJohn Marino 291*e4b17023SJohn Marino reg_defs = VEC_alloc (df_ref, heap, max_reg_num ()); 292*e4b17023SJohn Marino VEC_safe_grow_cleared (df_ref, heap, reg_defs, max_reg_num ()); 293*e4b17023SJohn Marino 294*e4b17023SJohn Marino reg_defs_stack = VEC_alloc (df_ref, heap, n_basic_blocks * 10); 295*e4b17023SJohn Marino local_md = BITMAP_ALLOC (NULL); 296*e4b17023SJohn Marino local_lr = BITMAP_ALLOC (NULL); 297*e4b17023SJohn Marino 298*e4b17023SJohn Marino /* Walk the dominator tree looking for single reaching definitions 299*e4b17023SJohn Marino dominating the uses. This is similar to how SSA form is built. */ 300*e4b17023SJohn Marino walk_data.dom_direction = CDI_DOMINATORS; 301*e4b17023SJohn Marino walk_data.initialize_block_local_data = NULL; 302*e4b17023SJohn Marino walk_data.before_dom_children = single_def_use_enter_block; 303*e4b17023SJohn Marino walk_data.after_dom_children = single_def_use_leave_block; 304*e4b17023SJohn Marino 305*e4b17023SJohn Marino init_walk_dominator_tree (&walk_data); 306*e4b17023SJohn Marino walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR); 307*e4b17023SJohn Marino fini_walk_dominator_tree (&walk_data); 308*e4b17023SJohn Marino 309*e4b17023SJohn Marino BITMAP_FREE (local_lr); 310*e4b17023SJohn Marino BITMAP_FREE (local_md); 311*e4b17023SJohn Marino VEC_free (df_ref, heap, reg_defs); 312*e4b17023SJohn Marino VEC_free (df_ref, heap, reg_defs_stack); 313*e4b17023SJohn Marino } 314*e4b17023SJohn Marino 315*e4b17023SJohn Marino 316*e4b17023SJohn Marino /* Do not try to replace constant addresses or addresses of local and 317*e4b17023SJohn Marino argument slots. These MEM expressions are made only once and inserted 318*e4b17023SJohn Marino in many instructions, as well as being used to control symbol table 319*e4b17023SJohn Marino output. It is not safe to clobber them. 320*e4b17023SJohn Marino 321*e4b17023SJohn Marino There are some uncommon cases where the address is already in a register 322*e4b17023SJohn Marino for some reason, but we cannot take advantage of that because we have 323*e4b17023SJohn Marino no easy way to unshare the MEM. In addition, looking up all stack 324*e4b17023SJohn Marino addresses is costly. */ 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino static bool 327*e4b17023SJohn Marino can_simplify_addr (rtx addr) 328*e4b17023SJohn Marino { 329*e4b17023SJohn Marino rtx reg; 330*e4b17023SJohn Marino 331*e4b17023SJohn Marino if (CONSTANT_ADDRESS_P (addr)) 332*e4b17023SJohn Marino return false; 333*e4b17023SJohn Marino 334*e4b17023SJohn Marino if (GET_CODE (addr) == PLUS) 335*e4b17023SJohn Marino reg = XEXP (addr, 0); 336*e4b17023SJohn Marino else 337*e4b17023SJohn Marino reg = addr; 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino return (!REG_P (reg) 340*e4b17023SJohn Marino || (REGNO (reg) != FRAME_POINTER_REGNUM 341*e4b17023SJohn Marino && REGNO (reg) != HARD_FRAME_POINTER_REGNUM 342*e4b17023SJohn Marino && REGNO (reg) != ARG_POINTER_REGNUM)); 343*e4b17023SJohn Marino } 344*e4b17023SJohn Marino 345*e4b17023SJohn Marino /* Returns a canonical version of X for the address, from the point of view, 346*e4b17023SJohn Marino that all multiplications are represented as MULT instead of the multiply 347*e4b17023SJohn Marino by a power of 2 being represented as ASHIFT. 348*e4b17023SJohn Marino 349*e4b17023SJohn Marino Every ASHIFT we find has been made by simplify_gen_binary and was not 350*e4b17023SJohn Marino there before, so it is not shared. So we can do this in place. */ 351*e4b17023SJohn Marino 352*e4b17023SJohn Marino static void 353*e4b17023SJohn Marino canonicalize_address (rtx x) 354*e4b17023SJohn Marino { 355*e4b17023SJohn Marino for (;;) 356*e4b17023SJohn Marino switch (GET_CODE (x)) 357*e4b17023SJohn Marino { 358*e4b17023SJohn Marino case ASHIFT: 359*e4b17023SJohn Marino if (CONST_INT_P (XEXP (x, 1)) 360*e4b17023SJohn Marino && INTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (GET_MODE (x)) 361*e4b17023SJohn Marino && INTVAL (XEXP (x, 1)) >= 0) 362*e4b17023SJohn Marino { 363*e4b17023SJohn Marino HOST_WIDE_INT shift = INTVAL (XEXP (x, 1)); 364*e4b17023SJohn Marino PUT_CODE (x, MULT); 365*e4b17023SJohn Marino XEXP (x, 1) = gen_int_mode ((HOST_WIDE_INT) 1 << shift, 366*e4b17023SJohn Marino GET_MODE (x)); 367*e4b17023SJohn Marino } 368*e4b17023SJohn Marino 369*e4b17023SJohn Marino x = XEXP (x, 0); 370*e4b17023SJohn Marino break; 371*e4b17023SJohn Marino 372*e4b17023SJohn Marino case PLUS: 373*e4b17023SJohn Marino if (GET_CODE (XEXP (x, 0)) == PLUS 374*e4b17023SJohn Marino || GET_CODE (XEXP (x, 0)) == ASHIFT 375*e4b17023SJohn Marino || GET_CODE (XEXP (x, 0)) == CONST) 376*e4b17023SJohn Marino canonicalize_address (XEXP (x, 0)); 377*e4b17023SJohn Marino 378*e4b17023SJohn Marino x = XEXP (x, 1); 379*e4b17023SJohn Marino break; 380*e4b17023SJohn Marino 381*e4b17023SJohn Marino case CONST: 382*e4b17023SJohn Marino x = XEXP (x, 0); 383*e4b17023SJohn Marino break; 384*e4b17023SJohn Marino 385*e4b17023SJohn Marino default: 386*e4b17023SJohn Marino return; 387*e4b17023SJohn Marino } 388*e4b17023SJohn Marino } 389*e4b17023SJohn Marino 390*e4b17023SJohn Marino /* OLD is a memory address. Return whether it is good to use NEW instead, 391*e4b17023SJohn Marino for a memory access in the given MODE. */ 392*e4b17023SJohn Marino 393*e4b17023SJohn Marino static bool 394*e4b17023SJohn Marino should_replace_address (rtx old_rtx, rtx new_rtx, enum machine_mode mode, 395*e4b17023SJohn Marino addr_space_t as, bool speed) 396*e4b17023SJohn Marino { 397*e4b17023SJohn Marino int gain; 398*e4b17023SJohn Marino 399*e4b17023SJohn Marino if (rtx_equal_p (old_rtx, new_rtx) 400*e4b17023SJohn Marino || !memory_address_addr_space_p (mode, new_rtx, as)) 401*e4b17023SJohn Marino return false; 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino /* Copy propagation is always ok. */ 404*e4b17023SJohn Marino if (REG_P (old_rtx) && REG_P (new_rtx)) 405*e4b17023SJohn Marino return true; 406*e4b17023SJohn Marino 407*e4b17023SJohn Marino /* Prefer the new address if it is less expensive. */ 408*e4b17023SJohn Marino gain = (address_cost (old_rtx, mode, as, speed) 409*e4b17023SJohn Marino - address_cost (new_rtx, mode, as, speed)); 410*e4b17023SJohn Marino 411*e4b17023SJohn Marino /* If the addresses have equivalent cost, prefer the new address 412*e4b17023SJohn Marino if it has the highest `set_src_cost'. That has the potential of 413*e4b17023SJohn Marino eliminating the most insns without additional costs, and it 414*e4b17023SJohn Marino is the same that cse.c used to do. */ 415*e4b17023SJohn Marino if (gain == 0) 416*e4b17023SJohn Marino gain = set_src_cost (new_rtx, speed) - set_src_cost (old_rtx, speed); 417*e4b17023SJohn Marino 418*e4b17023SJohn Marino return (gain > 0); 419*e4b17023SJohn Marino } 420*e4b17023SJohn Marino 421*e4b17023SJohn Marino 422*e4b17023SJohn Marino /* Flags for the last parameter of propagate_rtx_1. */ 423*e4b17023SJohn Marino 424*e4b17023SJohn Marino enum { 425*e4b17023SJohn Marino /* If PR_CAN_APPEAR is true, propagate_rtx_1 always returns true; 426*e4b17023SJohn Marino if it is false, propagate_rtx_1 returns false if, for at least 427*e4b17023SJohn Marino one occurrence OLD, it failed to collapse the result to a constant. 428*e4b17023SJohn Marino For example, (mult:M (reg:M A) (minus:M (reg:M B) (reg:M A))) may 429*e4b17023SJohn Marino collapse to zero if replacing (reg:M B) with (reg:M A). 430*e4b17023SJohn Marino 431*e4b17023SJohn Marino PR_CAN_APPEAR is disregarded inside MEMs: in that case, 432*e4b17023SJohn Marino propagate_rtx_1 just tries to make cheaper and valid memory 433*e4b17023SJohn Marino addresses. */ 434*e4b17023SJohn Marino PR_CAN_APPEAR = 1, 435*e4b17023SJohn Marino 436*e4b17023SJohn Marino /* If PR_HANDLE_MEM is not set, propagate_rtx_1 won't attempt any replacement 437*e4b17023SJohn Marino outside memory addresses. This is needed because propagate_rtx_1 does 438*e4b17023SJohn Marino not do any analysis on memory; thus it is very conservative and in general 439*e4b17023SJohn Marino it will fail if non-read-only MEMs are found in the source expression. 440*e4b17023SJohn Marino 441*e4b17023SJohn Marino PR_HANDLE_MEM is set when the source of the propagation was not 442*e4b17023SJohn Marino another MEM. Then, it is safe not to treat non-read-only MEMs as 443*e4b17023SJohn Marino ``opaque'' objects. */ 444*e4b17023SJohn Marino PR_HANDLE_MEM = 2, 445*e4b17023SJohn Marino 446*e4b17023SJohn Marino /* Set when costs should be optimized for speed. */ 447*e4b17023SJohn Marino PR_OPTIMIZE_FOR_SPEED = 4 448*e4b17023SJohn Marino }; 449*e4b17023SJohn Marino 450*e4b17023SJohn Marino 451*e4b17023SJohn Marino /* Replace all occurrences of OLD in *PX with NEW and try to simplify the 452*e4b17023SJohn Marino resulting expression. Replace *PX with a new RTL expression if an 453*e4b17023SJohn Marino occurrence of OLD was found. 454*e4b17023SJohn Marino 455*e4b17023SJohn Marino This is only a wrapper around simplify-rtx.c: do not add any pattern 456*e4b17023SJohn Marino matching code here. (The sole exception is the handling of LO_SUM, but 457*e4b17023SJohn Marino that is because there is no simplify_gen_* function for LO_SUM). */ 458*e4b17023SJohn Marino 459*e4b17023SJohn Marino static bool 460*e4b17023SJohn Marino propagate_rtx_1 (rtx *px, rtx old_rtx, rtx new_rtx, int flags) 461*e4b17023SJohn Marino { 462*e4b17023SJohn Marino rtx x = *px, tem = NULL_RTX, op0, op1, op2; 463*e4b17023SJohn Marino enum rtx_code code = GET_CODE (x); 464*e4b17023SJohn Marino enum machine_mode mode = GET_MODE (x); 465*e4b17023SJohn Marino enum machine_mode op_mode; 466*e4b17023SJohn Marino bool can_appear = (flags & PR_CAN_APPEAR) != 0; 467*e4b17023SJohn Marino bool valid_ops = true; 468*e4b17023SJohn Marino 469*e4b17023SJohn Marino if (!(flags & PR_HANDLE_MEM) && MEM_P (x) && !MEM_READONLY_P (x)) 470*e4b17023SJohn Marino { 471*e4b17023SJohn Marino /* If unsafe, change MEMs to CLOBBERs or SCRATCHes (to preserve whether 472*e4b17023SJohn Marino they have side effects or not). */ 473*e4b17023SJohn Marino *px = (side_effects_p (x) 474*e4b17023SJohn Marino ? gen_rtx_CLOBBER (GET_MODE (x), const0_rtx) 475*e4b17023SJohn Marino : gen_rtx_SCRATCH (GET_MODE (x))); 476*e4b17023SJohn Marino return false; 477*e4b17023SJohn Marino } 478*e4b17023SJohn Marino 479*e4b17023SJohn Marino /* If X is OLD_RTX, return NEW_RTX. But not if replacing only within an 480*e4b17023SJohn Marino address, and we are *not* inside one. */ 481*e4b17023SJohn Marino if (x == old_rtx) 482*e4b17023SJohn Marino { 483*e4b17023SJohn Marino *px = new_rtx; 484*e4b17023SJohn Marino return can_appear; 485*e4b17023SJohn Marino } 486*e4b17023SJohn Marino 487*e4b17023SJohn Marino /* If this is an expression, try recursive substitution. */ 488*e4b17023SJohn Marino switch (GET_RTX_CLASS (code)) 489*e4b17023SJohn Marino { 490*e4b17023SJohn Marino case RTX_UNARY: 491*e4b17023SJohn Marino op0 = XEXP (x, 0); 492*e4b17023SJohn Marino op_mode = GET_MODE (op0); 493*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags); 494*e4b17023SJohn Marino if (op0 == XEXP (x, 0)) 495*e4b17023SJohn Marino return true; 496*e4b17023SJohn Marino tem = simplify_gen_unary (code, mode, op0, op_mode); 497*e4b17023SJohn Marino break; 498*e4b17023SJohn Marino 499*e4b17023SJohn Marino case RTX_BIN_ARITH: 500*e4b17023SJohn Marino case RTX_COMM_ARITH: 501*e4b17023SJohn Marino op0 = XEXP (x, 0); 502*e4b17023SJohn Marino op1 = XEXP (x, 1); 503*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags); 504*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags); 505*e4b17023SJohn Marino if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 506*e4b17023SJohn Marino return true; 507*e4b17023SJohn Marino tem = simplify_gen_binary (code, mode, op0, op1); 508*e4b17023SJohn Marino break; 509*e4b17023SJohn Marino 510*e4b17023SJohn Marino case RTX_COMPARE: 511*e4b17023SJohn Marino case RTX_COMM_COMPARE: 512*e4b17023SJohn Marino op0 = XEXP (x, 0); 513*e4b17023SJohn Marino op1 = XEXP (x, 1); 514*e4b17023SJohn Marino op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); 515*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags); 516*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags); 517*e4b17023SJohn Marino if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 518*e4b17023SJohn Marino return true; 519*e4b17023SJohn Marino tem = simplify_gen_relational (code, mode, op_mode, op0, op1); 520*e4b17023SJohn Marino break; 521*e4b17023SJohn Marino 522*e4b17023SJohn Marino case RTX_TERNARY: 523*e4b17023SJohn Marino case RTX_BITFIELD_OPS: 524*e4b17023SJohn Marino op0 = XEXP (x, 0); 525*e4b17023SJohn Marino op1 = XEXP (x, 1); 526*e4b17023SJohn Marino op2 = XEXP (x, 2); 527*e4b17023SJohn Marino op_mode = GET_MODE (op0); 528*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags); 529*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags); 530*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op2, old_rtx, new_rtx, flags); 531*e4b17023SJohn Marino if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2)) 532*e4b17023SJohn Marino return true; 533*e4b17023SJohn Marino if (op_mode == VOIDmode) 534*e4b17023SJohn Marino op_mode = GET_MODE (op0); 535*e4b17023SJohn Marino tem = simplify_gen_ternary (code, mode, op_mode, op0, op1, op2); 536*e4b17023SJohn Marino break; 537*e4b17023SJohn Marino 538*e4b17023SJohn Marino case RTX_EXTRA: 539*e4b17023SJohn Marino /* The only case we try to handle is a SUBREG. */ 540*e4b17023SJohn Marino if (code == SUBREG) 541*e4b17023SJohn Marino { 542*e4b17023SJohn Marino op0 = XEXP (x, 0); 543*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags); 544*e4b17023SJohn Marino if (op0 == XEXP (x, 0)) 545*e4b17023SJohn Marino return true; 546*e4b17023SJohn Marino tem = simplify_gen_subreg (mode, op0, GET_MODE (SUBREG_REG (x)), 547*e4b17023SJohn Marino SUBREG_BYTE (x)); 548*e4b17023SJohn Marino } 549*e4b17023SJohn Marino break; 550*e4b17023SJohn Marino 551*e4b17023SJohn Marino case RTX_OBJ: 552*e4b17023SJohn Marino if (code == MEM && x != new_rtx) 553*e4b17023SJohn Marino { 554*e4b17023SJohn Marino rtx new_op0; 555*e4b17023SJohn Marino op0 = XEXP (x, 0); 556*e4b17023SJohn Marino 557*e4b17023SJohn Marino /* There are some addresses that we cannot work on. */ 558*e4b17023SJohn Marino if (!can_simplify_addr (op0)) 559*e4b17023SJohn Marino return true; 560*e4b17023SJohn Marino 561*e4b17023SJohn Marino op0 = new_op0 = targetm.delegitimize_address (op0); 562*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&new_op0, old_rtx, new_rtx, 563*e4b17023SJohn Marino flags | PR_CAN_APPEAR); 564*e4b17023SJohn Marino 565*e4b17023SJohn Marino /* Dismiss transformation that we do not want to carry on. */ 566*e4b17023SJohn Marino if (!valid_ops 567*e4b17023SJohn Marino || new_op0 == op0 568*e4b17023SJohn Marino || !(GET_MODE (new_op0) == GET_MODE (op0) 569*e4b17023SJohn Marino || GET_MODE (new_op0) == VOIDmode)) 570*e4b17023SJohn Marino return true; 571*e4b17023SJohn Marino 572*e4b17023SJohn Marino canonicalize_address (new_op0); 573*e4b17023SJohn Marino 574*e4b17023SJohn Marino /* Copy propagations are always ok. Otherwise check the costs. */ 575*e4b17023SJohn Marino if (!(REG_P (old_rtx) && REG_P (new_rtx)) 576*e4b17023SJohn Marino && !should_replace_address (op0, new_op0, GET_MODE (x), 577*e4b17023SJohn Marino MEM_ADDR_SPACE (x), 578*e4b17023SJohn Marino flags & PR_OPTIMIZE_FOR_SPEED)) 579*e4b17023SJohn Marino return true; 580*e4b17023SJohn Marino 581*e4b17023SJohn Marino tem = replace_equiv_address_nv (x, new_op0); 582*e4b17023SJohn Marino } 583*e4b17023SJohn Marino 584*e4b17023SJohn Marino else if (code == LO_SUM) 585*e4b17023SJohn Marino { 586*e4b17023SJohn Marino op0 = XEXP (x, 0); 587*e4b17023SJohn Marino op1 = XEXP (x, 1); 588*e4b17023SJohn Marino 589*e4b17023SJohn Marino /* The only simplification we do attempts to remove references to op0 590*e4b17023SJohn Marino or make it constant -- in both cases, op0's invalidity will not 591*e4b17023SJohn Marino make the result invalid. */ 592*e4b17023SJohn Marino propagate_rtx_1 (&op0, old_rtx, new_rtx, flags | PR_CAN_APPEAR); 593*e4b17023SJohn Marino valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags); 594*e4b17023SJohn Marino if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1)) 595*e4b17023SJohn Marino return true; 596*e4b17023SJohn Marino 597*e4b17023SJohn Marino /* (lo_sum (high x) x) -> x */ 598*e4b17023SJohn Marino if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1)) 599*e4b17023SJohn Marino tem = op1; 600*e4b17023SJohn Marino else 601*e4b17023SJohn Marino tem = gen_rtx_LO_SUM (mode, op0, op1); 602*e4b17023SJohn Marino 603*e4b17023SJohn Marino /* OP1 is likely not a legitimate address, otherwise there would have 604*e4b17023SJohn Marino been no LO_SUM. We want it to disappear if it is invalid, return 605*e4b17023SJohn Marino false in that case. */ 606*e4b17023SJohn Marino return memory_address_p (mode, tem); 607*e4b17023SJohn Marino } 608*e4b17023SJohn Marino 609*e4b17023SJohn Marino else if (code == REG) 610*e4b17023SJohn Marino { 611*e4b17023SJohn Marino if (rtx_equal_p (x, old_rtx)) 612*e4b17023SJohn Marino { 613*e4b17023SJohn Marino *px = new_rtx; 614*e4b17023SJohn Marino return can_appear; 615*e4b17023SJohn Marino } 616*e4b17023SJohn Marino } 617*e4b17023SJohn Marino break; 618*e4b17023SJohn Marino 619*e4b17023SJohn Marino default: 620*e4b17023SJohn Marino break; 621*e4b17023SJohn Marino } 622*e4b17023SJohn Marino 623*e4b17023SJohn Marino /* No change, no trouble. */ 624*e4b17023SJohn Marino if (tem == NULL_RTX) 625*e4b17023SJohn Marino return true; 626*e4b17023SJohn Marino 627*e4b17023SJohn Marino *px = tem; 628*e4b17023SJohn Marino 629*e4b17023SJohn Marino /* The replacement we made so far is valid, if all of the recursive 630*e4b17023SJohn Marino replacements were valid, or we could simplify everything to 631*e4b17023SJohn Marino a constant. */ 632*e4b17023SJohn Marino return valid_ops || can_appear || CONSTANT_P (tem); 633*e4b17023SJohn Marino } 634*e4b17023SJohn Marino 635*e4b17023SJohn Marino 636*e4b17023SJohn Marino /* for_each_rtx traversal function that returns 1 if BODY points to 637*e4b17023SJohn Marino a non-constant mem. */ 638*e4b17023SJohn Marino 639*e4b17023SJohn Marino static int 640*e4b17023SJohn Marino varying_mem_p (rtx *body, void *data ATTRIBUTE_UNUSED) 641*e4b17023SJohn Marino { 642*e4b17023SJohn Marino rtx x = *body; 643*e4b17023SJohn Marino return MEM_P (x) && !MEM_READONLY_P (x); 644*e4b17023SJohn Marino } 645*e4b17023SJohn Marino 646*e4b17023SJohn Marino 647*e4b17023SJohn Marino /* Replace all occurrences of OLD in X with NEW and try to simplify the 648*e4b17023SJohn Marino resulting expression (in mode MODE). Return a new expression if it is 649*e4b17023SJohn Marino a constant, otherwise X. 650*e4b17023SJohn Marino 651*e4b17023SJohn Marino Simplifications where occurrences of NEW collapse to a constant are always 652*e4b17023SJohn Marino accepted. All simplifications are accepted if NEW is a pseudo too. 653*e4b17023SJohn Marino Otherwise, we accept simplifications that have a lower or equal cost. */ 654*e4b17023SJohn Marino 655*e4b17023SJohn Marino static rtx 656*e4b17023SJohn Marino propagate_rtx (rtx x, enum machine_mode mode, rtx old_rtx, rtx new_rtx, 657*e4b17023SJohn Marino bool speed) 658*e4b17023SJohn Marino { 659*e4b17023SJohn Marino rtx tem; 660*e4b17023SJohn Marino bool collapsed; 661*e4b17023SJohn Marino int flags; 662*e4b17023SJohn Marino 663*e4b17023SJohn Marino if (REG_P (new_rtx) && REGNO (new_rtx) < FIRST_PSEUDO_REGISTER) 664*e4b17023SJohn Marino return NULL_RTX; 665*e4b17023SJohn Marino 666*e4b17023SJohn Marino flags = 0; 667*e4b17023SJohn Marino if (REG_P (new_rtx) || CONSTANT_P (new_rtx)) 668*e4b17023SJohn Marino flags |= PR_CAN_APPEAR; 669*e4b17023SJohn Marino if (!for_each_rtx (&new_rtx, varying_mem_p, NULL)) 670*e4b17023SJohn Marino flags |= PR_HANDLE_MEM; 671*e4b17023SJohn Marino 672*e4b17023SJohn Marino if (speed) 673*e4b17023SJohn Marino flags |= PR_OPTIMIZE_FOR_SPEED; 674*e4b17023SJohn Marino 675*e4b17023SJohn Marino tem = x; 676*e4b17023SJohn Marino collapsed = propagate_rtx_1 (&tem, old_rtx, copy_rtx (new_rtx), flags); 677*e4b17023SJohn Marino if (tem == x || !collapsed) 678*e4b17023SJohn Marino return NULL_RTX; 679*e4b17023SJohn Marino 680*e4b17023SJohn Marino /* gen_lowpart_common will not be able to process VOIDmode entities other 681*e4b17023SJohn Marino than CONST_INTs. */ 682*e4b17023SJohn Marino if (GET_MODE (tem) == VOIDmode && !CONST_INT_P (tem)) 683*e4b17023SJohn Marino return NULL_RTX; 684*e4b17023SJohn Marino 685*e4b17023SJohn Marino if (GET_MODE (tem) == VOIDmode) 686*e4b17023SJohn Marino tem = rtl_hooks.gen_lowpart_no_emit (mode, tem); 687*e4b17023SJohn Marino else 688*e4b17023SJohn Marino gcc_assert (GET_MODE (tem) == mode); 689*e4b17023SJohn Marino 690*e4b17023SJohn Marino return tem; 691*e4b17023SJohn Marino } 692*e4b17023SJohn Marino 693*e4b17023SJohn Marino 694*e4b17023SJohn Marino 695*e4b17023SJohn Marino 696*e4b17023SJohn Marino /* Return true if the register from reference REF is killed 697*e4b17023SJohn Marino between FROM to (but not including) TO. */ 698*e4b17023SJohn Marino 699*e4b17023SJohn Marino static bool 700*e4b17023SJohn Marino local_ref_killed_between_p (df_ref ref, rtx from, rtx to) 701*e4b17023SJohn Marino { 702*e4b17023SJohn Marino rtx insn; 703*e4b17023SJohn Marino 704*e4b17023SJohn Marino for (insn = from; insn != to; insn = NEXT_INSN (insn)) 705*e4b17023SJohn Marino { 706*e4b17023SJohn Marino df_ref *def_rec; 707*e4b17023SJohn Marino if (!INSN_P (insn)) 708*e4b17023SJohn Marino continue; 709*e4b17023SJohn Marino 710*e4b17023SJohn Marino for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) 711*e4b17023SJohn Marino { 712*e4b17023SJohn Marino df_ref def = *def_rec; 713*e4b17023SJohn Marino if (DF_REF_REGNO (ref) == DF_REF_REGNO (def)) 714*e4b17023SJohn Marino return true; 715*e4b17023SJohn Marino } 716*e4b17023SJohn Marino } 717*e4b17023SJohn Marino return false; 718*e4b17023SJohn Marino } 719*e4b17023SJohn Marino 720*e4b17023SJohn Marino 721*e4b17023SJohn Marino /* Check if the given DEF is available in INSN. This would require full 722*e4b17023SJohn Marino computation of available expressions; we check only restricted conditions: 723*e4b17023SJohn Marino - if DEF is the sole definition of its register, go ahead; 724*e4b17023SJohn Marino - in the same basic block, we check for no definitions killing the 725*e4b17023SJohn Marino definition of DEF_INSN; 726*e4b17023SJohn Marino - if USE's basic block has DEF's basic block as the sole predecessor, 727*e4b17023SJohn Marino we check if the definition is killed after DEF_INSN or before 728*e4b17023SJohn Marino TARGET_INSN insn, in their respective basic blocks. */ 729*e4b17023SJohn Marino static bool 730*e4b17023SJohn Marino use_killed_between (df_ref use, rtx def_insn, rtx target_insn) 731*e4b17023SJohn Marino { 732*e4b17023SJohn Marino basic_block def_bb = BLOCK_FOR_INSN (def_insn); 733*e4b17023SJohn Marino basic_block target_bb = BLOCK_FOR_INSN (target_insn); 734*e4b17023SJohn Marino int regno; 735*e4b17023SJohn Marino df_ref def; 736*e4b17023SJohn Marino 737*e4b17023SJohn Marino /* We used to have a def reaching a use that is _before_ the def, 738*e4b17023SJohn Marino with the def not dominating the use even though the use and def 739*e4b17023SJohn Marino are in the same basic block, when a register may be used 740*e4b17023SJohn Marino uninitialized in a loop. This should not happen anymore since 741*e4b17023SJohn Marino we do not use reaching definitions, but still we test for such 742*e4b17023SJohn Marino cases and assume that DEF is not available. */ 743*e4b17023SJohn Marino if (def_bb == target_bb 744*e4b17023SJohn Marino ? DF_INSN_LUID (def_insn) >= DF_INSN_LUID (target_insn) 745*e4b17023SJohn Marino : !dominated_by_p (CDI_DOMINATORS, target_bb, def_bb)) 746*e4b17023SJohn Marino return true; 747*e4b17023SJohn Marino 748*e4b17023SJohn Marino /* Check if the reg in USE has only one definition. We already 749*e4b17023SJohn Marino know that this definition reaches use, or we wouldn't be here. 750*e4b17023SJohn Marino However, this is invalid for hard registers because if they are 751*e4b17023SJohn Marino live at the beginning of the function it does not mean that we 752*e4b17023SJohn Marino have an uninitialized access. */ 753*e4b17023SJohn Marino regno = DF_REF_REGNO (use); 754*e4b17023SJohn Marino def = DF_REG_DEF_CHAIN (regno); 755*e4b17023SJohn Marino if (def 756*e4b17023SJohn Marino && DF_REF_NEXT_REG (def) == NULL 757*e4b17023SJohn Marino && regno >= FIRST_PSEUDO_REGISTER) 758*e4b17023SJohn Marino return false; 759*e4b17023SJohn Marino 760*e4b17023SJohn Marino /* Check locally if we are in the same basic block. */ 761*e4b17023SJohn Marino if (def_bb == target_bb) 762*e4b17023SJohn Marino return local_ref_killed_between_p (use, def_insn, target_insn); 763*e4b17023SJohn Marino 764*e4b17023SJohn Marino /* Finally, if DEF_BB is the sole predecessor of TARGET_BB. */ 765*e4b17023SJohn Marino if (single_pred_p (target_bb) 766*e4b17023SJohn Marino && single_pred (target_bb) == def_bb) 767*e4b17023SJohn Marino { 768*e4b17023SJohn Marino df_ref x; 769*e4b17023SJohn Marino 770*e4b17023SJohn Marino /* See if USE is killed between DEF_INSN and the last insn in the 771*e4b17023SJohn Marino basic block containing DEF_INSN. */ 772*e4b17023SJohn Marino x = df_bb_regno_last_def_find (def_bb, regno); 773*e4b17023SJohn Marino if (x && DF_INSN_LUID (DF_REF_INSN (x)) >= DF_INSN_LUID (def_insn)) 774*e4b17023SJohn Marino return true; 775*e4b17023SJohn Marino 776*e4b17023SJohn Marino /* See if USE is killed between TARGET_INSN and the first insn in the 777*e4b17023SJohn Marino basic block containing TARGET_INSN. */ 778*e4b17023SJohn Marino x = df_bb_regno_first_def_find (target_bb, regno); 779*e4b17023SJohn Marino if (x && DF_INSN_LUID (DF_REF_INSN (x)) < DF_INSN_LUID (target_insn)) 780*e4b17023SJohn Marino return true; 781*e4b17023SJohn Marino 782*e4b17023SJohn Marino return false; 783*e4b17023SJohn Marino } 784*e4b17023SJohn Marino 785*e4b17023SJohn Marino /* Otherwise assume the worst case. */ 786*e4b17023SJohn Marino return true; 787*e4b17023SJohn Marino } 788*e4b17023SJohn Marino 789*e4b17023SJohn Marino 790*e4b17023SJohn Marino /* Check if all uses in DEF_INSN can be used in TARGET_INSN. This 791*e4b17023SJohn Marino would require full computation of available expressions; 792*e4b17023SJohn Marino we check only restricted conditions, see use_killed_between. */ 793*e4b17023SJohn Marino static bool 794*e4b17023SJohn Marino all_uses_available_at (rtx def_insn, rtx target_insn) 795*e4b17023SJohn Marino { 796*e4b17023SJohn Marino df_ref *use_rec; 797*e4b17023SJohn Marino struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn); 798*e4b17023SJohn Marino rtx def_set = single_set (def_insn); 799*e4b17023SJohn Marino 800*e4b17023SJohn Marino gcc_assert (def_set); 801*e4b17023SJohn Marino 802*e4b17023SJohn Marino /* If target_insn comes right after def_insn, which is very common 803*e4b17023SJohn Marino for addresses, we can use a quicker test. */ 804*e4b17023SJohn Marino if (NEXT_INSN (def_insn) == target_insn 805*e4b17023SJohn Marino && REG_P (SET_DEST (def_set))) 806*e4b17023SJohn Marino { 807*e4b17023SJohn Marino rtx def_reg = SET_DEST (def_set); 808*e4b17023SJohn Marino 809*e4b17023SJohn Marino /* If the insn uses the reg that it defines, the substitution is 810*e4b17023SJohn Marino invalid. */ 811*e4b17023SJohn Marino for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++) 812*e4b17023SJohn Marino { 813*e4b17023SJohn Marino df_ref use = *use_rec; 814*e4b17023SJohn Marino if (rtx_equal_p (DF_REF_REG (use), def_reg)) 815*e4b17023SJohn Marino return false; 816*e4b17023SJohn Marino } 817*e4b17023SJohn Marino for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++) 818*e4b17023SJohn Marino { 819*e4b17023SJohn Marino df_ref use = *use_rec; 820*e4b17023SJohn Marino if (rtx_equal_p (DF_REF_REG (use), def_reg)) 821*e4b17023SJohn Marino return false; 822*e4b17023SJohn Marino } 823*e4b17023SJohn Marino } 824*e4b17023SJohn Marino else 825*e4b17023SJohn Marino { 826*e4b17023SJohn Marino rtx def_reg = REG_P (SET_DEST (def_set)) ? SET_DEST (def_set) : NULL_RTX; 827*e4b17023SJohn Marino 828*e4b17023SJohn Marino /* Look at all the uses of DEF_INSN, and see if they are not 829*e4b17023SJohn Marino killed between DEF_INSN and TARGET_INSN. */ 830*e4b17023SJohn Marino for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++) 831*e4b17023SJohn Marino { 832*e4b17023SJohn Marino df_ref use = *use_rec; 833*e4b17023SJohn Marino if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg)) 834*e4b17023SJohn Marino return false; 835*e4b17023SJohn Marino if (use_killed_between (use, def_insn, target_insn)) 836*e4b17023SJohn Marino return false; 837*e4b17023SJohn Marino } 838*e4b17023SJohn Marino for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++) 839*e4b17023SJohn Marino { 840*e4b17023SJohn Marino df_ref use = *use_rec; 841*e4b17023SJohn Marino if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg)) 842*e4b17023SJohn Marino return false; 843*e4b17023SJohn Marino if (use_killed_between (use, def_insn, target_insn)) 844*e4b17023SJohn Marino return false; 845*e4b17023SJohn Marino } 846*e4b17023SJohn Marino } 847*e4b17023SJohn Marino 848*e4b17023SJohn Marino return true; 849*e4b17023SJohn Marino } 850*e4b17023SJohn Marino 851*e4b17023SJohn Marino 852*e4b17023SJohn Marino static df_ref *active_defs; 853*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 854*e4b17023SJohn Marino static sparseset active_defs_check; 855*e4b17023SJohn Marino #endif 856*e4b17023SJohn Marino 857*e4b17023SJohn Marino /* Fill the ACTIVE_DEFS array with the use->def link for the registers 858*e4b17023SJohn Marino mentioned in USE_REC. Register the valid entries in ACTIVE_DEFS_CHECK 859*e4b17023SJohn Marino too, for checking purposes. */ 860*e4b17023SJohn Marino 861*e4b17023SJohn Marino static void 862*e4b17023SJohn Marino register_active_defs (df_ref *use_rec) 863*e4b17023SJohn Marino { 864*e4b17023SJohn Marino while (*use_rec) 865*e4b17023SJohn Marino { 866*e4b17023SJohn Marino df_ref use = *use_rec++; 867*e4b17023SJohn Marino df_ref def = get_def_for_use (use); 868*e4b17023SJohn Marino int regno = DF_REF_REGNO (use); 869*e4b17023SJohn Marino 870*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 871*e4b17023SJohn Marino sparseset_set_bit (active_defs_check, regno); 872*e4b17023SJohn Marino #endif 873*e4b17023SJohn Marino active_defs[regno] = def; 874*e4b17023SJohn Marino } 875*e4b17023SJohn Marino } 876*e4b17023SJohn Marino 877*e4b17023SJohn Marino 878*e4b17023SJohn Marino /* Build the use->def links that we use to update the dataflow info 879*e4b17023SJohn Marino for new uses. Note that building the links is very cheap and if 880*e4b17023SJohn Marino it were done earlier, they could be used to rule out invalid 881*e4b17023SJohn Marino propagations (in addition to what is done in all_uses_available_at). 882*e4b17023SJohn Marino I'm not doing this yet, though. */ 883*e4b17023SJohn Marino 884*e4b17023SJohn Marino static void 885*e4b17023SJohn Marino update_df_init (rtx def_insn, rtx insn) 886*e4b17023SJohn Marino { 887*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 888*e4b17023SJohn Marino sparseset_clear (active_defs_check); 889*e4b17023SJohn Marino #endif 890*e4b17023SJohn Marino register_active_defs (DF_INSN_USES (def_insn)); 891*e4b17023SJohn Marino register_active_defs (DF_INSN_USES (insn)); 892*e4b17023SJohn Marino register_active_defs (DF_INSN_EQ_USES (insn)); 893*e4b17023SJohn Marino } 894*e4b17023SJohn Marino 895*e4b17023SJohn Marino 896*e4b17023SJohn Marino /* Update the USE_DEF_REF array for the given use, using the active definitions 897*e4b17023SJohn Marino in the ACTIVE_DEFS array to match pseudos to their def. */ 898*e4b17023SJohn Marino 899*e4b17023SJohn Marino static inline void 900*e4b17023SJohn Marino update_uses (df_ref *use_rec) 901*e4b17023SJohn Marino { 902*e4b17023SJohn Marino while (*use_rec) 903*e4b17023SJohn Marino { 904*e4b17023SJohn Marino df_ref use = *use_rec++; 905*e4b17023SJohn Marino int regno = DF_REF_REGNO (use); 906*e4b17023SJohn Marino 907*e4b17023SJohn Marino /* Set up the use-def chain. */ 908*e4b17023SJohn Marino if (DF_REF_ID (use) >= (int) VEC_length (df_ref, use_def_ref)) 909*e4b17023SJohn Marino VEC_safe_grow_cleared (df_ref, heap, use_def_ref, 910*e4b17023SJohn Marino DF_REF_ID (use) + 1); 911*e4b17023SJohn Marino 912*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 913*e4b17023SJohn Marino gcc_assert (sparseset_bit_p (active_defs_check, regno)); 914*e4b17023SJohn Marino #endif 915*e4b17023SJohn Marino VEC_replace (df_ref, use_def_ref, DF_REF_ID (use), active_defs[regno]); 916*e4b17023SJohn Marino } 917*e4b17023SJohn Marino } 918*e4b17023SJohn Marino 919*e4b17023SJohn Marino 920*e4b17023SJohn Marino /* Update the USE_DEF_REF array for the uses in INSN. Only update note 921*e4b17023SJohn Marino uses if NOTES_ONLY is true. */ 922*e4b17023SJohn Marino 923*e4b17023SJohn Marino static void 924*e4b17023SJohn Marino update_df (rtx insn, rtx note) 925*e4b17023SJohn Marino { 926*e4b17023SJohn Marino struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); 927*e4b17023SJohn Marino 928*e4b17023SJohn Marino if (note) 929*e4b17023SJohn Marino { 930*e4b17023SJohn Marino df_uses_create (&XEXP (note, 0), insn, DF_REF_IN_NOTE); 931*e4b17023SJohn Marino df_notes_rescan (insn); 932*e4b17023SJohn Marino } 933*e4b17023SJohn Marino else 934*e4b17023SJohn Marino { 935*e4b17023SJohn Marino df_uses_create (&PATTERN (insn), insn, 0); 936*e4b17023SJohn Marino df_insn_rescan (insn); 937*e4b17023SJohn Marino update_uses (DF_INSN_INFO_USES (insn_info)); 938*e4b17023SJohn Marino } 939*e4b17023SJohn Marino 940*e4b17023SJohn Marino update_uses (DF_INSN_INFO_EQ_USES (insn_info)); 941*e4b17023SJohn Marino } 942*e4b17023SJohn Marino 943*e4b17023SJohn Marino 944*e4b17023SJohn Marino /* Try substituting NEW into LOC, which originated from forward propagation 945*e4b17023SJohn Marino of USE's value from DEF_INSN. SET_REG_EQUAL says whether we are 946*e4b17023SJohn Marino substituting the whole SET_SRC, so we can set a REG_EQUAL note if the 947*e4b17023SJohn Marino new insn is not recognized. Return whether the substitution was 948*e4b17023SJohn Marino performed. */ 949*e4b17023SJohn Marino 950*e4b17023SJohn Marino static bool 951*e4b17023SJohn Marino try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_equal) 952*e4b17023SJohn Marino { 953*e4b17023SJohn Marino rtx insn = DF_REF_INSN (use); 954*e4b17023SJohn Marino rtx set = single_set (insn); 955*e4b17023SJohn Marino rtx note = NULL_RTX; 956*e4b17023SJohn Marino bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 957*e4b17023SJohn Marino int old_cost = 0; 958*e4b17023SJohn Marino bool ok; 959*e4b17023SJohn Marino 960*e4b17023SJohn Marino update_df_init (def_insn, insn); 961*e4b17023SJohn Marino 962*e4b17023SJohn Marino /* forward_propagate_subreg may be operating on an instruction with 963*e4b17023SJohn Marino multiple sets. If so, assume the cost of the new instruction is 964*e4b17023SJohn Marino not greater than the old one. */ 965*e4b17023SJohn Marino if (set) 966*e4b17023SJohn Marino old_cost = set_src_cost (SET_SRC (set), speed); 967*e4b17023SJohn Marino if (dump_file) 968*e4b17023SJohn Marino { 969*e4b17023SJohn Marino fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn)); 970*e4b17023SJohn Marino print_inline_rtx (dump_file, *loc, 2); 971*e4b17023SJohn Marino fprintf (dump_file, "\n with "); 972*e4b17023SJohn Marino print_inline_rtx (dump_file, new_rtx, 2); 973*e4b17023SJohn Marino fprintf (dump_file, "\n"); 974*e4b17023SJohn Marino } 975*e4b17023SJohn Marino 976*e4b17023SJohn Marino validate_unshare_change (insn, loc, new_rtx, true); 977*e4b17023SJohn Marino if (!verify_changes (0)) 978*e4b17023SJohn Marino { 979*e4b17023SJohn Marino if (dump_file) 980*e4b17023SJohn Marino fprintf (dump_file, "Changes to insn %d not recognized\n", 981*e4b17023SJohn Marino INSN_UID (insn)); 982*e4b17023SJohn Marino ok = false; 983*e4b17023SJohn Marino } 984*e4b17023SJohn Marino 985*e4b17023SJohn Marino else if (DF_REF_TYPE (use) == DF_REF_REG_USE 986*e4b17023SJohn Marino && set 987*e4b17023SJohn Marino && set_src_cost (SET_SRC (set), speed) > old_cost) 988*e4b17023SJohn Marino { 989*e4b17023SJohn Marino if (dump_file) 990*e4b17023SJohn Marino fprintf (dump_file, "Changes to insn %d not profitable\n", 991*e4b17023SJohn Marino INSN_UID (insn)); 992*e4b17023SJohn Marino ok = false; 993*e4b17023SJohn Marino } 994*e4b17023SJohn Marino 995*e4b17023SJohn Marino else 996*e4b17023SJohn Marino { 997*e4b17023SJohn Marino if (dump_file) 998*e4b17023SJohn Marino fprintf (dump_file, "Changed insn %d\n", INSN_UID (insn)); 999*e4b17023SJohn Marino ok = true; 1000*e4b17023SJohn Marino } 1001*e4b17023SJohn Marino 1002*e4b17023SJohn Marino if (ok) 1003*e4b17023SJohn Marino { 1004*e4b17023SJohn Marino confirm_change_group (); 1005*e4b17023SJohn Marino num_changes++; 1006*e4b17023SJohn Marino } 1007*e4b17023SJohn Marino else 1008*e4b17023SJohn Marino { 1009*e4b17023SJohn Marino cancel_changes (0); 1010*e4b17023SJohn Marino 1011*e4b17023SJohn Marino /* Can also record a simplified value in a REG_EQUAL note, 1012*e4b17023SJohn Marino making a new one if one does not already exist. */ 1013*e4b17023SJohn Marino if (set_reg_equal) 1014*e4b17023SJohn Marino { 1015*e4b17023SJohn Marino if (dump_file) 1016*e4b17023SJohn Marino fprintf (dump_file, " Setting REG_EQUAL note\n"); 1017*e4b17023SJohn Marino 1018*e4b17023SJohn Marino note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx)); 1019*e4b17023SJohn Marino } 1020*e4b17023SJohn Marino } 1021*e4b17023SJohn Marino 1022*e4b17023SJohn Marino if ((ok || note) && !CONSTANT_P (new_rtx)) 1023*e4b17023SJohn Marino update_df (insn, note); 1024*e4b17023SJohn Marino 1025*e4b17023SJohn Marino return ok; 1026*e4b17023SJohn Marino } 1027*e4b17023SJohn Marino 1028*e4b17023SJohn Marino /* For the given single_set INSN, containing SRC known to be a 1029*e4b17023SJohn Marino ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN 1030*e4b17023SJohn Marino is redundant due to the register being set by a LOAD_EXTEND_OP 1031*e4b17023SJohn Marino load from memory. */ 1032*e4b17023SJohn Marino 1033*e4b17023SJohn Marino static bool 1034*e4b17023SJohn Marino free_load_extend (rtx src, rtx insn) 1035*e4b17023SJohn Marino { 1036*e4b17023SJohn Marino rtx reg; 1037*e4b17023SJohn Marino df_ref *use_vec; 1038*e4b17023SJohn Marino df_ref use = 0, def; 1039*e4b17023SJohn Marino 1040*e4b17023SJohn Marino reg = XEXP (src, 0); 1041*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP 1042*e4b17023SJohn Marino if (LOAD_EXTEND_OP (GET_MODE (reg)) != GET_CODE (src)) 1043*e4b17023SJohn Marino #endif 1044*e4b17023SJohn Marino return false; 1045*e4b17023SJohn Marino 1046*e4b17023SJohn Marino for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++) 1047*e4b17023SJohn Marino { 1048*e4b17023SJohn Marino use = *use_vec; 1049*e4b17023SJohn Marino 1050*e4b17023SJohn Marino if (!DF_REF_IS_ARTIFICIAL (use) 1051*e4b17023SJohn Marino && DF_REF_TYPE (use) == DF_REF_REG_USE 1052*e4b17023SJohn Marino && DF_REF_REG (use) == reg) 1053*e4b17023SJohn Marino break; 1054*e4b17023SJohn Marino } 1055*e4b17023SJohn Marino if (!use) 1056*e4b17023SJohn Marino return false; 1057*e4b17023SJohn Marino 1058*e4b17023SJohn Marino def = get_def_for_use (use); 1059*e4b17023SJohn Marino if (!def) 1060*e4b17023SJohn Marino return false; 1061*e4b17023SJohn Marino 1062*e4b17023SJohn Marino if (DF_REF_IS_ARTIFICIAL (def)) 1063*e4b17023SJohn Marino return false; 1064*e4b17023SJohn Marino 1065*e4b17023SJohn Marino if (NONJUMP_INSN_P (DF_REF_INSN (def))) 1066*e4b17023SJohn Marino { 1067*e4b17023SJohn Marino rtx patt = PATTERN (DF_REF_INSN (def)); 1068*e4b17023SJohn Marino 1069*e4b17023SJohn Marino if (GET_CODE (patt) == SET 1070*e4b17023SJohn Marino && GET_CODE (SET_SRC (patt)) == MEM 1071*e4b17023SJohn Marino && rtx_equal_p (SET_DEST (patt), reg)) 1072*e4b17023SJohn Marino return true; 1073*e4b17023SJohn Marino } 1074*e4b17023SJohn Marino return false; 1075*e4b17023SJohn Marino } 1076*e4b17023SJohn Marino 1077*e4b17023SJohn Marino /* If USE is a subreg, see if it can be replaced by a pseudo. */ 1078*e4b17023SJohn Marino 1079*e4b17023SJohn Marino static bool 1080*e4b17023SJohn Marino forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set) 1081*e4b17023SJohn Marino { 1082*e4b17023SJohn Marino rtx use_reg = DF_REF_REG (use); 1083*e4b17023SJohn Marino rtx use_insn, src; 1084*e4b17023SJohn Marino 1085*e4b17023SJohn Marino /* Only consider subregs... */ 1086*e4b17023SJohn Marino enum machine_mode use_mode = GET_MODE (use_reg); 1087*e4b17023SJohn Marino if (GET_CODE (use_reg) != SUBREG 1088*e4b17023SJohn Marino || !REG_P (SET_DEST (def_set))) 1089*e4b17023SJohn Marino return false; 1090*e4b17023SJohn Marino 1091*e4b17023SJohn Marino /* If this is a paradoxical SUBREG... */ 1092*e4b17023SJohn Marino if (GET_MODE_SIZE (use_mode) 1093*e4b17023SJohn Marino > GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg)))) 1094*e4b17023SJohn Marino { 1095*e4b17023SJohn Marino /* If this is a paradoxical SUBREG, we have no idea what value the 1096*e4b17023SJohn Marino extra bits would have. However, if the operand is equivalent to 1097*e4b17023SJohn Marino a SUBREG whose operand is the same as our mode, and all the modes 1098*e4b17023SJohn Marino are within a word, we can just use the inner operand because 1099*e4b17023SJohn Marino these SUBREGs just say how to treat the register. */ 1100*e4b17023SJohn Marino use_insn = DF_REF_INSN (use); 1101*e4b17023SJohn Marino src = SET_SRC (def_set); 1102*e4b17023SJohn Marino if (GET_CODE (src) == SUBREG 1103*e4b17023SJohn Marino && REG_P (SUBREG_REG (src)) 1104*e4b17023SJohn Marino && REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER 1105*e4b17023SJohn Marino && GET_MODE (SUBREG_REG (src)) == use_mode 1106*e4b17023SJohn Marino && subreg_lowpart_p (src) 1107*e4b17023SJohn Marino && all_uses_available_at (def_insn, use_insn)) 1108*e4b17023SJohn Marino return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src), 1109*e4b17023SJohn Marino def_insn, false); 1110*e4b17023SJohn Marino } 1111*e4b17023SJohn Marino 1112*e4b17023SJohn Marino /* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG 1113*e4b17023SJohn Marino is the low part of the reg being extended then just use the inner 1114*e4b17023SJohn Marino operand. Don't do this if the ZERO_EXTEND or SIGN_EXTEND insn will 1115*e4b17023SJohn Marino be removed due to it matching a LOAD_EXTEND_OP load from memory, 1116*e4b17023SJohn Marino or due to the operation being a no-op when applied to registers. 1117*e4b17023SJohn Marino For example, if we have: 1118*e4b17023SJohn Marino 1119*e4b17023SJohn Marino A: (set (reg:DI X) (sign_extend:DI (reg:SI Y))) 1120*e4b17023SJohn Marino B: (... (subreg:SI (reg:DI X)) ...) 1121*e4b17023SJohn Marino 1122*e4b17023SJohn Marino and mode_rep_extended says that Y is already sign-extended, 1123*e4b17023SJohn Marino the backend will typically allow A to be combined with the 1124*e4b17023SJohn Marino definition of Y or, failing that, allow A to be deleted after 1125*e4b17023SJohn Marino reload through register tying. Introducing more uses of Y 1126*e4b17023SJohn Marino prevents both optimisations. */ 1127*e4b17023SJohn Marino else if (subreg_lowpart_p (use_reg)) 1128*e4b17023SJohn Marino { 1129*e4b17023SJohn Marino use_insn = DF_REF_INSN (use); 1130*e4b17023SJohn Marino src = SET_SRC (def_set); 1131*e4b17023SJohn Marino if ((GET_CODE (src) == ZERO_EXTEND 1132*e4b17023SJohn Marino || GET_CODE (src) == SIGN_EXTEND) 1133*e4b17023SJohn Marino && REG_P (XEXP (src, 0)) 1134*e4b17023SJohn Marino && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER 1135*e4b17023SJohn Marino && GET_MODE (XEXP (src, 0)) == use_mode 1136*e4b17023SJohn Marino && !free_load_extend (src, def_insn) 1137*e4b17023SJohn Marino && (targetm.mode_rep_extended (use_mode, GET_MODE (src)) 1138*e4b17023SJohn Marino != (int) GET_CODE (src)) 1139*e4b17023SJohn Marino && all_uses_available_at (def_insn, use_insn)) 1140*e4b17023SJohn Marino return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0), 1141*e4b17023SJohn Marino def_insn, false); 1142*e4b17023SJohn Marino } 1143*e4b17023SJohn Marino 1144*e4b17023SJohn Marino return false; 1145*e4b17023SJohn Marino } 1146*e4b17023SJohn Marino 1147*e4b17023SJohn Marino /* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */ 1148*e4b17023SJohn Marino 1149*e4b17023SJohn Marino static bool 1150*e4b17023SJohn Marino forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg) 1151*e4b17023SJohn Marino { 1152*e4b17023SJohn Marino rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc; 1153*e4b17023SJohn Marino int speed_p, i; 1154*e4b17023SJohn Marino df_ref *use_vec; 1155*e4b17023SJohn Marino 1156*e4b17023SJohn Marino gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0); 1157*e4b17023SJohn Marino 1158*e4b17023SJohn Marino src = SET_SRC (def_set); 1159*e4b17023SJohn Marino use_pat = PATTERN (use_insn); 1160*e4b17023SJohn Marino 1161*e4b17023SJohn Marino /* In __asm don't replace if src might need more registers than 1162*e4b17023SJohn Marino reg, as that could increase register pressure on the __asm. */ 1163*e4b17023SJohn Marino use_vec = DF_INSN_USES (def_insn); 1164*e4b17023SJohn Marino if (use_vec[0] && use_vec[1]) 1165*e4b17023SJohn Marino return false; 1166*e4b17023SJohn Marino 1167*e4b17023SJohn Marino update_df_init (def_insn, use_insn); 1168*e4b17023SJohn Marino speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); 1169*e4b17023SJohn Marino asm_operands = NULL_RTX; 1170*e4b17023SJohn Marino switch (GET_CODE (use_pat)) 1171*e4b17023SJohn Marino { 1172*e4b17023SJohn Marino case ASM_OPERANDS: 1173*e4b17023SJohn Marino asm_operands = use_pat; 1174*e4b17023SJohn Marino break; 1175*e4b17023SJohn Marino case SET: 1176*e4b17023SJohn Marino if (MEM_P (SET_DEST (use_pat))) 1177*e4b17023SJohn Marino { 1178*e4b17023SJohn Marino loc = &SET_DEST (use_pat); 1179*e4b17023SJohn Marino new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); 1180*e4b17023SJohn Marino if (new_rtx) 1181*e4b17023SJohn Marino validate_unshare_change (use_insn, loc, new_rtx, true); 1182*e4b17023SJohn Marino } 1183*e4b17023SJohn Marino asm_operands = SET_SRC (use_pat); 1184*e4b17023SJohn Marino break; 1185*e4b17023SJohn Marino case PARALLEL: 1186*e4b17023SJohn Marino for (i = 0; i < XVECLEN (use_pat, 0); i++) 1187*e4b17023SJohn Marino if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET) 1188*e4b17023SJohn Marino { 1189*e4b17023SJohn Marino if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i)))) 1190*e4b17023SJohn Marino { 1191*e4b17023SJohn Marino loc = &SET_DEST (XVECEXP (use_pat, 0, i)); 1192*e4b17023SJohn Marino new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, 1193*e4b17023SJohn Marino src, speed_p); 1194*e4b17023SJohn Marino if (new_rtx) 1195*e4b17023SJohn Marino validate_unshare_change (use_insn, loc, new_rtx, true); 1196*e4b17023SJohn Marino } 1197*e4b17023SJohn Marino asm_operands = SET_SRC (XVECEXP (use_pat, 0, i)); 1198*e4b17023SJohn Marino } 1199*e4b17023SJohn Marino else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS) 1200*e4b17023SJohn Marino asm_operands = XVECEXP (use_pat, 0, i); 1201*e4b17023SJohn Marino break; 1202*e4b17023SJohn Marino default: 1203*e4b17023SJohn Marino gcc_unreachable (); 1204*e4b17023SJohn Marino } 1205*e4b17023SJohn Marino 1206*e4b17023SJohn Marino gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS); 1207*e4b17023SJohn Marino for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++) 1208*e4b17023SJohn Marino { 1209*e4b17023SJohn Marino loc = &ASM_OPERANDS_INPUT (asm_operands, i); 1210*e4b17023SJohn Marino new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); 1211*e4b17023SJohn Marino if (new_rtx) 1212*e4b17023SJohn Marino validate_unshare_change (use_insn, loc, new_rtx, true); 1213*e4b17023SJohn Marino } 1214*e4b17023SJohn Marino 1215*e4b17023SJohn Marino if (num_changes_pending () == 0 || !apply_change_group ()) 1216*e4b17023SJohn Marino return false; 1217*e4b17023SJohn Marino 1218*e4b17023SJohn Marino update_df (use_insn, NULL); 1219*e4b17023SJohn Marino num_changes++; 1220*e4b17023SJohn Marino return true; 1221*e4b17023SJohn Marino } 1222*e4b17023SJohn Marino 1223*e4b17023SJohn Marino /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the 1224*e4b17023SJohn Marino result. */ 1225*e4b17023SJohn Marino 1226*e4b17023SJohn Marino static bool 1227*e4b17023SJohn Marino forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set) 1228*e4b17023SJohn Marino { 1229*e4b17023SJohn Marino rtx use_insn = DF_REF_INSN (use); 1230*e4b17023SJohn Marino rtx use_set = single_set (use_insn); 1231*e4b17023SJohn Marino rtx src, reg, new_rtx, *loc; 1232*e4b17023SJohn Marino bool set_reg_equal; 1233*e4b17023SJohn Marino enum machine_mode mode; 1234*e4b17023SJohn Marino int asm_use = -1; 1235*e4b17023SJohn Marino 1236*e4b17023SJohn Marino if (INSN_CODE (use_insn) < 0) 1237*e4b17023SJohn Marino asm_use = asm_noperands (PATTERN (use_insn)); 1238*e4b17023SJohn Marino 1239*e4b17023SJohn Marino if (!use_set && asm_use < 0 && !DEBUG_INSN_P (use_insn)) 1240*e4b17023SJohn Marino return false; 1241*e4b17023SJohn Marino 1242*e4b17023SJohn Marino /* Do not propagate into PC, CC0, etc. */ 1243*e4b17023SJohn Marino if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode) 1244*e4b17023SJohn Marino return false; 1245*e4b17023SJohn Marino 1246*e4b17023SJohn Marino /* If def and use are subreg, check if they match. */ 1247*e4b17023SJohn Marino reg = DF_REF_REG (use); 1248*e4b17023SJohn Marino if (GET_CODE (reg) == SUBREG && GET_CODE (SET_DEST (def_set)) == SUBREG) 1249*e4b17023SJohn Marino { 1250*e4b17023SJohn Marino if (SUBREG_BYTE (SET_DEST (def_set)) != SUBREG_BYTE (reg)) 1251*e4b17023SJohn Marino return false; 1252*e4b17023SJohn Marino } 1253*e4b17023SJohn Marino /* Check if the def had a subreg, but the use has the whole reg. */ 1254*e4b17023SJohn Marino else if (REG_P (reg) && GET_CODE (SET_DEST (def_set)) == SUBREG) 1255*e4b17023SJohn Marino return false; 1256*e4b17023SJohn Marino /* Check if the use has a subreg, but the def had the whole reg. Unlike the 1257*e4b17023SJohn Marino previous case, the optimization is possible and often useful indeed. */ 1258*e4b17023SJohn Marino else if (GET_CODE (reg) == SUBREG && REG_P (SET_DEST (def_set))) 1259*e4b17023SJohn Marino reg = SUBREG_REG (reg); 1260*e4b17023SJohn Marino 1261*e4b17023SJohn Marino /* Make sure that we can treat REG as having the same mode as the 1262*e4b17023SJohn Marino source of DEF_SET. */ 1263*e4b17023SJohn Marino if (GET_MODE (SET_DEST (def_set)) != GET_MODE (reg)) 1264*e4b17023SJohn Marino return false; 1265*e4b17023SJohn Marino 1266*e4b17023SJohn Marino /* Check if the substitution is valid (last, because it's the most 1267*e4b17023SJohn Marino expensive check!). */ 1268*e4b17023SJohn Marino src = SET_SRC (def_set); 1269*e4b17023SJohn Marino if (!CONSTANT_P (src) && !all_uses_available_at (def_insn, use_insn)) 1270*e4b17023SJohn Marino return false; 1271*e4b17023SJohn Marino 1272*e4b17023SJohn Marino /* Check if the def is loading something from the constant pool; in this 1273*e4b17023SJohn Marino case we would undo optimization such as compress_float_constant. 1274*e4b17023SJohn Marino Still, we can set a REG_EQUAL note. */ 1275*e4b17023SJohn Marino if (MEM_P (src) && MEM_READONLY_P (src)) 1276*e4b17023SJohn Marino { 1277*e4b17023SJohn Marino rtx x = avoid_constant_pool_reference (src); 1278*e4b17023SJohn Marino if (x != src && use_set) 1279*e4b17023SJohn Marino { 1280*e4b17023SJohn Marino rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); 1281*e4b17023SJohn Marino rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set); 1282*e4b17023SJohn Marino rtx new_rtx = simplify_replace_rtx (old_rtx, src, x); 1283*e4b17023SJohn Marino if (old_rtx != new_rtx) 1284*e4b17023SJohn Marino set_unique_reg_note (use_insn, REG_EQUAL, copy_rtx (new_rtx)); 1285*e4b17023SJohn Marino } 1286*e4b17023SJohn Marino return false; 1287*e4b17023SJohn Marino } 1288*e4b17023SJohn Marino 1289*e4b17023SJohn Marino if (asm_use >= 0) 1290*e4b17023SJohn Marino return forward_propagate_asm (use, def_insn, def_set, reg); 1291*e4b17023SJohn Marino 1292*e4b17023SJohn Marino /* Else try simplifying. */ 1293*e4b17023SJohn Marino 1294*e4b17023SJohn Marino if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE) 1295*e4b17023SJohn Marino { 1296*e4b17023SJohn Marino loc = &SET_DEST (use_set); 1297*e4b17023SJohn Marino set_reg_equal = false; 1298*e4b17023SJohn Marino } 1299*e4b17023SJohn Marino else if (!use_set) 1300*e4b17023SJohn Marino { 1301*e4b17023SJohn Marino loc = &INSN_VAR_LOCATION_LOC (use_insn); 1302*e4b17023SJohn Marino set_reg_equal = false; 1303*e4b17023SJohn Marino } 1304*e4b17023SJohn Marino else 1305*e4b17023SJohn Marino { 1306*e4b17023SJohn Marino rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); 1307*e4b17023SJohn Marino if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE) 1308*e4b17023SJohn Marino loc = &XEXP (note, 0); 1309*e4b17023SJohn Marino else 1310*e4b17023SJohn Marino loc = &SET_SRC (use_set); 1311*e4b17023SJohn Marino 1312*e4b17023SJohn Marino /* Do not replace an existing REG_EQUAL note if the insn is not 1313*e4b17023SJohn Marino recognized. Either we're already replacing in the note, or we'll 1314*e4b17023SJohn Marino separately try plugging the definition in the note and simplifying. 1315*e4b17023SJohn Marino And only install a REQ_EQUAL note when the destination is a REG, 1316*e4b17023SJohn Marino as the note would be invalid otherwise. */ 1317*e4b17023SJohn Marino set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set))); 1318*e4b17023SJohn Marino } 1319*e4b17023SJohn Marino 1320*e4b17023SJohn Marino if (GET_MODE (*loc) == VOIDmode) 1321*e4b17023SJohn Marino mode = GET_MODE (SET_DEST (use_set)); 1322*e4b17023SJohn Marino else 1323*e4b17023SJohn Marino mode = GET_MODE (*loc); 1324*e4b17023SJohn Marino 1325*e4b17023SJohn Marino new_rtx = propagate_rtx (*loc, mode, reg, src, 1326*e4b17023SJohn Marino optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn))); 1327*e4b17023SJohn Marino 1328*e4b17023SJohn Marino if (!new_rtx) 1329*e4b17023SJohn Marino return false; 1330*e4b17023SJohn Marino 1331*e4b17023SJohn Marino return try_fwprop_subst (use, loc, new_rtx, def_insn, set_reg_equal); 1332*e4b17023SJohn Marino } 1333*e4b17023SJohn Marino 1334*e4b17023SJohn Marino 1335*e4b17023SJohn Marino /* Given a use USE of an insn, if it has a single reaching 1336*e4b17023SJohn Marino definition, try to forward propagate it into that insn. 1337*e4b17023SJohn Marino Return true if cfg cleanup will be needed. */ 1338*e4b17023SJohn Marino 1339*e4b17023SJohn Marino static bool 1340*e4b17023SJohn Marino forward_propagate_into (df_ref use) 1341*e4b17023SJohn Marino { 1342*e4b17023SJohn Marino df_ref def; 1343*e4b17023SJohn Marino rtx def_insn, def_set, use_insn; 1344*e4b17023SJohn Marino rtx parent; 1345*e4b17023SJohn Marino 1346*e4b17023SJohn Marino if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE) 1347*e4b17023SJohn Marino return false; 1348*e4b17023SJohn Marino if (DF_REF_IS_ARTIFICIAL (use)) 1349*e4b17023SJohn Marino return false; 1350*e4b17023SJohn Marino 1351*e4b17023SJohn Marino /* Only consider uses that have a single definition. */ 1352*e4b17023SJohn Marino def = get_def_for_use (use); 1353*e4b17023SJohn Marino if (!def) 1354*e4b17023SJohn Marino return false; 1355*e4b17023SJohn Marino if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE) 1356*e4b17023SJohn Marino return false; 1357*e4b17023SJohn Marino if (DF_REF_IS_ARTIFICIAL (def)) 1358*e4b17023SJohn Marino return false; 1359*e4b17023SJohn Marino 1360*e4b17023SJohn Marino /* Do not propagate loop invariant definitions inside the loop. */ 1361*e4b17023SJohn Marino if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father) 1362*e4b17023SJohn Marino return false; 1363*e4b17023SJohn Marino 1364*e4b17023SJohn Marino /* Check if the use is still present in the insn! */ 1365*e4b17023SJohn Marino use_insn = DF_REF_INSN (use); 1366*e4b17023SJohn Marino if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE) 1367*e4b17023SJohn Marino parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); 1368*e4b17023SJohn Marino else 1369*e4b17023SJohn Marino parent = PATTERN (use_insn); 1370*e4b17023SJohn Marino 1371*e4b17023SJohn Marino if (!reg_mentioned_p (DF_REF_REG (use), parent)) 1372*e4b17023SJohn Marino return false; 1373*e4b17023SJohn Marino 1374*e4b17023SJohn Marino def_insn = DF_REF_INSN (def); 1375*e4b17023SJohn Marino if (multiple_sets (def_insn)) 1376*e4b17023SJohn Marino return false; 1377*e4b17023SJohn Marino def_set = single_set (def_insn); 1378*e4b17023SJohn Marino if (!def_set) 1379*e4b17023SJohn Marino return false; 1380*e4b17023SJohn Marino 1381*e4b17023SJohn Marino /* Only try one kind of propagation. If two are possible, we'll 1382*e4b17023SJohn Marino do it on the following iterations. */ 1383*e4b17023SJohn Marino if (forward_propagate_and_simplify (use, def_insn, def_set) 1384*e4b17023SJohn Marino || forward_propagate_subreg (use, def_insn, def_set)) 1385*e4b17023SJohn Marino { 1386*e4b17023SJohn Marino if (cfun->can_throw_non_call_exceptions 1387*e4b17023SJohn Marino && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX) 1388*e4b17023SJohn Marino && purge_dead_edges (DF_REF_BB (use))) 1389*e4b17023SJohn Marino return true; 1390*e4b17023SJohn Marino } 1391*e4b17023SJohn Marino return false; 1392*e4b17023SJohn Marino } 1393*e4b17023SJohn Marino 1394*e4b17023SJohn Marino 1395*e4b17023SJohn Marino static void 1396*e4b17023SJohn Marino fwprop_init (void) 1397*e4b17023SJohn Marino { 1398*e4b17023SJohn Marino num_changes = 0; 1399*e4b17023SJohn Marino calculate_dominance_info (CDI_DOMINATORS); 1400*e4b17023SJohn Marino 1401*e4b17023SJohn Marino /* We do not always want to propagate into loops, so we have to find 1402*e4b17023SJohn Marino loops and be careful about them. But we have to call flow_loops_find 1403*e4b17023SJohn Marino before df_analyze, because flow_loops_find may introduce new jump 1404*e4b17023SJohn Marino insns (sadly) if we are not working in cfglayout mode. */ 1405*e4b17023SJohn Marino loop_optimizer_init (0); 1406*e4b17023SJohn Marino 1407*e4b17023SJohn Marino build_single_def_use_links (); 1408*e4b17023SJohn Marino df_set_flags (DF_DEFER_INSN_RESCAN); 1409*e4b17023SJohn Marino 1410*e4b17023SJohn Marino active_defs = XNEWVEC (df_ref, max_reg_num ()); 1411*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 1412*e4b17023SJohn Marino active_defs_check = sparseset_alloc (max_reg_num ()); 1413*e4b17023SJohn Marino #endif 1414*e4b17023SJohn Marino } 1415*e4b17023SJohn Marino 1416*e4b17023SJohn Marino static void 1417*e4b17023SJohn Marino fwprop_done (void) 1418*e4b17023SJohn Marino { 1419*e4b17023SJohn Marino loop_optimizer_finalize (); 1420*e4b17023SJohn Marino 1421*e4b17023SJohn Marino VEC_free (df_ref, heap, use_def_ref); 1422*e4b17023SJohn Marino free (active_defs); 1423*e4b17023SJohn Marino #ifdef ENABLE_CHECKING 1424*e4b17023SJohn Marino sparseset_free (active_defs_check); 1425*e4b17023SJohn Marino #endif 1426*e4b17023SJohn Marino 1427*e4b17023SJohn Marino free_dominance_info (CDI_DOMINATORS); 1428*e4b17023SJohn Marino cleanup_cfg (0); 1429*e4b17023SJohn Marino delete_trivially_dead_insns (get_insns (), max_reg_num ()); 1430*e4b17023SJohn Marino 1431*e4b17023SJohn Marino if (dump_file) 1432*e4b17023SJohn Marino fprintf (dump_file, 1433*e4b17023SJohn Marino "\nNumber of successful forward propagations: %d\n\n", 1434*e4b17023SJohn Marino num_changes); 1435*e4b17023SJohn Marino } 1436*e4b17023SJohn Marino 1437*e4b17023SJohn Marino 1438*e4b17023SJohn Marino /* Main entry point. */ 1439*e4b17023SJohn Marino 1440*e4b17023SJohn Marino static bool 1441*e4b17023SJohn Marino gate_fwprop (void) 1442*e4b17023SJohn Marino { 1443*e4b17023SJohn Marino return optimize > 0 && flag_forward_propagate; 1444*e4b17023SJohn Marino } 1445*e4b17023SJohn Marino 1446*e4b17023SJohn Marino static unsigned int 1447*e4b17023SJohn Marino fwprop (void) 1448*e4b17023SJohn Marino { 1449*e4b17023SJohn Marino unsigned i; 1450*e4b17023SJohn Marino bool need_cleanup = false; 1451*e4b17023SJohn Marino 1452*e4b17023SJohn Marino fwprop_init (); 1453*e4b17023SJohn Marino 1454*e4b17023SJohn Marino /* Go through all the uses. df_uses_create will create new ones at the 1455*e4b17023SJohn Marino end, and we'll go through them as well. 1456*e4b17023SJohn Marino 1457*e4b17023SJohn Marino Do not forward propagate addresses into loops until after unrolling. 1458*e4b17023SJohn Marino CSE did so because it was able to fix its own mess, but we are not. */ 1459*e4b17023SJohn Marino 1460*e4b17023SJohn Marino for (i = 0; i < DF_USES_TABLE_SIZE (); i++) 1461*e4b17023SJohn Marino { 1462*e4b17023SJohn Marino df_ref use = DF_USES_GET (i); 1463*e4b17023SJohn Marino if (use) 1464*e4b17023SJohn Marino if (DF_REF_TYPE (use) == DF_REF_REG_USE 1465*e4b17023SJohn Marino || DF_REF_BB (use)->loop_father == NULL 1466*e4b17023SJohn Marino /* The outer most loop is not really a loop. */ 1467*e4b17023SJohn Marino || loop_outer (DF_REF_BB (use)->loop_father) == NULL) 1468*e4b17023SJohn Marino need_cleanup |= forward_propagate_into (use); 1469*e4b17023SJohn Marino } 1470*e4b17023SJohn Marino 1471*e4b17023SJohn Marino fwprop_done (); 1472*e4b17023SJohn Marino if (need_cleanup) 1473*e4b17023SJohn Marino cleanup_cfg (0); 1474*e4b17023SJohn Marino return 0; 1475*e4b17023SJohn Marino } 1476*e4b17023SJohn Marino 1477*e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_fwprop = 1478*e4b17023SJohn Marino { 1479*e4b17023SJohn Marino { 1480*e4b17023SJohn Marino RTL_PASS, 1481*e4b17023SJohn Marino "fwprop1", /* name */ 1482*e4b17023SJohn Marino gate_fwprop, /* gate */ 1483*e4b17023SJohn Marino fwprop, /* execute */ 1484*e4b17023SJohn Marino NULL, /* sub */ 1485*e4b17023SJohn Marino NULL, /* next */ 1486*e4b17023SJohn Marino 0, /* static_pass_number */ 1487*e4b17023SJohn Marino TV_FWPROP, /* tv_id */ 1488*e4b17023SJohn Marino 0, /* properties_required */ 1489*e4b17023SJohn Marino 0, /* properties_provided */ 1490*e4b17023SJohn Marino 0, /* properties_destroyed */ 1491*e4b17023SJohn Marino 0, /* todo_flags_start */ 1492*e4b17023SJohn Marino TODO_df_finish 1493*e4b17023SJohn Marino | TODO_verify_flow 1494*e4b17023SJohn Marino | TODO_verify_rtl_sharing /* todo_flags_finish */ 1495*e4b17023SJohn Marino } 1496*e4b17023SJohn Marino }; 1497*e4b17023SJohn Marino 1498*e4b17023SJohn Marino static unsigned int 1499*e4b17023SJohn Marino fwprop_addr (void) 1500*e4b17023SJohn Marino { 1501*e4b17023SJohn Marino unsigned i; 1502*e4b17023SJohn Marino bool need_cleanup = false; 1503*e4b17023SJohn Marino 1504*e4b17023SJohn Marino fwprop_init (); 1505*e4b17023SJohn Marino 1506*e4b17023SJohn Marino /* Go through all the uses. df_uses_create will create new ones at the 1507*e4b17023SJohn Marino end, and we'll go through them as well. */ 1508*e4b17023SJohn Marino for (i = 0; i < DF_USES_TABLE_SIZE (); i++) 1509*e4b17023SJohn Marino { 1510*e4b17023SJohn Marino df_ref use = DF_USES_GET (i); 1511*e4b17023SJohn Marino if (use) 1512*e4b17023SJohn Marino if (DF_REF_TYPE (use) != DF_REF_REG_USE 1513*e4b17023SJohn Marino && DF_REF_BB (use)->loop_father != NULL 1514*e4b17023SJohn Marino /* The outer most loop is not really a loop. */ 1515*e4b17023SJohn Marino && loop_outer (DF_REF_BB (use)->loop_father) != NULL) 1516*e4b17023SJohn Marino need_cleanup |= forward_propagate_into (use); 1517*e4b17023SJohn Marino } 1518*e4b17023SJohn Marino 1519*e4b17023SJohn Marino fwprop_done (); 1520*e4b17023SJohn Marino 1521*e4b17023SJohn Marino if (need_cleanup) 1522*e4b17023SJohn Marino cleanup_cfg (0); 1523*e4b17023SJohn Marino return 0; 1524*e4b17023SJohn Marino } 1525*e4b17023SJohn Marino 1526*e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_fwprop_addr = 1527*e4b17023SJohn Marino { 1528*e4b17023SJohn Marino { 1529*e4b17023SJohn Marino RTL_PASS, 1530*e4b17023SJohn Marino "fwprop2", /* name */ 1531*e4b17023SJohn Marino gate_fwprop, /* gate */ 1532*e4b17023SJohn Marino fwprop_addr, /* execute */ 1533*e4b17023SJohn Marino NULL, /* sub */ 1534*e4b17023SJohn Marino NULL, /* next */ 1535*e4b17023SJohn Marino 0, /* static_pass_number */ 1536*e4b17023SJohn Marino TV_FWPROP, /* tv_id */ 1537*e4b17023SJohn Marino 0, /* properties_required */ 1538*e4b17023SJohn Marino 0, /* properties_provided */ 1539*e4b17023SJohn Marino 0, /* properties_destroyed */ 1540*e4b17023SJohn Marino 0, /* todo_flags_start */ 1541*e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing /* todo_flags_finish */ 1542*e4b17023SJohn Marino } 1543*e4b17023SJohn Marino }; 1544