diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-08-06 19:02:38 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-08-06 19:02:38 +0000 |
commit | a989c63acfb40c604b49a3d315a54942a63393f3 (patch) | |
tree | f40f0819acaaa0b2f23e005e31be9588a252a989 /gnu | |
parent | c592bc6a277d522ad859380fd672f8ac084ea40c (diff) |
One major difference between gcc 2.95 and gcc 3, is that the latter comes
with an optimization pass which attemps to identify and remove dead stores.
Unfortunately, this logic assumes that a given rtl MEM reference can only
refer to register contents and values, but not further dereference memory.
This is not true of all addressing modes on vax, and this causes gcc 3 to
consider as dead stores everything which can be expressed as *offset(register)
in vax assembly. The canonical example of this is linked list insertion or
removal, with instructions such as "item->prev->next = item->next" being
wrongly optimized out, and cause double frees or other funny linking problems
later on.
Add a knob to disable the troublesome part of that optimization pass, and
only enable this knob on vax.
This gives a native vax gcc 3 compiler able to rebuild the world.
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/vax/vax.h | 9 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/flow.c | 60 |
2 files changed, 39 insertions, 30 deletions
diff --git a/gnu/usr.bin/gcc/gcc/config/vax/vax.h b/gnu/usr.bin/gcc/gcc/config/vax/vax.h index 47a0f034e69..8d36e2cc355 100644 --- a/gnu/usr.bin/gcc/gcc/config/vax/vax.h +++ b/gnu/usr.bin/gcc/gcc/config/vax/vax.h @@ -800,11 +800,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; Do not define this if the table should contain absolute addresses. */ #define CASE_VECTOR_PC_RELATIVE 1 -/* Define this if the case instruction drops through after the table - when the index is out of range. Don't define it if the case insn - jumps to the default label instead. */ -#define CASE_DROPS_THROUGH - /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ #define JUMP_TABLES_IN_TEXT_SECTION 1 @@ -1233,3 +1228,7 @@ VAX operand formatting codes: actually have any code whatsoever for which this isn't overridden by the proper FDE definition. */ #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, PC_REGNUM) + +/* Tell flow.c not to try and optimize away MEM dead stores, as its + logic is confused by some of the addressing modes of the VAX. */ +#define FLOW_DEAD_STORES_BROKEN_P diff --git a/gnu/usr.bin/gcc/gcc/flow.c b/gnu/usr.bin/gcc/gcc/flow.c index 7882b25ae9a..e902ff6b377 100644 --- a/gnu/usr.bin/gcc/gcc/flow.c +++ b/gnu/usr.bin/gcc/gcc/flow.c @@ -1,6 +1,6 @@ /* Data flow analysis for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -431,9 +431,8 @@ life_analysis (f, file, flags) SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM); #endif - #ifdef CANNOT_CHANGE_MODE_CLASS - bitmap_initialize (&subregs_of_mode, 1); + init_subregs_of_mode (); #endif if (! optimize) @@ -1799,8 +1798,9 @@ propagate_one_insn (pbi, insn) current_function_return_rtx, (rtx *) 0))) { + enum rtx_code code = global_regs[i] ? SET : CLOBBER; /* We do not want REG_UNUSED notes for these registers. */ - mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn, + mark_set_1 (pbi, code, regno_reg_rtx[i], cond, insn, pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO)); } } @@ -2292,14 +2292,22 @@ insn_dead_p (pbi, x, call_ok, notes) } /* A CLOBBER of a pseudo-register that is dead serves no purpose. That - is not necessarily true for hard registers. */ - else if (code == CLOBBER && GET_CODE (XEXP (x, 0)) == REG - && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER - && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0)))) - return 1; - - /* We do not check other CLOBBER or USE here. An insn consisting of just - a CLOBBER or just a USE should not be deleted. */ + is not necessarily true for hard registers until after reload. */ + else if (code == CLOBBER) + { + if (GET_CODE (XEXP (x, 0)) == REG + && (REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER + || reload_completed) + && ! REGNO_REG_SET_P (pbi->reg_live, REGNO (XEXP (x, 0)))) + return 1; + } + + /* ??? A base USE is a historical relic. It ought not be needed anymore. + Instances where it is still used are either (1) temporary and the USE + escaped the pass, (2) cruft and the USE need not be emitted anymore, + or (3) hiding bugs elsewhere that are not properly representing data + flow. */ + return 0; } @@ -2694,10 +2702,12 @@ mark_set_1 (pbi, code, reg, cond, insn, flags) if (insn && GET_CODE (reg) == MEM) for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi); +#ifndef FLOW_DEAD_STORES_BROKEN_P if (GET_CODE (reg) == MEM && ! side_effects_p (reg) /* ??? With more effort we could track conditional memory life. */ && ! cond) add_to_mem_set_list (pbi, canon_rtx (reg)); +#endif } if (GET_CODE (reg) == REG @@ -2813,10 +2823,18 @@ mark_set_1 (pbi, code, reg, cond, insn, flags) in ASM_OPERANDs. If these registers get replaced, we might wind up changing the semantics of the insn, even if reload can make what appear to be valid - assignments later. */ + assignments later. + + We don't build a LOG_LINK for global registers to + or from a function call. We don't want to let + combine think that it knows what is going on with + global registers. */ if (y && (BLOCK_NUM (y) == blocknum) && (regno_first >= FIRST_PSEUDO_REGISTER - || asm_noperands (PATTERN (y)) < 0)) + || (asm_noperands (PATTERN (y)) < 0 + && ! ((GET_CODE (insn) == CALL_INSN + || GET_CODE (y) == CALL_INSN) + && global_regs[regno_first])))) LOG_LINKS (y) = alloc_INSN_LIST (insn, LOG_LINKS (y)); } } @@ -3834,11 +3852,7 @@ mark_used_regs (pbi, x, cond, insn) case SUBREG: #ifdef CANNOT_CHANGE_MODE_CLASS - if (GET_CODE (SUBREG_REG (x)) == REG - && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x)) - * MAX_MACHINE_MODE - + GET_MODE (x)); + record_subregs_of_mode (x); #endif /* While we're here, optimize this case. */ @@ -3883,12 +3897,8 @@ mark_used_regs (pbi, x, cond, insn) || GET_CODE (testreg) == SUBREG) { #ifdef CANNOT_CHANGE_MODE_CLASS - if (GET_CODE (testreg) == SUBREG - && GET_CODE (SUBREG_REG (testreg)) == REG - && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg)) - * MAX_MACHINE_MODE - + GET_MODE (testreg)); + if (GET_CODE (testreg) == SUBREG) + record_subregs_of_mode (testreg); #endif /* Modifying a single register in an alternate mode |