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

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