diff options
Diffstat (limited to 'contrib/gcc/flow.c')
-rw-r--r-- | contrib/gcc/flow.c | 85 |
1 files changed, 66 insertions, 19 deletions
diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c index 315cb2d..09c1094 100644 --- a/contrib/gcc/flow.c +++ b/contrib/gcc/flow.c @@ -167,6 +167,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #ifndef EPILOGUE_USES #define EPILOGUE_USES(REGNO) 0 #endif +#ifndef EH_USES +#define EH_USES(REGNO) 0 +#endif #ifdef HAVE_conditional_execution #ifndef REVERSE_CONDEXEC_PREDICATES_P @@ -633,6 +636,7 @@ update_life_info (blocks, extent, prop_flags) regset tmp; regset_head tmp_head; int i; + int stabilized_prop_flags = prop_flags; tmp = INITIALIZE_REG_SET (tmp_head); @@ -676,8 +680,21 @@ update_life_info (blocks, extent, prop_flags) | PROP_KILL_DEAD_CODE)); } - if (! changed || ! cleanup_cfg (CLEANUP_EXPENSIVE)) + /* Don't pass PROP_SCAN_DEAD_CODE or PROP_KILL_DEAD_CODE to + subsequent propagate_block calls, since removing or acting as + removing dead code can affect global register liveness, which + is supposed to be finalized for this call after this loop. */ + stabilized_prop_flags + &= ~(PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE); + + if (! changed) break; + + /* We repeat regardless of what cleanup_cfg says. If there were + instructions deleted above, that might have been only a + partial improvement (see MAX_MEM_SET_LIST_LEN usage). + Further improvement may be possible. */ + cleanup_cfg (CLEANUP_EXPENSIVE); } /* If asked, remove notes from the blocks we'll update. */ @@ -692,7 +709,7 @@ update_life_info (blocks, extent, prop_flags) basic_block bb = BASIC_BLOCK (i); COPY_REG_SET (tmp, bb->global_live_at_end); - propagate_block (bb, tmp, NULL, NULL, prop_flags); + propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags); if (extent == UPDATE_LIFE_LOCAL) verify_local_live_at_start (tmp, bb); @@ -705,7 +722,8 @@ update_life_info (blocks, extent, prop_flags) basic_block bb = BASIC_BLOCK (i); COPY_REG_SET (tmp, bb->global_live_at_end); - propagate_block (bb, tmp, NULL, NULL, prop_flags); + + propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags); if (extent == UPDATE_LIFE_LOCAL) verify_local_live_at_start (tmp, bb); @@ -1077,6 +1095,11 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) } } + /* We clean aux when we remove the initially-enqueued bbs, but we + don't enqueue ENTRY and EXIT initially, so clean them upfront and + unconditionally. */ + ENTRY_BLOCK_PTR->aux = EXIT_BLOCK_PTR->aux = NULL; + if (blocks_out) sbitmap_zero (blocks_out); @@ -1111,21 +1134,40 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) /* Begin by propagating live_at_start from the successor blocks. */ CLEAR_REG_SET (new_live_at_end); - for (e = bb->succ; e; e = e->succ_next) - { - basic_block sb = e->dest; - /* Call-clobbered registers die across exception and call edges. */ - /* ??? Abnormal call edges ignored for the moment, as this gets - confused by sibling call edges, which crashes reg-stack. */ - if (e->flags & EDGE_EH) - { - bitmap_operation (tmp, sb->global_live_at_start, - call_used, BITMAP_AND_COMPL); - IOR_REG_SET (new_live_at_end, tmp); - } - else - IOR_REG_SET (new_live_at_end, sb->global_live_at_start); + if (bb->succ) + for (e = bb->succ; e; e = e->succ_next) + { + basic_block sb = e->dest; + + /* Call-clobbered registers die across exception and + call edges. */ + /* ??? Abnormal call edges ignored for the moment, as this gets + confused by sibling call edges, which crashes reg-stack. */ + if (e->flags & EDGE_EH) + { + bitmap_operation (tmp, sb->global_live_at_start, + call_used, BITMAP_AND_COMPL); + IOR_REG_SET (new_live_at_end, tmp); + } + else + IOR_REG_SET (new_live_at_end, sb->global_live_at_start); + + /* If a target saves one register in another (instead of on + the stack) the save register will need to be live for EH. */ + if (e->flags & EDGE_EH) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (EH_USES (i)) + SET_REGNO_REG_SET (new_live_at_end, i); + } + else + { + /* This might be a noreturn function that throws. And + even if it isn't, getting the unwind info right helps + debugging. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (EH_USES (i)) + SET_REGNO_REG_SET (new_live_at_end, i); } /* The all-important stack pointer must always be live. */ @@ -3543,6 +3585,10 @@ mark_used_reg (pbi, reg, cond, insn) /* Mark the register as being live. */ for (i = regno_first; i <= regno_last; ++i) { +#ifdef HAVE_conditional_execution + int this_was_live = REGNO_REG_SET_P (pbi->reg_live, i); +#endif + SET_REGNO_REG_SET (pbi->reg_live, i); #ifdef HAVE_conditional_execution @@ -3554,7 +3600,7 @@ mark_used_reg (pbi, reg, cond, insn) struct reg_cond_life_info *rcli; rtx ncond; - if (some_was_live) + if (this_was_live) { node = splay_tree_lookup (pbi->reg_cond_dead, i); if (node == NULL) @@ -3596,7 +3642,7 @@ mark_used_reg (pbi, reg, cond, insn) SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); } } - else if (some_was_live) + else if (this_was_live) { /* The register may have been conditionally live previously, but is now unconditionally live. Remove it from the conditionally @@ -3635,6 +3681,7 @@ mark_used_regs (pbi, x, cond, insn) case CONST_INT: case CONST: case CONST_DOUBLE: + case CONST_VECTOR: case PC: case ADDR_VEC: case ADDR_DIFF_VEC: |