------- Comment #5 from zadeck at naturalbridge dot com  2008-05-08 23:04 
-------
Subject: Re:  [4.4 Regression] g++.dg/opt/pr23714.C
 ICEs with 135041 -> 135057

steven at gcc dot gnu dot org wrote:
> ------- Comment #4 from steven at gcc dot gnu dot org  2008-05-08 22:27 
> -------
> So I was looking at an older revision of dce.c.  There is this new check 
> before
> the !NONJUMP_INSN_P check now:
>
>   /* We can delete dead const or pure calls as long as they do not
>      infinite loop and are not sibling calls.  The problem with
>      sibling calls is that it is hard to see the result.  */
>   if (CALL_P (insn) 
>       && (!SIBLING_CALL_P (insn))
>       && (RTL_CONST_OR_PURE_CALL_P (insn)
>           && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
>     return true;
>
> CALL_P is obviously true for this insn, and so is !SIBLING_CALL_P (there is no
> call_insn/j).  The "/u" flag means that RTL_CONST_OR_PURE_CALL_P is true for
> the insn.  The "/c" flag is clear, so RTL_LOOPING_CONST_OR_PURE_CALL_P is
> false.
>
> I don't know where RTL_CONST_OR_PURE_CALL_P is set.  But that's where I would
> look.
>
> [ I see that RTL_LOOPING_CONST_OR_PURE_CALL_P is not documented.  Kenny, can
> you please take care of that (and probably other necessary document updates
> following your patch)? ]
>
>
>   
The real problem is that this call was being deleted (and I believe that 
it should have been because it is const.) and this caused some blocks to 
become orphaned. 

In particular, the bug was that when this call was deleted, it also 
caused the exception edge out of that block to be deleted.   That caused 
some other blocks to be orphaned and that caused an assertion check.   
What this patch does is only allow pure and const calls to be deleted 
when dce is run as a stand alone pass because it is not possible to 
properly update the blocks from the call  to fast dce that happens as a 
side effect of running the lr problem. 

However, such calls (and there will be a lot more of them once more 
libcall code gets removed) are deleted by the use-def based dce that is 
run right before combine. 

I am testing this patch on x86.  But hp needs to test it on the cris 
before i will ask for approval.

kenny

2008-05-08  Kenneth Zadeck  <[EMAIL PROTECTED]>

    * dce.c (deletable_insn_p): Do not delete calls if
    df_in_progress.
    (delete_unmarked_insns): When deleting a call, call
    delete_unreachable_blocks.
    * rtl.texi (RTL_CONST_CALL_P, RTL_PURE_CALL_P,
    RTL_CONST_OR_PURE_CALL_P, RTL_LOOPING_CONST_OR_PURE_CALL_P): Fixed
    doc.



Index: doc/rtl.texi
===================================================================
--- doc/rtl.texi        (revision 135089)
+++ doc/rtl.texi        (working copy)
@@ -559,13 +559,36 @@ In either case GCC assumes these address
 perhaps with the help of base registers.
 Stored in the @code{unchanging} field and printed as @samp{/u}.

[EMAIL PROTECTED] CONST_OR_PURE_CALL_P
[EMAIL PROTECTED] RTL_CONST_CALL_P
 @cindex @code{call_insn} and @samp{/u}
 @cindex @code{unchanging}, in @code{call_insn}
[EMAIL PROTECTED] CONST_OR_PURE_CALL_P (@var{x})
-In a @code{call_insn}, @code{note}, or an @code{expr_list} for notes,
-indicates that the insn represents a call to a const or pure function.
-Stored in the @code{unchanging} field and printed as @samp{/u}.
[EMAIL PROTECTED] RTLCONST_OR_PURE_CALL_P (@var{x})
+In a @code{call_insn} indicates that the insn represents a call to a
+const function.  Stored in the @code{unchanging} field and printed as
[EMAIL PROTECTED]/u}.
+
[EMAIL PROTECTED] RTL_PURE_CALL_P
[EMAIL PROTECTED] @code{call_insn} and @samp{/i}
[EMAIL PROTECTED] @code{return_val}, in @code{call_insn}
[EMAIL PROTECTED] RTLCONST_OR_PURE_CALL_P (@var{x})
+In a @code{call_insn} indicates that the insn represents a call to a
+pure function.  Stored in the @code{return_val} field and printed as
[EMAIL PROTECTED]/i}.
+
[EMAIL PROTECTED] RTL_CONST_OR_PURE_CALL_P
[EMAIL PROTECTED] @code{call_insn} and @samp{/u} or @samp{/i}
[EMAIL PROTECTED] RTL_CONST_OR_PURE_CALL_P (@var{x})
+In a @code{call_insn}, true if @code{RTL_CONST_CALL_P} or
[EMAIL PROTECTED] is true.
+
[EMAIL PROTECTED] RTL_LOOPING_CONST_OR_PURE_CALL_P
[EMAIL PROTECTED] @code{call_insn} and @samp{/c}
[EMAIL PROTECTED] @code{call}, in @code{call_insn}
[EMAIL PROTECTED] RTL_LOOPING_CONST_OR_PURE_CALL_P (@var{x})
+In a @code{call_insn} indicates that the insn represents a possibly
+infinite looping call to a const or pure function.  Stored in the
[EMAIL PROTECTED] field and printed as @samp{/c}.  Only true if one of
[EMAIL PROTECTED] or @code{RTL_PURE_CALL_P} is true.

 @findex INSN_ANNULLED_BRANCH_P
 @cindex @code{jump_insn} and @samp{/u}
@@ -869,6 +892,9 @@ These are the fields to which the above 
 @item call
 In a @code{mem}, 1 means that the memory reference will not trap.

+In a @code{call}, 1 means that this pure or const call may possibly
+infinite loop.
+
 In an RTL dump, this flag is represented as @samp{/c}.

 @findex frame_related
@@ -938,6 +964,8 @@ known not to be a member of a structure,

 In @code{symbol_ref} expressions, 1 means the referenced symbol is weak.

+In @code{call} expressions, 1 means the call is pure.
+
 In an RTL dump, this flag is represented as @samp{/i}.

 @findex jump
@@ -967,8 +995,8 @@ instruction, 1 means an annulling branch
 In a @code{symbol_ref} expression, 1 means that this symbol addresses
 something in the per-function constant pool.

-In a @code{call_insn}, @code{note}, or an @code{expr_list} of notes,
-1 means that this instruction is a call to a const or pure function.
+In a @code{call_insn} 1 means that this instruction is a call to a const
+function.

 In an RTL dump, this flag is represented as @samp{/u}.

Index: dce.c
===================================================================
--- dce.c       (revision 135089)
+++ dce.c       (working copy)
@@ -99,11 +99,16 @@ deletable_insn_p (rtx insn, bool fast)
   rtx body, x;
   int i;

-  /* We can delete dead const or pure calls as long as they do not
-     infinite loop and are not sibling calls.  The problem with
-     sibling calls is that it is hard to see the result.  */
-  if (CALL_P (insn) 
+  if (CALL_P (insn)
+      /* We cannot delete calls inside of the recursive dce because
+        this may cause basic blocks to be deleted and this messes up
+        the rest of the stack of optimization passes.  */
+      && (!df_in_progress)
+      /* We cannot delete pure or const sibling calls because it is
+        hard to see the result.  */
       && (!SIBLING_CALL_P (insn))
+      /* We can delete dead const or pure calls as long as they do not
+         infinite loop.  */
       && (RTL_CONST_OR_PURE_CALL_P (insn)
          && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
     return true;
@@ -305,6 +310,7 @@ delete_unmarked_insns (void)
 {
   basic_block bb;
   rtx insn, next;
+  bool must_clean = false;

   FOR_EACH_BB (bb)
     FOR_BB_INSNS_SAFE (bb, insn, next)
@@ -382,9 +388,19 @@ delete_unmarked_insns (void)
              remove_note (XEXP (note, 0), libcall_note);
            }

+         /* If a pure or const call is deleted, this may make the cfg
+            have unreachable blocks.  We rememeber this and call
+            delete_unreachable_blocks at the end.  */
+         if (CALL_P (insn))
+           must_clean = true;
+
          /* Now delete the insn.  */
          delete_insn_and_edges (insn);
        }
+
+  /* Deleted a pure or const call.  */
+  if (must_clean)
+    delete_unreachable_blocks ();
 }




-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36177

Reply via email to