diff options
Diffstat (limited to 'gcc/dce.c')
-rw-r--r-- | gcc/dce.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/gcc/dce.c b/gcc/dce.c index 7b2ffe92581..91cc9aa5c28 100644 --- a/gcc/dce.c +++ b/gcc/dce.c @@ -99,6 +99,20 @@ deletable_insn_p (rtx insn, bool fast) rtx body, x; int i; + if (CALL_P (insn) + /* We cannot delete calls inside of the recursive dce because + this may cause basic blocks to be deleted and this messes up + the rest of the stack of optimization passes. */ + && (!df_in_progress) + /* We cannot delete pure or const sibling calls because it is + hard to see the result. */ + && (!SIBLING_CALL_P (insn)) + /* We can delete dead const or pure calls as long as they do not + infinite loop. */ + && (RTL_CONST_OR_PURE_CALL_P (insn) + && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) + return true; + if (!NONJUMP_INSN_P (insn)) return false; @@ -296,6 +310,7 @@ delete_unmarked_insns (void) { basic_block bb; rtx insn, next; + bool must_clean = false; FOR_EACH_BB (bb) FOR_BB_INSNS_SAFE (bb, insn, next) @@ -373,9 +388,19 @@ delete_unmarked_insns (void) remove_note (XEXP (note, 0), libcall_note); } + /* If a pure or const call is deleted, this may make the cfg + have unreachable blocks. We rememeber this and call + delete_unreachable_blocks at the end. */ + if (CALL_P (insn)) + must_clean = true; + /* Now delete the insn. */ delete_insn_and_edges (insn); } + + /* Deleted a pure or const call. */ + if (must_clean) + delete_unreachable_blocks (); } |