This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/11646
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Sep 2003 08:20:54 +0200
- Subject: [PATCH] Fix PR optimization/11646
Hi,
This is again a problem with -fnon-call-exceptions, a regression present on
the 3.3 branch (and latent on mainline).
The compiler ICEs when trying to split an EH edge, the GCSE pass having
inserted some insns on this edge because its EDGE_ABNORMAL flag was
previously cleared by purge_dead_edges.
After purge_dead_edges is fixed, the compiler ICEs when trying to insert
insns on a bogus edge during GCSE. This is again because there is an
unreachable basic block, created by the previous CSE pass.
Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada).
2003-09-16 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/11646
* cfgrtl.c (purge_dead_edges) [JUMP_INSN]: Rematerialize the
EDGE_ABNORMAL flag for EH edges.
* toplev.c (rest_of_compilation): Delete unreachable blocks
if dead edges were purged after the first CSE pass.
2003-09-16 Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/opt/cfg3.C: New test.
--
Eric Botcazou
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.61.2.11
diff -u -p -r1.61.2.11 cfgrtl.c
--- cfgrtl.c 22 Apr 2003 23:08:15 -0000 1.61.2.11
+++ cfgrtl.c 15 Sep 2003 07:20:56 -0000
@@ -2261,8 +2261,12 @@ purge_dead_edges (bb)
continue;
else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
/* Keep the edges that correspond to exceptions thrown by
- this instruction. */
- continue;
+ this instruction and rematerialize the EDGE_ABNORMAL flag
+ we just cleared above. */
+ {
+ e->flags |= EDGE_ABNORMAL;
+ continue;
+ }
/* We do not need this edge. */
bb->flags |= BB_DIRTY;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.690.2.21
diff -u -p -r1.690.2.21 toplev.c
--- toplev.c 18 Jul 2003 06:59:16 -0000 1.690.2.21
+++ toplev.c 15 Sep 2003 07:21:55 -0000
@@ -2816,7 +2816,8 @@ rest_of_compilation (decl)
tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
if (tem)
rebuild_jump_labels (insns);
- purge_all_dead_edges (0);
+ if (purge_all_dead_edges (0))
+ delete_unreachable_blocks ();
delete_trivially_dead_insns (insns, max_reg_num ());
// PR optimization/11646
// Origin: <nick@ilm.com>
// This used to fail because the compiler inadvertently cleared
// the EDGE_ABNORMAL flag on a EDGE_EH edge and didn't delete
// unreachable blocks after CSE.
// { dg-do compile }
// { dg-options "-O -fgcse -fnon-call-exceptions" }
struct C
{
int i;
};
struct allocator
{
~allocator() throw() {}
};
struct _Vector_alloc_base
{
_Vector_alloc_base(const allocator& __a) {}
allocator _M_data_allocator;
struct C *_M_start, *_M_end_of_storage;
void _M_deallocate(struct C* __p, unsigned int __n) {}
};
struct _Vector_base : _Vector_alloc_base
{
_Vector_base(const allocator& __a) : _Vector_alloc_base(__a) { }
~_Vector_base() { _M_deallocate(0, _M_end_of_storage - _M_start); }
};
struct vector : _Vector_base
{
vector(const allocator& __a = allocator()) : _Vector_base(__a) {}
struct C& operator[](unsigned int __n) { return *_M_start; }
};
struct A
{
float l() const;
A operator-(const A &) const;
const A& operator=(float) const;
};
struct B
{
float d();
};
float f(const A& a, B& b)
{
vector vc;
int index = vc[0].i;
A aa;
float d = (aa - a).l();
if (d > b.d()) aa = 0;
return b.d();
}