diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2005-03-14 20:06:23 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2005-03-14 20:06:23 +0000 |
commit | 3a3b81e73f2f4b05740199db410f8b37df46be4f (patch) | |
tree | 1c5ac4147db728d1db8cce06fbd59ea041cbd2c0 /gcc/cse.c | |
parent | aff98faf417c338db54204046c684b91d9788e55 (diff) | |
download | gcc-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.c | 26 |
1 files changed, 24 insertions, 2 deletions
@@ -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) |