aboutsummaryrefslogtreecommitdiff
path: root/gcc/cse.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2005-03-14 20:06:23 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2005-03-14 20:06:23 +0000
commit3a3b81e73f2f4b05740199db410f8b37df46be4f (patch)
tree1c5ac4147db728d1db8cce06fbd59ea041cbd2c0 /gcc/cse.c
parentaff98faf417c338db54204046c684b91d9788e55 (diff)
downloadgcc-3a3b81e73f2f4b05740199db410f8b37df46be4f.zip
gcc-3a3b81e73f2f4b05740199db410f8b37df46be4f.tar.gz
gcc-3a3b81e73f2f4b05740199db410f8b37df46be4f.tar.bz2
re PR rtl-optimization/18628 (miscompilation of switch statement in loop)
gcc/ChangeLog: PR middle-end/18628 * cse.c (fold_rtx_mem): Don't fold a load from a jumptable into a register. gcc/testsuite/ChangeLog: * gcc.dg/pr18628.c: New. From-SVN: r96445
Diffstat (limited to 'gcc/cse.c')
-rw-r--r--gcc/cse.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/gcc/cse.c b/gcc/cse.c
index d7f3027..fd5e21a 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3515,8 +3515,30 @@ fold_rtx_mem (rtx x, rtx insn)
if (offset >= 0
&& (offset / GET_MODE_SIZE (GET_MODE (table))
< XVECLEN (table, 0)))
- return XVECEXP (table, 0,
- offset / GET_MODE_SIZE (GET_MODE (table)));
+ {
+ rtx label = XVECEXP
+ (table, 0, offset / GET_MODE_SIZE (GET_MODE (table)));
+ rtx set;
+
+ /* If we have an insn that loads the label from the
+ jumptable into a reg, we don't want to set the reg
+ to the label, because this may cause a reference to
+ the label to remain after the label is removed in
+ some very obscure cases (PR middle-end/18628). */
+ if (!insn)
+ return label;
+
+ set = single_set (insn);
+
+ if (! set || SET_SRC (set) != x)
+ return x;
+
+ /* If it's a jump, it's safe to reference the label. */
+ if (SET_DEST (set) == pc_rtx)
+ return label;
+
+ return x;
+ }
}
if (table_insn && JUMP_P (table_insn)
&& GET_CODE (PATTERN (table_insn)) == ADDR_DIFF_VEC)