summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-12-01 22:54:03 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-12-01 22:54:03 +0000
commitb02dfe0ab7aae6700f0c15419373891118eab134 (patch)
tree535b6d29222cbe7e3bb3fe3d6f9637f31e93face /gnu
parenta06516e47e752c824b8c4c1a049b5e408d3ba696 (diff)
reload_cse_noop_set_p(): invoking rtx_equal_for_cselib_p() is not enough; if
it reports the dest and source parts of the set insn are identical, we need to check whether they are volatile memory references, and return 0 (not a noop) in that case. This allows `*volatile_ptr = *volatile_ptr;' constructs to no longer be incorrectly optimized away on platforms which can perform memory to memory transfers in a single instruction (i.e. m68k and vax). Found the hard way on vax, where some systems need to frob the interrupt stack early, before being able to handle faults, and a gcc3-built kernel would have this operation optimized away, leading to a quick system reset.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/gcc/gcc/reload1.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/gnu/usr.bin/gcc/gcc/reload1.c b/gnu/usr.bin/gcc/gcc/reload1.c
index 5f8102c8821..2cc4c3f7150 100644
--- a/gnu/usr.bin/gcc/gcc/reload1.c
+++ b/gnu/usr.bin/gcc/gcc/reload1.c
@@ -8059,7 +8059,19 @@ static int
reload_cse_noop_set_p (set)
rtx set;
{
- return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
+ rtx dest, src;
+
+ dest = SET_DEST (set);
+ src = SET_SRC (set);
+
+ if (! rtx_equal_for_cselib_p (dest, src))
+ return 0;
+
+ if ((GET_CODE (dest) == MEM && MEM_VOLATILE_P (dest))
+ || (GET_CODE (src) == MEM && MEM_VOLATILE_P (src)))
+ return 0;
+
+ return 1;
}
/* Try to simplify INSN. */