Bug 20115 - [4.0 Regression] Pure functions are mishandled
Summary: [4.0 Regression] Pure functions are mishandled
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.0.0
: P2 critical
Target Milestone: 4.0.0
Assignee: Diego Novillo
URL:
Keywords: wrong-code
Depends on:
Blocks: 20100
  Show dependency treegraph
 
Reported: 2005-02-20 23:06 UTC by Andrew Pinski
Modified: 2005-02-23 11:23 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.3.6 3.4.4
Known to fail: 4.0.0
Last reconfirmed: 2005-02-22 14:58:42


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2005-02-20 23:06:56 UTC
Take the following code, we should not abort:
int func_pure (void);
void func_other (int);
int global_int;
int func_pure (void) { return global_int; }
void func_other (int a)
{
  global_int = a + 1;
}
int f(void)
{
  int a;
  a = func_pure();
  func_other (a);
  a = func_pure (); // We are removing this function call
  return a;
}
void abort (void);

int main(void)
{
  global_int = 10;
  if (f() != 11)
    abort ();
}
Comment 1 Jakub Jelinek 2005-02-22 14:15:39 UTC
This is a DOM bug.
Comment above lookup_avail_expr says:
   NOTE: This function assumes that STMT is a MODIFY_EXPR node that
   contains no CALL_EXPR on its RHS and makes no volatile nor
   aliased references.  */
and I have no reason not to believe this, if not perhaps for const calls, then
certainly for pure calls.  For pure calls the code would need to invalidate
all recorded pure calls whenever a stmt might modify global state.
But optimize_stmt/eliminate_redundant_computations will happily call
lookup_avail_expr with a CALL_EXPR on the RHS, because const/pure calls don't
have TREE_SIDE_EFFECTS set.

I have tried:
--- tree-ssa-dom.c.jj  2005-02-17 20:02:58.000000000 +0100
+++ tree-ssa-dom.c      2005-02-22 14:40:14.912216290 +0100
@@ -2964,7 +2964,8 @@ optimize_stmt (struct dom_walk_data *wal
                        || (TREE_CODE (stmt) == MODIFY_EXPR
                            && ! TREE_SIDE_EFFECTS (TREE_OPERAND (stmt, 1)))
                        || TREE_CODE (stmt) == COND_EXPR
-                       || TREE_CODE (stmt) == SWITCH_EXPR));
+                       || TREE_CODE (stmt) == SWITCH_EXPR)
+                    && get_call_expr_in (stmt) == NULL);

   if (may_optimize_p)
     may_have_exposed_new_symbols

which fixes this, but it seems no other tree-SSA optimization is able to optimize
say extern int foo (void) __attribute__((pure)); ... a = foo (); a += foo ();
into a = 2 * foo ();, fortunately RTL optimizations optimize that.

If const calls are actually handled correctly by lookup_avail_expr, then
the comment above it ought to be changed and we could only avoid optimizing
DECL_IS_PURE calls in addition to TREE_SIDE_EFFECTS rhs' in optimize_stmt.
Comment 2 Andrew Pinski 2005-02-22 14:19:31 UTC
Note this was cause by:
2005-01-26  Diego Novillo  <dnovillo@redhat.com>

        PR tree-optimization/19633
        * tree-ssa-alias.c (ptr_is_dereferenced_by): Also handle
        CALL_EXPRs.
        (maybe_create_global_var): Do not create .GLOBAL_VAR if there
        are no call-clobbered variables.
        * tree-outof-ssa.c (check_replaceable): Return false for calls
        with side-effects.


Comment 3 Andrew Pinski 2005-02-22 14:21:28 UTC
Also note that DOM is doing the "correct" thing as the DOM does not know that func_other could 
change the value of func_pure.
Comment 4 Andrew Pinski 2005-02-22 14:56:42 UTC
> For pure calls the code would need to invalidate
> all recorded pure calls whenever a stmt might modify global state.
Yes this was done with GLOBAL_VAR before Diego's patch but now it is not done with anything else.  
This is basically the same issue as PR 20100.
Comment 5 Diego Novillo 2005-02-22 18:26:58 UTC
Testing patch.
Comment 6 GCC Commits 2005-02-23 05:08:50 UTC
Subject: Bug 20115

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	dnovillo@gcc.gnu.org	2005-02-23 05:08:33

Modified files:
	gcc            : ChangeLog tree-optimize.c tree-pass.h 
	                 tree-ssa-alias.c tree-ssa-operands.c tree-ssa.c 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/gcc.dg/tree-ssa: 20040517-1.c 
Added files:
	gcc/testsuite/gcc.dg: pr20100.c pr20115-1.c pr20115.c 

Log message:
	PR tree-optimization/20100
	PR tree-optimization/20115
	* tree-optimize.c (init_tree_optimization_passes): Remove
	pass_maybe_create_global_var.
	* tree-pass.h (pass_maybe_create_global_var): Remove.
	* tree-ssa-alias.c (aliases_computed_p): Declare.
	(struct alias_info): Add field NUM_PURE_CONST_CALLS_FOUND.
	(count_calls_and_maybe_create_global_var): Remove.
	(pass_maybe_create_global_var): Remove.
	(init_alias_info): Do not declare aliases_computed_p.
	(maybe_create_global_var): If the function contains no
	call-clobbered variables and a mix of pure/const and regular
	function calls, create .GLOBAL_VAR.
	Mark all call-clobbered variables for renaming.
	(merge_pointed_to_info): Update comment.
	(add_pointed_to_var): Likewise.
	(is_escape_site): Likewise.
	Accept struct alias_info * instead of size_t *.
	Update all users.
	Update AI->NUM_CALLS_FOUND and AI->NUM_PURE_CONST_CALLS_FOUND
	as necessary.
	* tree-ssa-operands.c (get_call_expr_operands): If
	ALIASES_COMPUTED_P is false, do not add call-clobbering
	operands.
	* tree-ssa.c (init_tree_ssa): Set ALIASES_COMPUTED_P to false.
	(delete_tree_ssa): Likewise.
	
	testsuite/ChangeLog
	
	PR tree-optimization/20100
	PR tree-optimization/20115
	* gcc.dg/pr20115.c: New test.
	* gcc.dg/pr20115-1.c: New test.
	* gcc.dg/pr20100.c: New test.
	* gcc.dg/tree-ssa/20040517-1.c: Expect virtual operands for
	call-clobbered variables after alias1.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7566&r2=2.7567
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-optimize.c.diff?cvsroot=gcc&r1=2.73&r2=2.74
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-pass.h.diff?cvsroot=gcc&r1=2.26&r2=2.27
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-alias.c.diff?cvsroot=gcc&r1=2.70&r2=2.71
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-operands.c.diff?cvsroot=gcc&r1=2.62&r2=2.63
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa.c.diff?cvsroot=gcc&r1=2.77&r2=2.78
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5071&r2=1.5072
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/pr20100.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/pr20115-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/pr20115.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c.diff?cvsroot=gcc&r1=1.3&r2=1.4

Comment 7 Steven Bosscher 2005-02-23 11:23:01 UTC
http://gcc.gnu.org/ml/gcc-patches/2005-02/msg01387.html