[tree-ssa] dead const/pure/alloca call removal
Jan Hubicka
jh@suse.cz
Sat Nov 8 21:21:00 GMT 2003
> > > On Sat, 08 Nov 2003 10:55:16 -0800, "Zack Weinberg" <zack@codesourcery.com> wrote:
> > >
> > > > Falk Hueffner <falk.hueffner@student.uni-tuebingen.de> writes:
> > > >
> > > >> Jan Hubicka <jh@suse.cz> writes:
> > > >>
> > > >>> + /* Return false when CALL can be removed when it's return value is dead.
> > > >> ^ true?
> > > >>
> > > >> I would formulate it like this:
> > > >>
> > > >> Return true if CALL can be removed in case its return value is dead.
> > > >
> > > > Still better English, given your explanation of the return value:
> > > >
> > > > Return true if CALL cannot be removed even if its return value
> > > > is dead (i.e. CALL must be assumed to have side effects).
> > >
> > > We have a flag for this: TREE_SIDE_EFFECTS, which is cleared in
> > > gimplify_call_expr for const functions. If it should also be cleared for
> > > pure and alloca calls, please make the change there rather than introduce a
> > > new function.
> >
> > OK, I will update the pure functions and ask for TREE_SIDE_EFFECTS.
> > Are you really sure we want to clear alloca too? It has side effect.
> > Only I know that given the semantic of alloca the side effect is useless
> > when return value is thrown away.
>
> This has a problem. We first gimplify functions, then analyze them and
> mark as CONST/PURE and then optimize. So we lose the information.
>
> Wehre do you think this flag should be updated?
> (remove_useless* looks like one candidate)
Hi,
here is updated patch that use TREE_SIDE_EFFECTS for const and pure
functions, adds code to update the flag to remove_useless* and still use
separate test for alloca. I added test that ensures that automatically
recognized pure functions are optimized.
It also updates spelling isses pointed out by Zack. Thanks for all the comments :)
Bootstrap still in progress (stage3 now). OK assuming it passes?
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-dce" } */
int t() __attribute__ ((const));
q()
{
int i = t();
if (!i)
i = t();
}
/* There should be no IF conditionals. */
/* { dg-final { scan-tree-dump-times "if " 0 "dce"} } */
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-dce" } */
int t() __attribute__ ((const));
q()
{
alloca ();
}
/* There should be no alloca conditionals. */
/* { dg-final { scan-tree-dump-times "alloca" 0 "dce"} } */
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-dce" } */
__attribute__ ((noinline))
static int t(int a)
{
return a;
}
q()
{
int i = t(1);
if (!i)
i = t(1);
}
/* We should notice that t is pure and we should delete IF conditional. */
/* { dg-final { scan-tree-dump-times "Deleted.*if " 0 "dce"} } */
* tree-ssa-dce.c (call_useful_p): New function.
(stmt_useful_p): Use it.
* gimplify.c (gimplify_call_expr): Clear side effect flags for pure
functions.
* tree-cfg.c (remove_useless_stmts_and_vars_1): Clear side effect flags
for pure and const functions.
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.106
diff -c -3 -p -r1.1.2.106 gimplify.c
*** gimplify.c 5 Nov 2003 13:39:23 -0000 1.1.2.106
--- gimplify.c 8 Nov 2003 21:11:02 -0000
*************** gimplify_call_expr (tree *expr_p, tree *
*** 1709,1719 ****
}
}
! /* If the function is "const", then clear TREE_SIDE_EFFECTS on its
decl. This allows us to eliminate redundant or useless
calls to "const" functions. */
if (TREE_CODE (*expr_p) == CALL_EXPR
! && (call_expr_flags (*expr_p) & ECF_CONST))
TREE_SIDE_EFFECTS (*expr_p) = 0;
return ret;
--- 1709,1719 ----
}
}
! /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
decl. This allows us to eliminate redundant or useless
calls to "const" functions. */
if (TREE_CODE (*expr_p) == CALL_EXPR
! && (call_expr_flags (*expr_p) & (ECF_CONST | ECF_PURE)))
TREE_SIDE_EFFECTS (*expr_p) = 0;
return ret;
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.199
diff -c -3 -p -r1.1.4.199 tree-cfg.c
*** tree-cfg.c 8 Nov 2003 09:49:19 -0000 1.1.4.199
--- tree-cfg.c 8 Nov 2003 21:11:02 -0000
*************** remove_useless_stmts_and_vars_1 (tree *f
*** 1233,1240 ****
case RETURN_EXPR:
data->may_branch = true;
break;
- case MODIFY_EXPR:
case CALL_EXPR:
if (tree_could_throw_p (*stmt_p))
data->may_throw = true;
break;
--- 1233,1256 ----
case RETURN_EXPR:
data->may_branch = true;
break;
case CALL_EXPR:
+ /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
+ decl. This allows us to eliminate redundant or useless
+ calls to "const" functions.
+
+ Gimplifier already does the same operation, but we may notice functions
+ being const and pure once their calls has been gimplified, so we need
+ to update the flag. */
+ if (call_expr_flags (*stmt_p) & (ECF_CONST | ECF_PURE))
+ TREE_SIDE_EFFECTS (*stmt_p) = 0;
+ if (tree_could_throw_p (*stmt_p))
+ data->may_throw = true;
+ break;
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (*stmt_p, 1)) == CALL_EXPR
+ && (call_expr_flags (TREE_OPERAND (*stmt_p, 1))
+ & (ECF_CONST | ECF_PURE)))
+ TREE_SIDE_EFFECTS (TREE_OPERAND (*stmt_p, 1)) = 0;
if (tree_could_throw_p (*stmt_p))
data->may_throw = true;
break;
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.64
diff -c -3 -p -r1.1.2.64 tree-ssa-dce.c
*** tree-ssa-dce.c 5 Nov 2003 13:39:23 -0000 1.1.2.64
--- tree-ssa-dce.c 8 Nov 2003 21:11:02 -0000
*************** find_useful_stmts (void)
*** 236,241 ****
--- 236,259 ----
}
}
+ /* Return true if CALL cannot be removed even if its return value
+ is dead (i.e. CALL must be assumed to have side effects).
+ In addition to const and pure functions we may elliminate alloca
+ builtin too. */
+
+ static bool
+ call_useful_p (tree call)
+ {
+ tree decl;
+
+ if (!TREE_SIDE_EFFECTS (call))
+ return false;
+ decl = get_callee_fndecl (call);
+ if (decl && DECL_BUILT_IN (decl)
+ && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
+ return false;
+ return true;
+ }
/* Return true if STMT is necessary. */
*************** stmt_useful_p (tree stmt)
*** 258,269 ****
case CASE_LABEL_EXPR:
case LABEL_EXPR:
case BIND_EXPR:
- case CALL_EXPR:
case RESX_EXPR:
return true;
case MODIFY_EXPR:
! if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
return true;
/* These values are mildly magic bits of the EH runtime. We can't
--- 276,289 ----
case CASE_LABEL_EXPR:
case LABEL_EXPR:
case BIND_EXPR:
case RESX_EXPR:
return true;
+ case CALL_EXPR:
+ return call_useful_p (stmt);
case MODIFY_EXPR:
! if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR
! && call_useful_p (TREE_OPERAND (stmt, 1)))
return true;
/* These values are mildly magic bits of the EH runtime. We can't
More information about the Gcc-patches
mailing list