This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH/RFC] Fix PR optimization/11083
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 8 Jul 2003 15:01:33 +0200
- Subject: [PATCH/RFC] Fix PR optimization/11083
Hi,
This is a regression from GCC 3.2.3 present on the 3.3 branch only, caused by
this patch (thanks to Janis for tracking it down):
2002-06-13 Jeffrey Law <law@redhat.com>
* gcse.c (delete_null_pointer_checks_1): Inform caller if any
null pointer checks were eliminated. Update prototype.
(delete_null_pointer_checks): Similarly.
* rtl.h (delete_null_pointer_checks): Update prototype.
* toplev.c (rest_of_compilation): Only run cleanup_cfg if
delete_null_pointer_checks deletes one or more null
pointer checks. Do not run cleanup_cfg before gcse, the
CFG is accurate and optimized at that point.
more specifically this hunk:
@@ -2814,7 +2814,6 @@
timevar_push (TV_GCSE);
open_dump_file (DFI_gcse, decl);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
tem = gcse_main (insns, rtl_dump_file);
rebuild_jump_labels (insns);
delete_trivially_dead_insns (insns, max_reg_num ());
Jeff thought that the CFG is optimized before the GCSE pass, the testcase
provides an admittedly pathological counter-example on the 3.3 branch: the
addressof pass calls purge_all_dead_edges in optimizing mode, so we end up
with unreachable basic blocks, which fools the LCM code used by GCSE. The
compiler eventually dies when trying to insert an insn on a bogus edge.
I'm not a specialist of the subject so I mimiced Jan's fix for PR opt/8492,
which was another example of the LCM code being fooled by unreachable basic
blocks. This is sufficient to fix the ICE.
Is that the right approach? If so, ok for the 3.3 branch after the usual
testing? What about the mainline (which doesn't ICE on the testcase)?
--
Eric Botcazou
2003-07-08 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/11083
* toplev.c (rest_of_compilation): Delete unreachable blocks
if dead edges were purged after the addressof pass.
2003-07-08 Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/opt/cfg1.C: New test.
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.690.2.20
diff -u -p -r1.690.2.20 toplev.c
--- toplev.c 20 Jun 2003 21:18:41 -0000 1.690.2.20
+++ toplev.c 8 Jul 2003 12:52:54 -0000
@@ -2847,8 +2847,8 @@ rest_of_compilation (decl)
open_dump_file (DFI_addressof, decl);
purge_addressof (insns);
- if (optimize)
- purge_all_dead_edges (0);
+ if (optimize && purge_all_dead_edges (0))
+ delete_unreachable_blocks ();
reg_scan (insns, max_reg_num (), 1);
close_dump_file (DFI_addressof, print_rtl, insns);
// PR optimization/11083
// Origin: <nick@ilm.com>
// Reduced testcase by Wolfgang Bangerth <bangerth@ticam.utexas.edu>
// The compiler used to keep unreachable basic blocks after dead edges
// were purged, which fooled the LCM code of the GCSE pass.
// { dg-do compile }
// { dg-options "-O2 -fnon-call-exceptions" }
extern void *memmove (void *, const void *, unsigned int) throw ();
struct S {
int *q;
S(int *i) : q(i) {}
};
struct X {
int *p;
void foo(S first, S last) {
try { memmove(0, 0, last.q - first.q); }
catch(...) { throw; }
}
void bar (const X& x);
};
void X::bar (const X& x)
{
const unsigned int xlen = S(x.p).q - S(x.p).q;
if (xlen > 0)
foo(S(x.p), S(x.p));
}