This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix crossjumping (PR middle-end/21492)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 11 May 2005 05:22:18 -0400
- Subject: [PATCH] Fix crossjumping (PR middle-end/21492)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The testcase below ICEs in crossjumping on ppc-linux (32-bit).
Here try_crossjump_to_edge crossjumps 2 times, the bb's in question are
(simplified):
B1:
(use (symbol_ref/f:SI ("*.LC1")))
(set (reg:SI 3 3) (reg/f:SI 29 29 [130])) // REG_EQUAL (symbol_ref/f:SI ("*.LC1"))
(call_insn FUN1)
fallthrough to B2 + EH edge to BEH
B2:
(use (symbol_ref/f:SI ("*.LC1")))
(set (reg:SI 3 3) (reg/f:SI 29 29 [130])) // REG_EQUAL (symbol_ref/f:SI ("*.LC1"))
(call_insn FUN2)
fallthrough to forwarder block to BDST + EH edge to BEH
---
B3:
(use (symbol_ref/f:SI ("*.LC3")))
(set (reg:SI 3 3) (reg/f:SI 29 29 [130])) // REG_EQUAL (symbol_ref/f:SI ("*.LC3"))
(call_insn FUN1)
fallthrough to B4 + EH edge to BEH
B4:
(use (symbol_ref/f:SI ("*.LC3")))
(set (reg:SI 3 3) (reg/f:SI 29 29 [130])) // REG_EQUAL (symbol_ref/f:SI ("*.LC3"))
(call_insn FUN2)
fallthrough to forwarder block to BDST + EH edge to BEH
As only last to insns in B2 and B4 are equal, try_crossjump_to_edge
calls split_block on both src2 and src1, but given that USE is not an active
instruction, both src1 and src2 become forwarder blocks.
try_crossjump_to_edge calls update_forwarder_flag on src1:
redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
...
update_forwarder_flag (redirect_from);
(just wondering why it uses a separate variable redirect_from, as
redirect_from must be == src1), but doesn't update it for the other
split:
redirect_to = split_block (src2, PREV_INSN (newpos2))->dest;
The next round it tries to crossjump B1 with B3 and ICEs in recomputation
of BB frequencies and counts, where it uses FORWARDER_BLOCK_P, which is
not set correctly for one of the destination BBs.
Ok for 4.0/HEAD, assuming bootstrap finishes and regtesting shows no
regressions?
2005-05-11 Jakub Jelinek <jakub@redhat.com>
PR middle-end/21492
* cfgcleanup.c (try_crossjump_to_edge): update_forwarder_flag for
src2 if src2 has been split.
* g++.dg/opt/crossjump1.C: New test.
--- gcc/cfgcleanup.c.jj 2005-02-17 20:02:57.000000000 +0100
+++ gcc/cfgcleanup.c 2005-05-11 10:49:22.000000000 +0200
@@ -1686,6 +1686,8 @@ try_crossjump_to_edge (int mode, edge e1
delete_basic_block (to_remove);
update_forwarder_flag (redirect_from);
+ if (redirect_to != src2)
+ update_forwarder_flag (src2);
return true;
}
--- gcc/testsuite/g++.dg/opt/crossjump1.C.jj 2005-04-07 15:51:53.775361896 +0200
+++ gcc/testsuite/g++.dg/opt/crossjump1.C 2005-05-11 10:55:11.000000000 +0200
@@ -0,0 +1,33 @@
+// PR middle-end/21492
+// { dg-do compile }
+// { dg-options "-Os -fPIC" }
+
+extern char *bar (const char *, const char *);
+extern char *baz (char *, const char *);
+extern unsigned int fn (const char *);
+static const struct C { int i; } k = { 0};
+
+struct A
+{
+ ~A ();
+};
+
+char *
+foo (char *x, const char *y)
+{
+ A a;
+ char *c = x;
+
+ if (bar (y, "foo"))
+ {
+ baz (c, "foo");
+ c += fn ("foo");
+ }
+ else if (bar (y, "bar"))
+ {
+ baz (c, "bar");
+ c += fn ("bar");
+ }
+
+ return x;
+}
Jakub