This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix crossjumping (PR middle-end/21492)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]