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 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();
}

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