From: aoliva Date: Mon, 14 Mar 2005 20:06:23 +0000 (+0000) Subject: gcc/ChangeLog: X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=3d2931b52bc6e77b35fac2cabaf7e5e91db63f9a;hp=03623d96836cf980f972e4ef8b9cb98aec14d4fd 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96445 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 910eb398c9f..1e0a0f48f74 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2005-03-14 Alexandre Oliva + PR middle-end/18628 + * cse.c (fold_rtx_mem): Don't fold a load from a jumptable into a + register. + +2005-03-14 Alexandre Oliva + PR c++/20280 * gimplify.c (gimplify_cond_expr): Add fallback argument. Use a temporary variable of pointer type if an lvalues is required. diff --git a/gcc/cse.c b/gcc/cse.c index d7f3027e2bb..fd5e21ac2ee 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e18492dbab..3053e823e8f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2005-03-14 Alexandre Oliva + * gcc.dg/pr18628.c: New. + +2005-03-14 Alexandre Oliva + PR c++/20280 * g++.dg/tree-ssa/pr20280.C: New. diff --git a/gcc/testsuite/gcc.dg/pr18628.c b/gcc/testsuite/gcc.dg/pr18628.c new file mode 100644 index 00000000000..d365075b729 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18628.c @@ -0,0 +1,31 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +/* PR middle-end/18628 exposed a problem in which cse folded a load + from a jump table into the label that was the target of the branch. + Unfortunately, the indirect jump was moved to a different basic + block, and the LABEL_REF copied to the register wasn't enough to + keep the cfg from optimizing the otherwise-unused label away. So + we ended up with a dangling reference to the label. */ + +int i; + +int main() +{ + for (;;) + { + switch (i) + { + case 0: + case 1: + return 1; + + case 2: + case 3: + return 0; + + case 5: + --i; + } + } +}