Patchwork Improve ipa-pure-const handling of builtins

login
register
mail settings
Submitter Jan Hubicka
Date June 11, 2010, 3:16 p.m.
Message ID <20100611151604.GC7958@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/55336/
State New
Headers show

Comments

Jakub Jelinek - June 11, 2010, 2:32 p.m.
On Fri, Jun 11, 2010 at 05:16:04PM +0200, Jan Hubicka wrote:
> 	* ipa-pure-const.c (special_builtlin_state): New function.

Spelling (also in the code). s/ltlin/ltin/

> 	(check_call): Use it instead of special casign BUILT_IN_RETURN.

s/casign/casing/

	Jakub
Jan Hubicka - June 11, 2010, 3:16 p.m.
Hi,
while looking on statistics, I noticed that quite large portion of functions are not
pure/const because they call alloca or __builtin_unreachable.   This patch adds code
to ipa-pure-const.c to recognize builtins that are special in a way that they can
not be const/pure, but function calling them can.

Bootstrapped/regtested x86_64-linux, commited.
Honza

	* ipa-pure-const.c (special_builtlin_state): New function.
	(check_call): Use it instead of special casign BUILT_IN_RETURN.
	(propagate_pure_const): Use it.

	* gcc.dg/ipa/pure-const-2.c: New testcase.
H.J. Lu - June 11, 2010, 9:36 p.m.
On Fri, Jun 11, 2010 at 8:16 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> while looking on statistics, I noticed that quite large portion of functions are not
> pure/const because they call alloca or __builtin_unreachable.   This patch adds code
> to ipa-pure-const.c to recognize builtins that are special in a way that they can
> not be const/pure, but function calling them can.
>
> Bootstrapped/regtested x86_64-linux, commited.
> Honza
>
>        * ipa-pure-const.c (special_builtlin_state): New function.
>        (check_call): Use it instead of special casign BUILT_IN_RETURN.
>        (propagate_pure_const): Use it.
>

This caused:

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

Patch

Index: ipa-pure-const.c
===================================================================
--- ipa-pure-const.c	(revision 160547)
+++ ipa-pure-const.c	(working copy)
@@ -410,6 +410,40 @@  worse_state (enum pure_const_state_e *st
   *looping = MAX (*looping, looping2);
 }
 
+/* Recognize special cases of builtins that are by themself not pure or const
+   but function using them is.  */
+static bool
+special_builtlin_state (enum pure_const_state_e *state, bool *looping,
+			tree callee)
+{
+  if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
+    switch (DECL_FUNCTION_CODE (callee))
+      {
+	case BUILT_IN_RETURN:
+	case BUILT_IN_UNREACHABLE:
+	case BUILT_IN_ALLOCA:
+	case BUILT_IN_STACK_SAVE:
+	case BUILT_IN_STACK_RESTORE:
+	case BUILT_IN_EH_POINTER:
+	case BUILT_IN_EH_FILTER:
+	case BUILT_IN_UNWIND_RESUME:
+	case BUILT_IN_CXA_END_CLEANUP:
+	case BUILT_IN_EH_COPY_VALUES:
+	case BUILT_IN_FRAME_ADDRESS:
+	case BUILT_IN_APPLY:
+	case BUILT_IN_APPLY_ARGS:
+	case BUILT_IN_ARGS_INFO:
+	  *looping = false;
+	  *state = IPA_CONST;
+	  return true;
+	case BUILT_IN_PREFETCH:
+	  *looping = true;
+	  *state = IPA_CONST;
+	  return true;
+      }
+  return false;
+}
+
 /* Check the parameters of a function call to CALL_EXPR to see if
    there are any references in the parameters that are not allowed for
    pure or const functions.  Also check to see if this is either an
@@ -460,9 +494,15 @@  check_call (funct_state local, gimple ca
      graph.  */
   if (callee_t)
     {
-      /* built_in_return is really just an return statemnt.  */
-      if (gimple_call_builtin_p (call, BUILT_IN_RETURN))
-	return;
+      enum pure_const_state_e call_state;
+      bool call_looping;
+
+      if (special_builtlin_state (&call_state, &call_looping, callee_t))
+	{
+	  worse_state (&local->pure_const_state, &local->looping,
+		       call_state, call_looping);
+	  return;
+	}
       /* When bad things happen to bad functions, they cannot be const
 	 or pure.  */
       if (setjmp_call_p (callee_t))
@@ -1143,10 +1183,13 @@  propagate_pure_const (void)
 		      edge_looping = y_l->looping;
 		    }
 		}
+	      else if (special_builtlin_state (&edge_state, &edge_looping,
+					       y->decl))
+		;
 	      else
 		state_from_flags (&edge_state, &edge_looping,
-			          flags_from_decl_or_type (y->decl),
-			          cgraph_edge_cannot_lead_to_return (e));
+				  flags_from_decl_or_type (y->decl),
+				  cgraph_edge_cannot_lead_to_return (e));
 
 	      /* Merge the results with what we already know.  */
 	      better_state (&edge_state, &edge_looping,
Index: testsuite/gcc.dg/ipa/pure-const-2.c
===================================================================
--- testsuite/gcc.dg/ipa/pure-const-2.c	(revision 0)
+++ testsuite/gcc.dg/ipa/pure-const-2.c	(revision 0)
@@ -0,0 +1,28 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-local-pure-const1 -fdump-tree-optimized" } */
+static __attribute__ ((noinline, noclone))
+int i_am_pure(char *c, int n)
+{
+  char *d=__builtin_alloca (n);
+  int i;
+  int sum;
+  for (i=0;i<n;i++)
+    d[i] = c[i];
+  for (i=0;i<n;i++)
+    d[i] *= c[n-i];
+  for (i=0;i<n;i++)
+    sum+=d[i];
+  if (sum)
+    __builtin_unreachable ();
+  return sum;
+}
+char array[11];
+int
+main(void)
+{
+  i_am_pure (array,5);
+  i_am_pure (array,11);
+  return 0;
+}
+/* { dg-final { scan-tree-dump "found to be pure: i_am_pure" "local-pure-const1"} } */
+/* { dg-final { scan-tree-dump-not "i_am_pure" "optimized"} } */