1*38fd1498Szrj /* RTL dead code elimination. 2*38fd1498Szrj Copyright (C) 2005-2018 Free Software Foundation, Inc. 3*38fd1498Szrj 4*38fd1498Szrj This file is part of GCC. 5*38fd1498Szrj 6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under 7*38fd1498Szrj the terms of the GNU General Public License as published by the Free 8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later 9*38fd1498Szrj version. 10*38fd1498Szrj 11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or 13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14*38fd1498Szrj for more details. 15*38fd1498Szrj 16*38fd1498Szrj You should have received a copy of the GNU General Public License 17*38fd1498Szrj along with GCC; see the file COPYING3. If not see 18*38fd1498Szrj <http://www.gnu.org/licenses/>. */ 19*38fd1498Szrj 20*38fd1498Szrj #include "config.h" 21*38fd1498Szrj #include "system.h" 22*38fd1498Szrj #include "coretypes.h" 23*38fd1498Szrj #include "backend.h" 24*38fd1498Szrj #include "rtl.h" 25*38fd1498Szrj #include "tree.h" 26*38fd1498Szrj #include "predict.h" 27*38fd1498Szrj #include "df.h" 28*38fd1498Szrj #include "memmodel.h" 29*38fd1498Szrj #include "tm_p.h" 30*38fd1498Szrj #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ 31*38fd1498Szrj #include "cfgrtl.h" 32*38fd1498Szrj #include "cfgbuild.h" 33*38fd1498Szrj #include "cfgcleanup.h" 34*38fd1498Szrj #include "dce.h" 35*38fd1498Szrj #include "valtrack.h" 36*38fd1498Szrj #include "tree-pass.h" 37*38fd1498Szrj #include "dbgcnt.h" 38*38fd1498Szrj 39*38fd1498Szrj 40*38fd1498Szrj /* ------------------------------------------------------------------------- 41*38fd1498Szrj Core mark/delete routines 42*38fd1498Szrj ------------------------------------------------------------------------- */ 43*38fd1498Szrj 44*38fd1498Szrj /* True if we are invoked while the df engine is running; in this case, 45*38fd1498Szrj we don't want to reenter it. */ 46*38fd1498Szrj static bool df_in_progress = false; 47*38fd1498Szrj 48*38fd1498Szrj /* True if we are allowed to alter the CFG in this pass. */ 49*38fd1498Szrj static bool can_alter_cfg = false; 50*38fd1498Szrj 51*38fd1498Szrj /* Instructions that have been marked but whose dependencies have not 52*38fd1498Szrj yet been processed. */ 53*38fd1498Szrj static vec<rtx_insn *> worklist; 54*38fd1498Szrj 55*38fd1498Szrj /* Bitmap of instructions marked as needed indexed by INSN_UID. */ 56*38fd1498Szrj static sbitmap marked; 57*38fd1498Szrj 58*38fd1498Szrj /* Bitmap obstacks used for block processing by the fast algorithm. */ 59*38fd1498Szrj static bitmap_obstack dce_blocks_bitmap_obstack; 60*38fd1498Szrj static bitmap_obstack dce_tmp_bitmap_obstack; 61*38fd1498Szrj 62*38fd1498Szrj static bool find_call_stack_args (rtx_call_insn *, bool, bool, bitmap); 63*38fd1498Szrj 64*38fd1498Szrj /* A subroutine for which BODY is part of the instruction being tested; 65*38fd1498Szrj either the top-level pattern, or an element of a PARALLEL. The 66*38fd1498Szrj instruction is known not to be a bare USE or CLOBBER. */ 67*38fd1498Szrj 68*38fd1498Szrj static bool 69*38fd1498Szrj deletable_insn_p_1 (rtx body) 70*38fd1498Szrj { 71*38fd1498Szrj switch (GET_CODE (body)) 72*38fd1498Szrj { 73*38fd1498Szrj case PREFETCH: 74*38fd1498Szrj case TRAP_IF: 75*38fd1498Szrj /* The UNSPEC case was added here because the ia-64 claims that 76*38fd1498Szrj USEs do not work after reload and generates UNSPECS rather 77*38fd1498Szrj than USEs. Since dce is run after reload we need to avoid 78*38fd1498Szrj deleting these even if they are dead. If it turns out that 79*38fd1498Szrj USEs really do work after reload, the ia-64 should be 80*38fd1498Szrj changed, and the UNSPEC case can be removed. */ 81*38fd1498Szrj case UNSPEC: 82*38fd1498Szrj return false; 83*38fd1498Szrj 84*38fd1498Szrj default: 85*38fd1498Szrj return !volatile_refs_p (body); 86*38fd1498Szrj } 87*38fd1498Szrj } 88*38fd1498Szrj 89*38fd1498Szrj 90*38fd1498Szrj /* Return true if INSN is a normal instruction that can be deleted by 91*38fd1498Szrj the DCE pass. */ 92*38fd1498Szrj 93*38fd1498Szrj static bool 94*38fd1498Szrj deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores) 95*38fd1498Szrj { 96*38fd1498Szrj rtx body, x; 97*38fd1498Szrj int i; 98*38fd1498Szrj df_ref def; 99*38fd1498Szrj 100*38fd1498Szrj if (CALL_P (insn) 101*38fd1498Szrj /* We cannot delete calls inside of the recursive dce because 102*38fd1498Szrj this may cause basic blocks to be deleted and this messes up 103*38fd1498Szrj the rest of the stack of optimization passes. */ 104*38fd1498Szrj && (!df_in_progress) 105*38fd1498Szrj /* We cannot delete pure or const sibling calls because it is 106*38fd1498Szrj hard to see the result. */ 107*38fd1498Szrj && (!SIBLING_CALL_P (insn)) 108*38fd1498Szrj /* We can delete dead const or pure calls as long as they do not 109*38fd1498Szrj infinite loop. */ 110*38fd1498Szrj && (RTL_CONST_OR_PURE_CALL_P (insn) 111*38fd1498Szrj && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) 112*38fd1498Szrj return find_call_stack_args (as_a <rtx_call_insn *> (insn), false, 113*38fd1498Szrj fast, arg_stores); 114*38fd1498Szrj 115*38fd1498Szrj /* Don't delete jumps, notes and the like. */ 116*38fd1498Szrj if (!NONJUMP_INSN_P (insn)) 117*38fd1498Szrj return false; 118*38fd1498Szrj 119*38fd1498Szrj /* Don't delete insns that may throw if we cannot do so. */ 120*38fd1498Szrj if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) 121*38fd1498Szrj && !insn_nothrow_p (insn)) 122*38fd1498Szrj return false; 123*38fd1498Szrj 124*38fd1498Szrj /* If INSN sets a global_reg, leave it untouched. */ 125*38fd1498Szrj FOR_EACH_INSN_DEF (def, insn) 126*38fd1498Szrj if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def)) 127*38fd1498Szrj && global_regs[DF_REF_REGNO (def)]) 128*38fd1498Szrj return false; 129*38fd1498Szrj /* Initialization of pseudo PIC register should never be removed. */ 130*38fd1498Szrj else if (DF_REF_REG (def) == pic_offset_table_rtx 131*38fd1498Szrj && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) 132*38fd1498Szrj return false; 133*38fd1498Szrj 134*38fd1498Szrj /* Callee-save restores are needed. */ 135*38fd1498Szrj if (RTX_FRAME_RELATED_P (insn) 136*38fd1498Szrj && crtl->shrink_wrapped_separate 137*38fd1498Szrj && find_reg_note (insn, REG_CFA_RESTORE, NULL)) 138*38fd1498Szrj return false; 139*38fd1498Szrj 140*38fd1498Szrj body = PATTERN (insn); 141*38fd1498Szrj switch (GET_CODE (body)) 142*38fd1498Szrj { 143*38fd1498Szrj case USE: 144*38fd1498Szrj case VAR_LOCATION: 145*38fd1498Szrj return false; 146*38fd1498Szrj 147*38fd1498Szrj case CLOBBER: 148*38fd1498Szrj if (fast) 149*38fd1498Szrj { 150*38fd1498Szrj /* A CLOBBER of a dead pseudo register serves no purpose. 151*38fd1498Szrj That is not necessarily true for hard registers until 152*38fd1498Szrj after reload. */ 153*38fd1498Szrj x = XEXP (body, 0); 154*38fd1498Szrj return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed); 155*38fd1498Szrj } 156*38fd1498Szrj else 157*38fd1498Szrj /* Because of the way that use-def chains are built, it is not 158*38fd1498Szrj possible to tell if the clobber is dead because it can 159*38fd1498Szrj never be the target of a use-def chain. */ 160*38fd1498Szrj return false; 161*38fd1498Szrj 162*38fd1498Szrj case PARALLEL: 163*38fd1498Szrj for (i = XVECLEN (body, 0) - 1; i >= 0; i--) 164*38fd1498Szrj if (!deletable_insn_p_1 (XVECEXP (body, 0, i))) 165*38fd1498Szrj return false; 166*38fd1498Szrj return true; 167*38fd1498Szrj 168*38fd1498Szrj default: 169*38fd1498Szrj return deletable_insn_p_1 (body); 170*38fd1498Szrj } 171*38fd1498Szrj } 172*38fd1498Szrj 173*38fd1498Szrj 174*38fd1498Szrj /* Return true if INSN has been marked as needed. */ 175*38fd1498Szrj 176*38fd1498Szrj static inline int 177*38fd1498Szrj marked_insn_p (rtx_insn *insn) 178*38fd1498Szrj { 179*38fd1498Szrj /* Artificial defs are always needed and they do not have an insn. 180*38fd1498Szrj We should never see them here. */ 181*38fd1498Szrj gcc_assert (insn); 182*38fd1498Szrj return bitmap_bit_p (marked, INSN_UID (insn)); 183*38fd1498Szrj } 184*38fd1498Szrj 185*38fd1498Szrj 186*38fd1498Szrj /* If INSN has not yet been marked as needed, mark it now, and add it to 187*38fd1498Szrj the worklist. */ 188*38fd1498Szrj 189*38fd1498Szrj static void 190*38fd1498Szrj mark_insn (rtx_insn *insn, bool fast) 191*38fd1498Szrj { 192*38fd1498Szrj if (!marked_insn_p (insn)) 193*38fd1498Szrj { 194*38fd1498Szrj if (!fast) 195*38fd1498Szrj worklist.safe_push (insn); 196*38fd1498Szrj bitmap_set_bit (marked, INSN_UID (insn)); 197*38fd1498Szrj if (dump_file) 198*38fd1498Szrj fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn)); 199*38fd1498Szrj if (CALL_P (insn) 200*38fd1498Szrj && !df_in_progress 201*38fd1498Szrj && !SIBLING_CALL_P (insn) 202*38fd1498Szrj && (RTL_CONST_OR_PURE_CALL_P (insn) 203*38fd1498Szrj && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) 204*38fd1498Szrj find_call_stack_args (as_a <rtx_call_insn *> (insn), true, fast, NULL); 205*38fd1498Szrj } 206*38fd1498Szrj } 207*38fd1498Szrj 208*38fd1498Szrj 209*38fd1498Szrj /* A note_stores callback used by mark_nonreg_stores. DATA is the 210*38fd1498Szrj instruction containing DEST. */ 211*38fd1498Szrj 212*38fd1498Szrj static void 213*38fd1498Szrj mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data) 214*38fd1498Szrj { 215*38fd1498Szrj if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) 216*38fd1498Szrj mark_insn ((rtx_insn *) data, true); 217*38fd1498Szrj } 218*38fd1498Szrj 219*38fd1498Szrj 220*38fd1498Szrj /* A note_stores callback used by mark_nonreg_stores. DATA is the 221*38fd1498Szrj instruction containing DEST. */ 222*38fd1498Szrj 223*38fd1498Szrj static void 224*38fd1498Szrj mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data) 225*38fd1498Szrj { 226*38fd1498Szrj if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) 227*38fd1498Szrj mark_insn ((rtx_insn *) data, false); 228*38fd1498Szrj } 229*38fd1498Szrj 230*38fd1498Szrj 231*38fd1498Szrj /* Mark INSN if BODY stores to a non-register destination. */ 232*38fd1498Szrj 233*38fd1498Szrj static void 234*38fd1498Szrj mark_nonreg_stores (rtx body, rtx_insn *insn, bool fast) 235*38fd1498Szrj { 236*38fd1498Szrj if (fast) 237*38fd1498Szrj note_stores (body, mark_nonreg_stores_1, insn); 238*38fd1498Szrj else 239*38fd1498Szrj note_stores (body, mark_nonreg_stores_2, insn); 240*38fd1498Szrj } 241*38fd1498Szrj 242*38fd1498Szrj 243*38fd1498Szrj /* Return true if a store to SIZE bytes, starting OFF bytes from stack pointer, 244*38fd1498Szrj is a call argument store, and clear corresponding bits from SP_BYTES 245*38fd1498Szrj bitmap if it is. */ 246*38fd1498Szrj 247*38fd1498Szrj static bool 248*38fd1498Szrj check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off, 249*38fd1498Szrj HOST_WIDE_INT min_sp_off, HOST_WIDE_INT max_sp_off, 250*38fd1498Szrj bitmap sp_bytes) 251*38fd1498Szrj { 252*38fd1498Szrj HOST_WIDE_INT byte; 253*38fd1498Szrj for (byte = off; byte < off + size; byte++) 254*38fd1498Szrj { 255*38fd1498Szrj if (byte < min_sp_off 256*38fd1498Szrj || byte >= max_sp_off 257*38fd1498Szrj || !bitmap_clear_bit (sp_bytes, byte - min_sp_off)) 258*38fd1498Szrj return false; 259*38fd1498Szrj } 260*38fd1498Szrj return true; 261*38fd1498Szrj } 262*38fd1498Szrj 263*38fd1498Szrj 264*38fd1498Szrj /* Try to find all stack stores of CALL_INSN arguments if 265*38fd1498Szrj ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found 266*38fd1498Szrj and it is therefore safe to eliminate the call, return true, 267*38fd1498Szrj otherwise return false. This function should be first called 268*38fd1498Szrj with DO_MARK false, and only when the CALL_INSN is actually 269*38fd1498Szrj going to be marked called again with DO_MARK true. */ 270*38fd1498Szrj 271*38fd1498Szrj static bool 272*38fd1498Szrj find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, 273*38fd1498Szrj bitmap arg_stores) 274*38fd1498Szrj { 275*38fd1498Szrj rtx p; 276*38fd1498Szrj rtx_insn *insn, *prev_insn; 277*38fd1498Szrj bool ret; 278*38fd1498Szrj HOST_WIDE_INT min_sp_off, max_sp_off; 279*38fd1498Szrj bitmap sp_bytes; 280*38fd1498Szrj 281*38fd1498Szrj gcc_assert (CALL_P (call_insn)); 282*38fd1498Szrj if (!ACCUMULATE_OUTGOING_ARGS) 283*38fd1498Szrj return true; 284*38fd1498Szrj 285*38fd1498Szrj if (!do_mark) 286*38fd1498Szrj { 287*38fd1498Szrj gcc_assert (arg_stores); 288*38fd1498Szrj bitmap_clear (arg_stores); 289*38fd1498Szrj } 290*38fd1498Szrj 291*38fd1498Szrj min_sp_off = INTTYPE_MAXIMUM (HOST_WIDE_INT); 292*38fd1498Szrj max_sp_off = 0; 293*38fd1498Szrj 294*38fd1498Szrj /* First determine the minimum and maximum offset from sp for 295*38fd1498Szrj stored arguments. */ 296*38fd1498Szrj for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1)) 297*38fd1498Szrj if (GET_CODE (XEXP (p, 0)) == USE 298*38fd1498Szrj && MEM_P (XEXP (XEXP (p, 0), 0))) 299*38fd1498Szrj { 300*38fd1498Szrj rtx mem = XEXP (XEXP (p, 0), 0), addr; 301*38fd1498Szrj HOST_WIDE_INT off = 0, size; 302*38fd1498Szrj if (!MEM_SIZE_KNOWN_P (mem) || !MEM_SIZE (mem).is_constant (&size)) 303*38fd1498Szrj return false; 304*38fd1498Szrj addr = XEXP (mem, 0); 305*38fd1498Szrj if (GET_CODE (addr) == PLUS 306*38fd1498Szrj && REG_P (XEXP (addr, 0)) 307*38fd1498Szrj && CONST_INT_P (XEXP (addr, 1))) 308*38fd1498Szrj { 309*38fd1498Szrj off = INTVAL (XEXP (addr, 1)); 310*38fd1498Szrj addr = XEXP (addr, 0); 311*38fd1498Szrj } 312*38fd1498Szrj if (addr != stack_pointer_rtx) 313*38fd1498Szrj { 314*38fd1498Szrj if (!REG_P (addr)) 315*38fd1498Szrj return false; 316*38fd1498Szrj /* If not fast, use chains to see if addr wasn't set to 317*38fd1498Szrj sp + offset. */ 318*38fd1498Szrj if (!fast) 319*38fd1498Szrj { 320*38fd1498Szrj df_ref use; 321*38fd1498Szrj struct df_link *defs; 322*38fd1498Szrj rtx set; 323*38fd1498Szrj 324*38fd1498Szrj FOR_EACH_INSN_USE (use, call_insn) 325*38fd1498Szrj if (rtx_equal_p (addr, DF_REF_REG (use))) 326*38fd1498Szrj break; 327*38fd1498Szrj 328*38fd1498Szrj if (use == NULL) 329*38fd1498Szrj return false; 330*38fd1498Szrj 331*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 332*38fd1498Szrj if (! DF_REF_IS_ARTIFICIAL (defs->ref)) 333*38fd1498Szrj break; 334*38fd1498Szrj 335*38fd1498Szrj if (defs == NULL) 336*38fd1498Szrj return false; 337*38fd1498Szrj 338*38fd1498Szrj set = single_set (DF_REF_INSN (defs->ref)); 339*38fd1498Szrj if (!set) 340*38fd1498Szrj return false; 341*38fd1498Szrj 342*38fd1498Szrj if (GET_CODE (SET_SRC (set)) != PLUS 343*38fd1498Szrj || XEXP (SET_SRC (set), 0) != stack_pointer_rtx 344*38fd1498Szrj || !CONST_INT_P (XEXP (SET_SRC (set), 1))) 345*38fd1498Szrj return false; 346*38fd1498Szrj 347*38fd1498Szrj off += INTVAL (XEXP (SET_SRC (set), 1)); 348*38fd1498Szrj } 349*38fd1498Szrj else 350*38fd1498Szrj return false; 351*38fd1498Szrj } 352*38fd1498Szrj min_sp_off = MIN (min_sp_off, off); 353*38fd1498Szrj max_sp_off = MAX (max_sp_off, off + size); 354*38fd1498Szrj } 355*38fd1498Szrj 356*38fd1498Szrj if (min_sp_off >= max_sp_off) 357*38fd1498Szrj return true; 358*38fd1498Szrj sp_bytes = BITMAP_ALLOC (NULL); 359*38fd1498Szrj 360*38fd1498Szrj /* Set bits in SP_BYTES bitmap for bytes relative to sp + min_sp_off 361*38fd1498Szrj which contain arguments. Checking has been done in the previous 362*38fd1498Szrj loop. */ 363*38fd1498Szrj for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1)) 364*38fd1498Szrj if (GET_CODE (XEXP (p, 0)) == USE 365*38fd1498Szrj && MEM_P (XEXP (XEXP (p, 0), 0))) 366*38fd1498Szrj { 367*38fd1498Szrj rtx mem = XEXP (XEXP (p, 0), 0), addr; 368*38fd1498Szrj HOST_WIDE_INT off = 0, byte, size; 369*38fd1498Szrj /* Checked in the previous iteration. */ 370*38fd1498Szrj size = MEM_SIZE (mem).to_constant (); 371*38fd1498Szrj addr = XEXP (mem, 0); 372*38fd1498Szrj if (GET_CODE (addr) == PLUS 373*38fd1498Szrj && REG_P (XEXP (addr, 0)) 374*38fd1498Szrj && CONST_INT_P (XEXP (addr, 1))) 375*38fd1498Szrj { 376*38fd1498Szrj off = INTVAL (XEXP (addr, 1)); 377*38fd1498Szrj addr = XEXP (addr, 0); 378*38fd1498Szrj } 379*38fd1498Szrj if (addr != stack_pointer_rtx) 380*38fd1498Szrj { 381*38fd1498Szrj df_ref use; 382*38fd1498Szrj struct df_link *defs; 383*38fd1498Szrj rtx set; 384*38fd1498Szrj 385*38fd1498Szrj FOR_EACH_INSN_USE (use, call_insn) 386*38fd1498Szrj if (rtx_equal_p (addr, DF_REF_REG (use))) 387*38fd1498Szrj break; 388*38fd1498Szrj 389*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 390*38fd1498Szrj if (! DF_REF_IS_ARTIFICIAL (defs->ref)) 391*38fd1498Szrj break; 392*38fd1498Szrj 393*38fd1498Szrj set = single_set (DF_REF_INSN (defs->ref)); 394*38fd1498Szrj off += INTVAL (XEXP (SET_SRC (set), 1)); 395*38fd1498Szrj } 396*38fd1498Szrj for (byte = off; byte < off + size; byte++) 397*38fd1498Szrj { 398*38fd1498Szrj if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) 399*38fd1498Szrj gcc_unreachable (); 400*38fd1498Szrj } 401*38fd1498Szrj } 402*38fd1498Szrj 403*38fd1498Szrj /* Walk backwards, looking for argument stores. The search stops 404*38fd1498Szrj when seeing another call, sp adjustment or memory store other than 405*38fd1498Szrj argument store. */ 406*38fd1498Szrj ret = false; 407*38fd1498Szrj for (insn = PREV_INSN (call_insn); insn; insn = prev_insn) 408*38fd1498Szrj { 409*38fd1498Szrj rtx set, mem, addr; 410*38fd1498Szrj HOST_WIDE_INT off; 411*38fd1498Szrj 412*38fd1498Szrj if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn))) 413*38fd1498Szrj prev_insn = NULL; 414*38fd1498Szrj else 415*38fd1498Szrj prev_insn = PREV_INSN (insn); 416*38fd1498Szrj 417*38fd1498Szrj if (CALL_P (insn)) 418*38fd1498Szrj break; 419*38fd1498Szrj 420*38fd1498Szrj if (!NONDEBUG_INSN_P (insn)) 421*38fd1498Szrj continue; 422*38fd1498Szrj 423*38fd1498Szrj set = single_set (insn); 424*38fd1498Szrj if (!set || SET_DEST (set) == stack_pointer_rtx) 425*38fd1498Szrj break; 426*38fd1498Szrj 427*38fd1498Szrj if (!MEM_P (SET_DEST (set))) 428*38fd1498Szrj continue; 429*38fd1498Szrj 430*38fd1498Szrj mem = SET_DEST (set); 431*38fd1498Szrj addr = XEXP (mem, 0); 432*38fd1498Szrj off = 0; 433*38fd1498Szrj if (GET_CODE (addr) == PLUS 434*38fd1498Szrj && REG_P (XEXP (addr, 0)) 435*38fd1498Szrj && CONST_INT_P (XEXP (addr, 1))) 436*38fd1498Szrj { 437*38fd1498Szrj off = INTVAL (XEXP (addr, 1)); 438*38fd1498Szrj addr = XEXP (addr, 0); 439*38fd1498Szrj } 440*38fd1498Szrj if (addr != stack_pointer_rtx) 441*38fd1498Szrj { 442*38fd1498Szrj if (!REG_P (addr)) 443*38fd1498Szrj break; 444*38fd1498Szrj if (!fast) 445*38fd1498Szrj { 446*38fd1498Szrj df_ref use; 447*38fd1498Szrj struct df_link *defs; 448*38fd1498Szrj rtx set; 449*38fd1498Szrj 450*38fd1498Szrj FOR_EACH_INSN_USE (use, insn) 451*38fd1498Szrj if (rtx_equal_p (addr, DF_REF_REG (use))) 452*38fd1498Szrj break; 453*38fd1498Szrj 454*38fd1498Szrj if (use == NULL) 455*38fd1498Szrj break; 456*38fd1498Szrj 457*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 458*38fd1498Szrj if (! DF_REF_IS_ARTIFICIAL (defs->ref)) 459*38fd1498Szrj break; 460*38fd1498Szrj 461*38fd1498Szrj if (defs == NULL) 462*38fd1498Szrj break; 463*38fd1498Szrj 464*38fd1498Szrj set = single_set (DF_REF_INSN (defs->ref)); 465*38fd1498Szrj if (!set) 466*38fd1498Szrj break; 467*38fd1498Szrj 468*38fd1498Szrj if (GET_CODE (SET_SRC (set)) != PLUS 469*38fd1498Szrj || XEXP (SET_SRC (set), 0) != stack_pointer_rtx 470*38fd1498Szrj || !CONST_INT_P (XEXP (SET_SRC (set), 1))) 471*38fd1498Szrj break; 472*38fd1498Szrj 473*38fd1498Szrj off += INTVAL (XEXP (SET_SRC (set), 1)); 474*38fd1498Szrj } 475*38fd1498Szrj else 476*38fd1498Szrj break; 477*38fd1498Szrj } 478*38fd1498Szrj 479*38fd1498Szrj HOST_WIDE_INT size; 480*38fd1498Szrj if (!MEM_SIZE_KNOWN_P (mem) 481*38fd1498Szrj || !MEM_SIZE (mem).is_constant (&size) 482*38fd1498Szrj || !check_argument_store (size, off, min_sp_off, 483*38fd1498Szrj max_sp_off, sp_bytes)) 484*38fd1498Szrj break; 485*38fd1498Szrj 486*38fd1498Szrj if (!deletable_insn_p (insn, fast, NULL)) 487*38fd1498Szrj break; 488*38fd1498Szrj 489*38fd1498Szrj if (do_mark) 490*38fd1498Szrj mark_insn (insn, fast); 491*38fd1498Szrj else 492*38fd1498Szrj bitmap_set_bit (arg_stores, INSN_UID (insn)); 493*38fd1498Szrj 494*38fd1498Szrj if (bitmap_empty_p (sp_bytes)) 495*38fd1498Szrj { 496*38fd1498Szrj ret = true; 497*38fd1498Szrj break; 498*38fd1498Szrj } 499*38fd1498Szrj } 500*38fd1498Szrj 501*38fd1498Szrj BITMAP_FREE (sp_bytes); 502*38fd1498Szrj if (!ret && arg_stores) 503*38fd1498Szrj bitmap_clear (arg_stores); 504*38fd1498Szrj 505*38fd1498Szrj return ret; 506*38fd1498Szrj } 507*38fd1498Szrj 508*38fd1498Szrj 509*38fd1498Szrj /* Remove all REG_EQUAL and REG_EQUIV notes referring to the registers INSN 510*38fd1498Szrj writes to. */ 511*38fd1498Szrj 512*38fd1498Szrj static void 513*38fd1498Szrj remove_reg_equal_equiv_notes_for_defs (rtx_insn *insn) 514*38fd1498Szrj { 515*38fd1498Szrj df_ref def; 516*38fd1498Szrj 517*38fd1498Szrj FOR_EACH_INSN_DEF (def, insn) 518*38fd1498Szrj remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (def)); 519*38fd1498Szrj } 520*38fd1498Szrj 521*38fd1498Szrj /* Scan all BBs for debug insns and reset those that reference values 522*38fd1498Szrj defined in unmarked insns. */ 523*38fd1498Szrj 524*38fd1498Szrj static void 525*38fd1498Szrj reset_unmarked_insns_debug_uses (void) 526*38fd1498Szrj { 527*38fd1498Szrj basic_block bb; 528*38fd1498Szrj rtx_insn *insn, *next; 529*38fd1498Szrj 530*38fd1498Szrj FOR_EACH_BB_REVERSE_FN (bb, cfun) 531*38fd1498Szrj FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) 532*38fd1498Szrj if (DEBUG_INSN_P (insn)) 533*38fd1498Szrj { 534*38fd1498Szrj df_ref use; 535*38fd1498Szrj 536*38fd1498Szrj FOR_EACH_INSN_USE (use, insn) 537*38fd1498Szrj { 538*38fd1498Szrj struct df_link *defs; 539*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 540*38fd1498Szrj { 541*38fd1498Szrj rtx_insn *ref_insn; 542*38fd1498Szrj if (DF_REF_IS_ARTIFICIAL (defs->ref)) 543*38fd1498Szrj continue; 544*38fd1498Szrj ref_insn = DF_REF_INSN (defs->ref); 545*38fd1498Szrj if (!marked_insn_p (ref_insn)) 546*38fd1498Szrj break; 547*38fd1498Szrj } 548*38fd1498Szrj if (!defs) 549*38fd1498Szrj continue; 550*38fd1498Szrj /* ??? FIXME could we propagate the values assigned to 551*38fd1498Szrj each of the DEFs? */ 552*38fd1498Szrj INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); 553*38fd1498Szrj df_insn_rescan_debug_internal (insn); 554*38fd1498Szrj break; 555*38fd1498Szrj } 556*38fd1498Szrj } 557*38fd1498Szrj } 558*38fd1498Szrj 559*38fd1498Szrj /* Delete every instruction that hasn't been marked. */ 560*38fd1498Szrj 561*38fd1498Szrj static void 562*38fd1498Szrj delete_unmarked_insns (void) 563*38fd1498Szrj { 564*38fd1498Szrj basic_block bb; 565*38fd1498Szrj rtx_insn *insn, *next; 566*38fd1498Szrj bool must_clean = false; 567*38fd1498Szrj 568*38fd1498Szrj FOR_EACH_BB_REVERSE_FN (bb, cfun) 569*38fd1498Szrj FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) 570*38fd1498Szrj if (NONDEBUG_INSN_P (insn)) 571*38fd1498Szrj { 572*38fd1498Szrj rtx turn_into_use = NULL_RTX; 573*38fd1498Szrj 574*38fd1498Szrj /* Always delete no-op moves. */ 575*38fd1498Szrj if (noop_move_p (insn)) 576*38fd1498Szrj { 577*38fd1498Szrj if (RTX_FRAME_RELATED_P (insn)) 578*38fd1498Szrj turn_into_use 579*38fd1498Szrj = find_reg_note (insn, REG_CFA_RESTORE, NULL); 580*38fd1498Szrj if (turn_into_use && REG_P (XEXP (turn_into_use, 0))) 581*38fd1498Szrj turn_into_use = XEXP (turn_into_use, 0); 582*38fd1498Szrj else 583*38fd1498Szrj turn_into_use = NULL_RTX; 584*38fd1498Szrj } 585*38fd1498Szrj 586*38fd1498Szrj /* Otherwise rely only on the DCE algorithm. */ 587*38fd1498Szrj else if (marked_insn_p (insn)) 588*38fd1498Szrj continue; 589*38fd1498Szrj 590*38fd1498Szrj /* Beware that reaching a dbg counter limit here can result 591*38fd1498Szrj in miscompiled file. This occurs when a group of insns 592*38fd1498Szrj must be deleted together, typically because the kept insn 593*38fd1498Szrj depends on the output from the deleted insn. Deleting 594*38fd1498Szrj this insns in reverse order (both at the bb level and 595*38fd1498Szrj when looking at the blocks) minimizes this, but does not 596*38fd1498Szrj eliminate it, since it is possible for the using insn to 597*38fd1498Szrj be top of a block and the producer to be at the bottom of 598*38fd1498Szrj the block. However, in most cases this will only result 599*38fd1498Szrj in an uninitialized use of an insn that is dead anyway. 600*38fd1498Szrj 601*38fd1498Szrj However, there is one rare case that will cause a 602*38fd1498Szrj miscompile: deletion of non-looping pure and constant 603*38fd1498Szrj calls on a machine where ACCUMULATE_OUTGOING_ARGS is true. 604*38fd1498Szrj In this case it is possible to remove the call, but leave 605*38fd1498Szrj the argument pushes to the stack. Because of the changes 606*38fd1498Szrj to the stack pointer, this will almost always lead to a 607*38fd1498Szrj miscompile. */ 608*38fd1498Szrj if (!dbg_cnt (dce)) 609*38fd1498Szrj continue; 610*38fd1498Szrj 611*38fd1498Szrj if (dump_file) 612*38fd1498Szrj fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); 613*38fd1498Szrj 614*38fd1498Szrj /* Before we delete the insn we have to remove the REG_EQUAL notes 615*38fd1498Szrj for the destination regs in order to avoid dangling notes. */ 616*38fd1498Szrj remove_reg_equal_equiv_notes_for_defs (insn); 617*38fd1498Szrj 618*38fd1498Szrj /* If a pure or const call is deleted, this may make the cfg 619*38fd1498Szrj have unreachable blocks. We rememeber this and call 620*38fd1498Szrj delete_unreachable_blocks at the end. */ 621*38fd1498Szrj if (CALL_P (insn)) 622*38fd1498Szrj must_clean = true; 623*38fd1498Szrj 624*38fd1498Szrj if (turn_into_use) 625*38fd1498Szrj { 626*38fd1498Szrj /* Don't remove frame related noop moves if they cary 627*38fd1498Szrj REG_CFA_RESTORE note, while we don't need to emit any code, 628*38fd1498Szrj we need it to emit the CFI restore note. */ 629*38fd1498Szrj PATTERN (insn) 630*38fd1498Szrj = gen_rtx_USE (GET_MODE (turn_into_use), turn_into_use); 631*38fd1498Szrj INSN_CODE (insn) = -1; 632*38fd1498Szrj df_insn_rescan (insn); 633*38fd1498Szrj } 634*38fd1498Szrj else 635*38fd1498Szrj /* Now delete the insn. */ 636*38fd1498Szrj delete_insn_and_edges (insn); 637*38fd1498Szrj } 638*38fd1498Szrj 639*38fd1498Szrj /* Deleted a pure or const call. */ 640*38fd1498Szrj if (must_clean) 641*38fd1498Szrj delete_unreachable_blocks (); 642*38fd1498Szrj } 643*38fd1498Szrj 644*38fd1498Szrj 645*38fd1498Szrj /* Go through the instructions and mark those whose necessity is not 646*38fd1498Szrj dependent on inter-instruction information. Make sure all other 647*38fd1498Szrj instructions are not marked. */ 648*38fd1498Szrj 649*38fd1498Szrj static void 650*38fd1498Szrj prescan_insns_for_dce (bool fast) 651*38fd1498Szrj { 652*38fd1498Szrj basic_block bb; 653*38fd1498Szrj rtx_insn *insn, *prev; 654*38fd1498Szrj bitmap arg_stores = NULL; 655*38fd1498Szrj 656*38fd1498Szrj if (dump_file) 657*38fd1498Szrj fprintf (dump_file, "Finding needed instructions:\n"); 658*38fd1498Szrj 659*38fd1498Szrj if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS) 660*38fd1498Szrj arg_stores = BITMAP_ALLOC (NULL); 661*38fd1498Szrj 662*38fd1498Szrj FOR_EACH_BB_FN (bb, cfun) 663*38fd1498Szrj { 664*38fd1498Szrj FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) 665*38fd1498Szrj if (NONDEBUG_INSN_P (insn)) 666*38fd1498Szrj { 667*38fd1498Szrj /* Don't mark argument stores now. They will be marked 668*38fd1498Szrj if needed when the associated CALL is marked. */ 669*38fd1498Szrj if (arg_stores && bitmap_bit_p (arg_stores, INSN_UID (insn))) 670*38fd1498Szrj continue; 671*38fd1498Szrj if (deletable_insn_p (insn, fast, arg_stores)) 672*38fd1498Szrj mark_nonreg_stores (PATTERN (insn), insn, fast); 673*38fd1498Szrj else 674*38fd1498Szrj mark_insn (insn, fast); 675*38fd1498Szrj } 676*38fd1498Szrj /* find_call_stack_args only looks at argument stores in the 677*38fd1498Szrj same bb. */ 678*38fd1498Szrj if (arg_stores) 679*38fd1498Szrj bitmap_clear (arg_stores); 680*38fd1498Szrj } 681*38fd1498Szrj 682*38fd1498Szrj if (arg_stores) 683*38fd1498Szrj BITMAP_FREE (arg_stores); 684*38fd1498Szrj 685*38fd1498Szrj if (dump_file) 686*38fd1498Szrj fprintf (dump_file, "Finished finding needed instructions:\n"); 687*38fd1498Szrj } 688*38fd1498Szrj 689*38fd1498Szrj 690*38fd1498Szrj /* UD-based DSE routines. */ 691*38fd1498Szrj 692*38fd1498Szrj /* Mark instructions that define artificially-used registers, such as 693*38fd1498Szrj the frame pointer and the stack pointer. */ 694*38fd1498Szrj 695*38fd1498Szrj static void 696*38fd1498Szrj mark_artificial_uses (void) 697*38fd1498Szrj { 698*38fd1498Szrj basic_block bb; 699*38fd1498Szrj struct df_link *defs; 700*38fd1498Szrj df_ref use; 701*38fd1498Szrj 702*38fd1498Szrj FOR_ALL_BB_FN (bb, cfun) 703*38fd1498Szrj FOR_EACH_ARTIFICIAL_USE (use, bb->index) 704*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 705*38fd1498Szrj if (!DF_REF_IS_ARTIFICIAL (defs->ref)) 706*38fd1498Szrj mark_insn (DF_REF_INSN (defs->ref), false); 707*38fd1498Szrj } 708*38fd1498Szrj 709*38fd1498Szrj 710*38fd1498Szrj /* Mark every instruction that defines a register value that INSN uses. */ 711*38fd1498Szrj 712*38fd1498Szrj static void 713*38fd1498Szrj mark_reg_dependencies (rtx_insn *insn) 714*38fd1498Szrj { 715*38fd1498Szrj struct df_link *defs; 716*38fd1498Szrj df_ref use; 717*38fd1498Szrj 718*38fd1498Szrj if (DEBUG_INSN_P (insn)) 719*38fd1498Szrj return; 720*38fd1498Szrj 721*38fd1498Szrj FOR_EACH_INSN_USE (use, insn) 722*38fd1498Szrj { 723*38fd1498Szrj if (dump_file) 724*38fd1498Szrj { 725*38fd1498Szrj fprintf (dump_file, "Processing use of "); 726*38fd1498Szrj print_simple_rtl (dump_file, DF_REF_REG (use)); 727*38fd1498Szrj fprintf (dump_file, " in insn %d:\n", INSN_UID (insn)); 728*38fd1498Szrj } 729*38fd1498Szrj for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) 730*38fd1498Szrj if (! DF_REF_IS_ARTIFICIAL (defs->ref)) 731*38fd1498Szrj mark_insn (DF_REF_INSN (defs->ref), false); 732*38fd1498Szrj } 733*38fd1498Szrj } 734*38fd1498Szrj 735*38fd1498Szrj 736*38fd1498Szrj /* Initialize global variables for a new DCE pass. */ 737*38fd1498Szrj 738*38fd1498Szrj static void 739*38fd1498Szrj init_dce (bool fast) 740*38fd1498Szrj { 741*38fd1498Szrj if (!df_in_progress) 742*38fd1498Szrj { 743*38fd1498Szrj if (!fast) 744*38fd1498Szrj { 745*38fd1498Szrj df_set_flags (DF_RD_PRUNE_DEAD_DEFS); 746*38fd1498Szrj df_chain_add_problem (DF_UD_CHAIN); 747*38fd1498Szrj } 748*38fd1498Szrj df_analyze (); 749*38fd1498Szrj } 750*38fd1498Szrj 751*38fd1498Szrj if (dump_file) 752*38fd1498Szrj df_dump (dump_file); 753*38fd1498Szrj 754*38fd1498Szrj if (fast) 755*38fd1498Szrj { 756*38fd1498Szrj bitmap_obstack_initialize (&dce_blocks_bitmap_obstack); 757*38fd1498Szrj bitmap_obstack_initialize (&dce_tmp_bitmap_obstack); 758*38fd1498Szrj can_alter_cfg = false; 759*38fd1498Szrj } 760*38fd1498Szrj else 761*38fd1498Szrj can_alter_cfg = true; 762*38fd1498Szrj 763*38fd1498Szrj marked = sbitmap_alloc (get_max_uid () + 1); 764*38fd1498Szrj bitmap_clear (marked); 765*38fd1498Szrj } 766*38fd1498Szrj 767*38fd1498Szrj 768*38fd1498Szrj /* Free the data allocated by init_dce. */ 769*38fd1498Szrj 770*38fd1498Szrj static void 771*38fd1498Szrj fini_dce (bool fast) 772*38fd1498Szrj { 773*38fd1498Szrj sbitmap_free (marked); 774*38fd1498Szrj 775*38fd1498Szrj if (fast) 776*38fd1498Szrj { 777*38fd1498Szrj bitmap_obstack_release (&dce_blocks_bitmap_obstack); 778*38fd1498Szrj bitmap_obstack_release (&dce_tmp_bitmap_obstack); 779*38fd1498Szrj } 780*38fd1498Szrj } 781*38fd1498Szrj 782*38fd1498Szrj 783*38fd1498Szrj /* UD-chain based DCE. */ 784*38fd1498Szrj 785*38fd1498Szrj static unsigned int 786*38fd1498Szrj rest_of_handle_ud_dce (void) 787*38fd1498Szrj { 788*38fd1498Szrj rtx_insn *insn; 789*38fd1498Szrj 790*38fd1498Szrj init_dce (false); 791*38fd1498Szrj 792*38fd1498Szrj prescan_insns_for_dce (false); 793*38fd1498Szrj mark_artificial_uses (); 794*38fd1498Szrj while (worklist.length () > 0) 795*38fd1498Szrj { 796*38fd1498Szrj insn = worklist.pop (); 797*38fd1498Szrj mark_reg_dependencies (insn); 798*38fd1498Szrj } 799*38fd1498Szrj worklist.release (); 800*38fd1498Szrj 801*38fd1498Szrj if (MAY_HAVE_DEBUG_BIND_INSNS) 802*38fd1498Szrj reset_unmarked_insns_debug_uses (); 803*38fd1498Szrj 804*38fd1498Szrj /* Before any insns are deleted, we must remove the chains since 805*38fd1498Szrj they are not bidirectional. */ 806*38fd1498Szrj df_remove_problem (df_chain); 807*38fd1498Szrj delete_unmarked_insns (); 808*38fd1498Szrj 809*38fd1498Szrj fini_dce (false); 810*38fd1498Szrj return 0; 811*38fd1498Szrj } 812*38fd1498Szrj 813*38fd1498Szrj 814*38fd1498Szrj namespace { 815*38fd1498Szrj 816*38fd1498Szrj const pass_data pass_data_ud_rtl_dce = 817*38fd1498Szrj { 818*38fd1498Szrj RTL_PASS, /* type */ 819*38fd1498Szrj "ud_dce", /* name */ 820*38fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */ 821*38fd1498Szrj TV_DCE, /* tv_id */ 822*38fd1498Szrj 0, /* properties_required */ 823*38fd1498Szrj 0, /* properties_provided */ 824*38fd1498Szrj 0, /* properties_destroyed */ 825*38fd1498Szrj 0, /* todo_flags_start */ 826*38fd1498Szrj TODO_df_finish, /* todo_flags_finish */ 827*38fd1498Szrj }; 828*38fd1498Szrj 829*38fd1498Szrj class pass_ud_rtl_dce : public rtl_opt_pass 830*38fd1498Szrj { 831*38fd1498Szrj public: 832*38fd1498Szrj pass_ud_rtl_dce (gcc::context *ctxt) 833*38fd1498Szrj : rtl_opt_pass (pass_data_ud_rtl_dce, ctxt) 834*38fd1498Szrj {} 835*38fd1498Szrj 836*38fd1498Szrj /* opt_pass methods: */ 837*38fd1498Szrj virtual bool gate (function *) 838*38fd1498Szrj { 839*38fd1498Szrj return optimize > 1 && flag_dce && dbg_cnt (dce_ud); 840*38fd1498Szrj } 841*38fd1498Szrj 842*38fd1498Szrj virtual unsigned int execute (function *) 843*38fd1498Szrj { 844*38fd1498Szrj return rest_of_handle_ud_dce (); 845*38fd1498Szrj } 846*38fd1498Szrj 847*38fd1498Szrj }; // class pass_ud_rtl_dce 848*38fd1498Szrj 849*38fd1498Szrj } // anon namespace 850*38fd1498Szrj 851*38fd1498Szrj rtl_opt_pass * 852*38fd1498Szrj make_pass_ud_rtl_dce (gcc::context *ctxt) 853*38fd1498Szrj { 854*38fd1498Szrj return new pass_ud_rtl_dce (ctxt); 855*38fd1498Szrj } 856*38fd1498Szrj 857*38fd1498Szrj 858*38fd1498Szrj /* ------------------------------------------------------------------------- 859*38fd1498Szrj Fast DCE functions 860*38fd1498Szrj ------------------------------------------------------------------------- */ 861*38fd1498Szrj 862*38fd1498Szrj /* Process basic block BB. Return true if the live_in set has 863*38fd1498Szrj changed. REDO_OUT is true if the info at the bottom of the block 864*38fd1498Szrj needs to be recalculated before starting. AU is the proper set of 865*38fd1498Szrj artificial uses. Track global substitution of uses of dead pseudos 866*38fd1498Szrj in debug insns using GLOBAL_DEBUG. */ 867*38fd1498Szrj 868*38fd1498Szrj static bool 869*38fd1498Szrj word_dce_process_block (basic_block bb, bool redo_out, 870*38fd1498Szrj struct dead_debug_global *global_debug) 871*38fd1498Szrj { 872*38fd1498Szrj bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); 873*38fd1498Szrj rtx_insn *insn; 874*38fd1498Szrj bool block_changed; 875*38fd1498Szrj struct dead_debug_local debug; 876*38fd1498Szrj 877*38fd1498Szrj if (redo_out) 878*38fd1498Szrj { 879*38fd1498Szrj /* Need to redo the live_out set of this block if when one of 880*38fd1498Szrj the succs of this block has had a change in it live in 881*38fd1498Szrj set. */ 882*38fd1498Szrj edge e; 883*38fd1498Szrj edge_iterator ei; 884*38fd1498Szrj df_confluence_function_n con_fun_n = df_word_lr->problem->con_fun_n; 885*38fd1498Szrj bitmap_clear (DF_WORD_LR_OUT (bb)); 886*38fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs) 887*38fd1498Szrj (*con_fun_n) (e); 888*38fd1498Szrj } 889*38fd1498Szrj 890*38fd1498Szrj if (dump_file) 891*38fd1498Szrj { 892*38fd1498Szrj fprintf (dump_file, "processing block %d live out = ", bb->index); 893*38fd1498Szrj df_print_word_regset (dump_file, DF_WORD_LR_OUT (bb)); 894*38fd1498Szrj } 895*38fd1498Szrj 896*38fd1498Szrj bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); 897*38fd1498Szrj dead_debug_local_init (&debug, NULL, global_debug); 898*38fd1498Szrj 899*38fd1498Szrj FOR_BB_INSNS_REVERSE (bb, insn) 900*38fd1498Szrj if (DEBUG_INSN_P (insn)) 901*38fd1498Szrj { 902*38fd1498Szrj df_ref use; 903*38fd1498Szrj FOR_EACH_INSN_USE (use, insn) 904*38fd1498Szrj if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER 905*38fd1498Szrj && known_eq (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (use))), 906*38fd1498Szrj 2 * UNITS_PER_WORD) 907*38fd1498Szrj && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use)) 908*38fd1498Szrj && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use) + 1)) 909*38fd1498Szrj dead_debug_add (&debug, use, DF_REF_REGNO (use)); 910*38fd1498Szrj } 911*38fd1498Szrj else if (INSN_P (insn)) 912*38fd1498Szrj { 913*38fd1498Szrj bool any_changed; 914*38fd1498Szrj 915*38fd1498Szrj /* No matter if the instruction is needed or not, we remove 916*38fd1498Szrj any regno in the defs from the live set. */ 917*38fd1498Szrj any_changed = df_word_lr_simulate_defs (insn, local_live); 918*38fd1498Szrj if (any_changed) 919*38fd1498Szrj mark_insn (insn, true); 920*38fd1498Szrj 921*38fd1498Szrj /* On the other hand, we do not allow the dead uses to set 922*38fd1498Szrj anything in local_live. */ 923*38fd1498Szrj if (marked_insn_p (insn)) 924*38fd1498Szrj df_word_lr_simulate_uses (insn, local_live); 925*38fd1498Szrj 926*38fd1498Szrj /* Insert debug temps for dead REGs used in subsequent debug 927*38fd1498Szrj insns. We may have to emit a debug temp even if the insn 928*38fd1498Szrj was marked, in case the debug use was after the point of 929*38fd1498Szrj death. */ 930*38fd1498Szrj if (debug.used && !bitmap_empty_p (debug.used)) 931*38fd1498Szrj { 932*38fd1498Szrj df_ref def; 933*38fd1498Szrj 934*38fd1498Szrj FOR_EACH_INSN_DEF (def, insn) 935*38fd1498Szrj dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, 936*38fd1498Szrj marked_insn_p (insn) 937*38fd1498Szrj && !control_flow_insn_p (insn) 938*38fd1498Szrj ? DEBUG_TEMP_AFTER_WITH_REG_FORCE 939*38fd1498Szrj : DEBUG_TEMP_BEFORE_WITH_VALUE); 940*38fd1498Szrj } 941*38fd1498Szrj 942*38fd1498Szrj if (dump_file) 943*38fd1498Szrj { 944*38fd1498Szrj fprintf (dump_file, "finished processing insn %d live out = ", 945*38fd1498Szrj INSN_UID (insn)); 946*38fd1498Szrj df_print_word_regset (dump_file, local_live); 947*38fd1498Szrj } 948*38fd1498Szrj } 949*38fd1498Szrj 950*38fd1498Szrj block_changed = !bitmap_equal_p (local_live, DF_WORD_LR_IN (bb)); 951*38fd1498Szrj if (block_changed) 952*38fd1498Szrj bitmap_copy (DF_WORD_LR_IN (bb), local_live); 953*38fd1498Szrj 954*38fd1498Szrj dead_debug_local_finish (&debug, NULL); 955*38fd1498Szrj BITMAP_FREE (local_live); 956*38fd1498Szrj return block_changed; 957*38fd1498Szrj } 958*38fd1498Szrj 959*38fd1498Szrj 960*38fd1498Szrj /* Process basic block BB. Return true if the live_in set has 961*38fd1498Szrj changed. REDO_OUT is true if the info at the bottom of the block 962*38fd1498Szrj needs to be recalculated before starting. AU is the proper set of 963*38fd1498Szrj artificial uses. Track global substitution of uses of dead pseudos 964*38fd1498Szrj in debug insns using GLOBAL_DEBUG. */ 965*38fd1498Szrj 966*38fd1498Szrj static bool 967*38fd1498Szrj dce_process_block (basic_block bb, bool redo_out, bitmap au, 968*38fd1498Szrj struct dead_debug_global *global_debug) 969*38fd1498Szrj { 970*38fd1498Szrj bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); 971*38fd1498Szrj rtx_insn *insn; 972*38fd1498Szrj bool block_changed; 973*38fd1498Szrj df_ref def; 974*38fd1498Szrj struct dead_debug_local debug; 975*38fd1498Szrj 976*38fd1498Szrj if (redo_out) 977*38fd1498Szrj { 978*38fd1498Szrj /* Need to redo the live_out set of this block if when one of 979*38fd1498Szrj the succs of this block has had a change in it live in 980*38fd1498Szrj set. */ 981*38fd1498Szrj edge e; 982*38fd1498Szrj edge_iterator ei; 983*38fd1498Szrj df_confluence_function_n con_fun_n = df_lr->problem->con_fun_n; 984*38fd1498Szrj bitmap_clear (DF_LR_OUT (bb)); 985*38fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs) 986*38fd1498Szrj (*con_fun_n) (e); 987*38fd1498Szrj } 988*38fd1498Szrj 989*38fd1498Szrj if (dump_file) 990*38fd1498Szrj { 991*38fd1498Szrj fprintf (dump_file, "processing block %d lr out = ", bb->index); 992*38fd1498Szrj df_print_regset (dump_file, DF_LR_OUT (bb)); 993*38fd1498Szrj } 994*38fd1498Szrj 995*38fd1498Szrj bitmap_copy (local_live, DF_LR_OUT (bb)); 996*38fd1498Szrj 997*38fd1498Szrj df_simulate_initialize_backwards (bb, local_live); 998*38fd1498Szrj dead_debug_local_init (&debug, NULL, global_debug); 999*38fd1498Szrj 1000*38fd1498Szrj FOR_BB_INSNS_REVERSE (bb, insn) 1001*38fd1498Szrj if (DEBUG_INSN_P (insn)) 1002*38fd1498Szrj { 1003*38fd1498Szrj df_ref use; 1004*38fd1498Szrj FOR_EACH_INSN_USE (use, insn) 1005*38fd1498Szrj if (!bitmap_bit_p (local_live, DF_REF_REGNO (use)) 1006*38fd1498Szrj && !bitmap_bit_p (au, DF_REF_REGNO (use))) 1007*38fd1498Szrj dead_debug_add (&debug, use, DF_REF_REGNO (use)); 1008*38fd1498Szrj } 1009*38fd1498Szrj else if (INSN_P (insn)) 1010*38fd1498Szrj { 1011*38fd1498Szrj bool needed = marked_insn_p (insn); 1012*38fd1498Szrj 1013*38fd1498Szrj /* The insn is needed if there is someone who uses the output. */ 1014*38fd1498Szrj if (!needed) 1015*38fd1498Szrj FOR_EACH_INSN_DEF (def, insn) 1016*38fd1498Szrj if (bitmap_bit_p (local_live, DF_REF_REGNO (def)) 1017*38fd1498Szrj || bitmap_bit_p (au, DF_REF_REGNO (def))) 1018*38fd1498Szrj { 1019*38fd1498Szrj needed = true; 1020*38fd1498Szrj mark_insn (insn, true); 1021*38fd1498Szrj break; 1022*38fd1498Szrj } 1023*38fd1498Szrj 1024*38fd1498Szrj /* No matter if the instruction is needed or not, we remove 1025*38fd1498Szrj any regno in the defs from the live set. */ 1026*38fd1498Szrj df_simulate_defs (insn, local_live); 1027*38fd1498Szrj 1028*38fd1498Szrj /* On the other hand, we do not allow the dead uses to set 1029*38fd1498Szrj anything in local_live. */ 1030*38fd1498Szrj if (needed) 1031*38fd1498Szrj df_simulate_uses (insn, local_live); 1032*38fd1498Szrj 1033*38fd1498Szrj /* Insert debug temps for dead REGs used in subsequent debug 1034*38fd1498Szrj insns. We may have to emit a debug temp even if the insn 1035*38fd1498Szrj was marked, in case the debug use was after the point of 1036*38fd1498Szrj death. */ 1037*38fd1498Szrj if (debug.used && !bitmap_empty_p (debug.used)) 1038*38fd1498Szrj FOR_EACH_INSN_DEF (def, insn) 1039*38fd1498Szrj dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, 1040*38fd1498Szrj needed && !control_flow_insn_p (insn) 1041*38fd1498Szrj ? DEBUG_TEMP_AFTER_WITH_REG_FORCE 1042*38fd1498Szrj : DEBUG_TEMP_BEFORE_WITH_VALUE); 1043*38fd1498Szrj } 1044*38fd1498Szrj 1045*38fd1498Szrj dead_debug_local_finish (&debug, NULL); 1046*38fd1498Szrj df_simulate_finalize_backwards (bb, local_live); 1047*38fd1498Szrj 1048*38fd1498Szrj block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb)); 1049*38fd1498Szrj if (block_changed) 1050*38fd1498Szrj bitmap_copy (DF_LR_IN (bb), local_live); 1051*38fd1498Szrj 1052*38fd1498Szrj BITMAP_FREE (local_live); 1053*38fd1498Szrj return block_changed; 1054*38fd1498Szrj } 1055*38fd1498Szrj 1056*38fd1498Szrj 1057*38fd1498Szrj /* Perform fast DCE once initialization is done. If WORD_LEVEL is 1058*38fd1498Szrj true, use the word level dce, otherwise do it at the pseudo 1059*38fd1498Szrj level. */ 1060*38fd1498Szrj 1061*38fd1498Szrj static void 1062*38fd1498Szrj fast_dce (bool word_level) 1063*38fd1498Szrj { 1064*38fd1498Szrj int *postorder = df_get_postorder (DF_BACKWARD); 1065*38fd1498Szrj int n_blocks = df_get_n_blocks (DF_BACKWARD); 1066*38fd1498Szrj /* The set of blocks that have been seen on this iteration. */ 1067*38fd1498Szrj bitmap processed = BITMAP_ALLOC (&dce_blocks_bitmap_obstack); 1068*38fd1498Szrj /* The set of blocks that need to have the out vectors reset because 1069*38fd1498Szrj the in of one of their successors has changed. */ 1070*38fd1498Szrj bitmap redo_out = BITMAP_ALLOC (&dce_blocks_bitmap_obstack); 1071*38fd1498Szrj bitmap all_blocks = BITMAP_ALLOC (&dce_blocks_bitmap_obstack); 1072*38fd1498Szrj bool global_changed = true; 1073*38fd1498Szrj 1074*38fd1498Szrj /* These regs are considered always live so if they end up dying 1075*38fd1498Szrj because of some def, we need to bring the back again. Calling 1076*38fd1498Szrj df_simulate_fixup_sets has the disadvantage of calling 1077*38fd1498Szrj bb_has_eh_pred once per insn, so we cache the information 1078*38fd1498Szrj here. */ 1079*38fd1498Szrj bitmap au = &df->regular_block_artificial_uses; 1080*38fd1498Szrj bitmap au_eh = &df->eh_block_artificial_uses; 1081*38fd1498Szrj int i; 1082*38fd1498Szrj struct dead_debug_global global_debug; 1083*38fd1498Szrj 1084*38fd1498Szrj prescan_insns_for_dce (true); 1085*38fd1498Szrj 1086*38fd1498Szrj for (i = 0; i < n_blocks; i++) 1087*38fd1498Szrj bitmap_set_bit (all_blocks, postorder[i]); 1088*38fd1498Szrj 1089*38fd1498Szrj dead_debug_global_init (&global_debug, NULL); 1090*38fd1498Szrj 1091*38fd1498Szrj while (global_changed) 1092*38fd1498Szrj { 1093*38fd1498Szrj global_changed = false; 1094*38fd1498Szrj 1095*38fd1498Szrj for (i = 0; i < n_blocks; i++) 1096*38fd1498Szrj { 1097*38fd1498Szrj int index = postorder[i]; 1098*38fd1498Szrj basic_block bb = BASIC_BLOCK_FOR_FN (cfun, index); 1099*38fd1498Szrj bool local_changed; 1100*38fd1498Szrj 1101*38fd1498Szrj if (index < NUM_FIXED_BLOCKS) 1102*38fd1498Szrj { 1103*38fd1498Szrj bitmap_set_bit (processed, index); 1104*38fd1498Szrj continue; 1105*38fd1498Szrj } 1106*38fd1498Szrj 1107*38fd1498Szrj if (word_level) 1108*38fd1498Szrj local_changed 1109*38fd1498Szrj = word_dce_process_block (bb, bitmap_bit_p (redo_out, index), 1110*38fd1498Szrj &global_debug); 1111*38fd1498Szrj else 1112*38fd1498Szrj local_changed 1113*38fd1498Szrj = dce_process_block (bb, bitmap_bit_p (redo_out, index), 1114*38fd1498Szrj bb_has_eh_pred (bb) ? au_eh : au, 1115*38fd1498Szrj &global_debug); 1116*38fd1498Szrj bitmap_set_bit (processed, index); 1117*38fd1498Szrj 1118*38fd1498Szrj if (local_changed) 1119*38fd1498Szrj { 1120*38fd1498Szrj edge e; 1121*38fd1498Szrj edge_iterator ei; 1122*38fd1498Szrj FOR_EACH_EDGE (e, ei, bb->preds) 1123*38fd1498Szrj if (bitmap_bit_p (processed, e->src->index)) 1124*38fd1498Szrj /* Be tricky about when we need to iterate the 1125*38fd1498Szrj analysis. We only have redo the analysis if the 1126*38fd1498Szrj bitmaps change at the top of a block that is the 1127*38fd1498Szrj entry to a loop. */ 1128*38fd1498Szrj global_changed = true; 1129*38fd1498Szrj else 1130*38fd1498Szrj bitmap_set_bit (redo_out, e->src->index); 1131*38fd1498Szrj } 1132*38fd1498Szrj } 1133*38fd1498Szrj 1134*38fd1498Szrj if (global_changed) 1135*38fd1498Szrj { 1136*38fd1498Szrj /* Turn off the RUN_DCE flag to prevent recursive calls to 1137*38fd1498Szrj dce. */ 1138*38fd1498Szrj int old_flag = df_clear_flags (DF_LR_RUN_DCE); 1139*38fd1498Szrj 1140*38fd1498Szrj /* So something was deleted that requires a redo. Do it on 1141*38fd1498Szrj the cheap. */ 1142*38fd1498Szrj delete_unmarked_insns (); 1143*38fd1498Szrj bitmap_clear (marked); 1144*38fd1498Szrj bitmap_clear (processed); 1145*38fd1498Szrj bitmap_clear (redo_out); 1146*38fd1498Szrj 1147*38fd1498Szrj /* We do not need to rescan any instructions. We only need 1148*38fd1498Szrj to redo the dataflow equations for the blocks that had a 1149*38fd1498Szrj change at the top of the block. Then we need to redo the 1150*38fd1498Szrj iteration. */ 1151*38fd1498Szrj if (word_level) 1152*38fd1498Szrj df_analyze_problem (df_word_lr, all_blocks, postorder, n_blocks); 1153*38fd1498Szrj else 1154*38fd1498Szrj df_analyze_problem (df_lr, all_blocks, postorder, n_blocks); 1155*38fd1498Szrj 1156*38fd1498Szrj if (old_flag & DF_LR_RUN_DCE) 1157*38fd1498Szrj df_set_flags (DF_LR_RUN_DCE); 1158*38fd1498Szrj 1159*38fd1498Szrj prescan_insns_for_dce (true); 1160*38fd1498Szrj } 1161*38fd1498Szrj } 1162*38fd1498Szrj 1163*38fd1498Szrj dead_debug_global_finish (&global_debug, NULL); 1164*38fd1498Szrj 1165*38fd1498Szrj delete_unmarked_insns (); 1166*38fd1498Szrj 1167*38fd1498Szrj BITMAP_FREE (processed); 1168*38fd1498Szrj BITMAP_FREE (redo_out); 1169*38fd1498Szrj BITMAP_FREE (all_blocks); 1170*38fd1498Szrj } 1171*38fd1498Szrj 1172*38fd1498Szrj 1173*38fd1498Szrj /* Fast register level DCE. */ 1174*38fd1498Szrj 1175*38fd1498Szrj static unsigned int 1176*38fd1498Szrj rest_of_handle_fast_dce (void) 1177*38fd1498Szrj { 1178*38fd1498Szrj init_dce (true); 1179*38fd1498Szrj fast_dce (false); 1180*38fd1498Szrj fini_dce (true); 1181*38fd1498Szrj return 0; 1182*38fd1498Szrj } 1183*38fd1498Szrj 1184*38fd1498Szrj 1185*38fd1498Szrj /* Fast byte level DCE. */ 1186*38fd1498Szrj 1187*38fd1498Szrj void 1188*38fd1498Szrj run_word_dce (void) 1189*38fd1498Szrj { 1190*38fd1498Szrj int old_flags; 1191*38fd1498Szrj 1192*38fd1498Szrj if (!flag_dce) 1193*38fd1498Szrj return; 1194*38fd1498Szrj 1195*38fd1498Szrj timevar_push (TV_DCE); 1196*38fd1498Szrj old_flags = df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN); 1197*38fd1498Szrj df_word_lr_add_problem (); 1198*38fd1498Szrj init_dce (true); 1199*38fd1498Szrj fast_dce (true); 1200*38fd1498Szrj fini_dce (true); 1201*38fd1498Szrj df_set_flags (old_flags); 1202*38fd1498Szrj timevar_pop (TV_DCE); 1203*38fd1498Szrj } 1204*38fd1498Szrj 1205*38fd1498Szrj 1206*38fd1498Szrj /* This is an internal call that is used by the df live register 1207*38fd1498Szrj problem to run fast dce as a side effect of creating the live 1208*38fd1498Szrj information. The stack is organized so that the lr problem is run, 1209*38fd1498Szrj this pass is run, which updates the live info and the df scanning 1210*38fd1498Szrj info, and then returns to allow the rest of the problems to be run. 1211*38fd1498Szrj 1212*38fd1498Szrj This can be called by elsewhere but it will not update the bit 1213*38fd1498Szrj vectors for any other problems than LR. */ 1214*38fd1498Szrj 1215*38fd1498Szrj void 1216*38fd1498Szrj run_fast_df_dce (void) 1217*38fd1498Szrj { 1218*38fd1498Szrj if (flag_dce) 1219*38fd1498Szrj { 1220*38fd1498Szrj /* If dce is able to delete something, it has to happen 1221*38fd1498Szrj immediately. Otherwise there will be problems handling the 1222*38fd1498Szrj eq_notes. */ 1223*38fd1498Szrj int old_flags = 1224*38fd1498Szrj df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN); 1225*38fd1498Szrj 1226*38fd1498Szrj df_in_progress = true; 1227*38fd1498Szrj rest_of_handle_fast_dce (); 1228*38fd1498Szrj df_in_progress = false; 1229*38fd1498Szrj 1230*38fd1498Szrj df_set_flags (old_flags); 1231*38fd1498Szrj } 1232*38fd1498Szrj } 1233*38fd1498Szrj 1234*38fd1498Szrj 1235*38fd1498Szrj /* Run a fast DCE pass. */ 1236*38fd1498Szrj 1237*38fd1498Szrj void 1238*38fd1498Szrj run_fast_dce (void) 1239*38fd1498Szrj { 1240*38fd1498Szrj if (flag_dce) 1241*38fd1498Szrj rest_of_handle_fast_dce (); 1242*38fd1498Szrj } 1243*38fd1498Szrj 1244*38fd1498Szrj 1245*38fd1498Szrj namespace { 1246*38fd1498Szrj 1247*38fd1498Szrj const pass_data pass_data_fast_rtl_dce = 1248*38fd1498Szrj { 1249*38fd1498Szrj RTL_PASS, /* type */ 1250*38fd1498Szrj "rtl_dce", /* name */ 1251*38fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */ 1252*38fd1498Szrj TV_DCE, /* tv_id */ 1253*38fd1498Szrj 0, /* properties_required */ 1254*38fd1498Szrj 0, /* properties_provided */ 1255*38fd1498Szrj 0, /* properties_destroyed */ 1256*38fd1498Szrj 0, /* todo_flags_start */ 1257*38fd1498Szrj TODO_df_finish, /* todo_flags_finish */ 1258*38fd1498Szrj }; 1259*38fd1498Szrj 1260*38fd1498Szrj class pass_fast_rtl_dce : public rtl_opt_pass 1261*38fd1498Szrj { 1262*38fd1498Szrj public: 1263*38fd1498Szrj pass_fast_rtl_dce (gcc::context *ctxt) 1264*38fd1498Szrj : rtl_opt_pass (pass_data_fast_rtl_dce, ctxt) 1265*38fd1498Szrj {} 1266*38fd1498Szrj 1267*38fd1498Szrj /* opt_pass methods: */ 1268*38fd1498Szrj virtual bool gate (function *) 1269*38fd1498Szrj { 1270*38fd1498Szrj return optimize > 0 && flag_dce && dbg_cnt (dce_fast); 1271*38fd1498Szrj } 1272*38fd1498Szrj 1273*38fd1498Szrj virtual unsigned int execute (function *) 1274*38fd1498Szrj { 1275*38fd1498Szrj return rest_of_handle_fast_dce (); 1276*38fd1498Szrj } 1277*38fd1498Szrj 1278*38fd1498Szrj }; // class pass_fast_rtl_dce 1279*38fd1498Szrj 1280*38fd1498Szrj } // anon namespace 1281*38fd1498Szrj 1282*38fd1498Szrj rtl_opt_pass * 1283*38fd1498Szrj make_pass_fast_rtl_dce (gcc::context *ctxt) 1284*38fd1498Szrj { 1285*38fd1498Szrj return new pass_fast_rtl_dce (ctxt); 1286*38fd1498Szrj } 1287