[tree-ssa-branch] simplify builtins

Diego Novillo dnovillo@redhat.com
Sat Jun 29 11:58:00 GMT 2002


On Thu, 27 Jun 2002, Aldy Hernandez wrote:

> i need another nod because i changed 2 things.
> 
> 1. is_string_plus_int() was just replicating string_constant() which is
>    what the expand_builtins were using.  so now i just call that.
>    less code, cleaner, and catches more corner cases :).
> 
> 2. is_simple_compound_lval() was bailing out on INDIRECT_REFs, so it
>    never got a chance to call is_simple_min_lval().  this was causing
>    a vararg regression.
> 
I changed the implementation for #2.  When simplifying address
expressions, the simplifier should deal with expressions of the
form '&*PTR' by folding them first into 'PTR' and then
simplifying PTR as a regular rvalue.

The front end will fold those away for us.  But the builtin for
va_end is generating &*PTR expressions, so we need to deal with
them.

Notice that we are causing one more test to time out now.  Now
that things work, we should start paying attention to performance
issues.

Bootstrapped and tested on x86-linux.

Diego.


        * c-simplify.c (simplify_call_expr): Do not bail on all builtins.
        (is_simple_call_expr): Same.
	(simplify_addr_expr): New function.
	(simplify_expr): Call it.

        * tree-simple.c (is_simplifiable_builtin): New.
        (is_simple_compound_lval): Do not bail on INDIRECT_REF.

        * tree-simple.h: New prototype for is_simplifiable_builtin.

Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.1
diff -d -u -p -r1.1.4.1 c-simplify.c
--- c-simplify.c	22 Jun 2002 04:39:22 -0000	1.1.4.1
+++ c-simplify.c	29 Jun 2002 17:15:32 -0000
@@ -92,6 +92,7 @@ static void simplify_expr_wfl        PAR
 static void simplify_save_expr       PARAMS ((tree *, tree *));
 static void simplify_stmt_expr       PARAMS ((tree *, tree *));
 static void simplify_compound_literal_expr PARAMS ((tree *, tree *, tree *));
+static void simplify_addr_expr       PARAMS ((tree *, tree *, tree *));
 static void make_type_writable       PARAMS ((tree));
 static tree add_tree                 PARAMS ((tree, tree *));
 static tree insert_before_continue   PARAMS ((tree, tree));
@@ -1116,8 +1117,7 @@ simplify_expr (expr_p, pre_p, post_p, si
       break;
 
     case ADDR_EXPR:
-      simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
-		     is_simple_addr_expr_arg, fb_lvalue);
+      simplify_addr_expr (expr_p, pre_p, post_p);
       break;
 
     /* va_arg expressions should also be left alone to avoid confusing the
@@ -1501,16 +1501,12 @@ simplify_call_expr (expr_p, pre_p, post_
      tree *pre_p;
      tree *post_p;
 {
-  tree id;
-
   if (TREE_CODE (*expr_p) != CALL_EXPR)
     abort ();
 
-  /* Do not simplify calls to builtin functions as they may require
-     specific tree nodes (e.g., __builtin_stdarg_start).
-     FIXME: We should identify which builtins can be simplified safely.  */
-  id = get_callee_fndecl (*expr_p);
-  if (id && DECL_BUILT_IN (id))
+  /* Some builtins cannot be simplified because they require specific
+     arguments (e.g., __builtin_stdarg_start).  */
+  if (!is_simplifiable_builtin (*expr_p))
     return;
 
   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id,
@@ -1519,7 +1515,6 @@ simplify_call_expr (expr_p, pre_p, post_
                  fb_rvalue);
 }
 
-
 /*  Simplify the TREE_LIST node pointed by EXPR_P.
 
     PRE_P points to the list where side effects that must happen before
@@ -1945,6 +1940,38 @@ simplify_stmt_expr (expr_p, pre_p)
   simplify_stmt (&body);
   add_tree (body, pre_p);
 }
+
+/*  Re-write the ADDR_EXPR node pointed by EXPR_P
+
+    PRE_P points to the list where side effects that must happen before
+	*EXPR_P should be stored.
+
+    POST_P points to the list where side effects that must happen after
+	*EXPR_P should be stored.  */
+
+static void
+simplify_addr_expr (expr_p, pre_p, post_p)
+     tree *expr_p;
+     tree *pre_p;
+     tree *post_p;
+{
+  /* Check if we are dealing with an expression of the form '&*ptr'.
+     While the front end folds away '&*ptr' into 'ptr', these
+     expressions may be generated internally by the compiler (e.g.,
+     builtins like __builtin_va_end).  */
+  if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) != INDIRECT_REF)
+    simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, 
+		   is_simple_addr_expr_arg, fb_lvalue);
+  else
+    {
+      /* Fold &*EXPR into EXPR and simplify EXPR into a legal argument for
+	 ADDR_EXPR.  Notice that we need to request an rvalue because EXPR is
+	 already the lvalue that we were looking for originally.  */
+      *expr_p = TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0);
+      simplify_expr (expr_p, pre_p, post_p, is_simple_addr_expr_arg, fb_rvalue);
+    }
+}
+
 
 /* Code generation.  */
 
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.1
diff -d -u -p -r1.1.4.1 tree-simple.c
--- tree-simple.c	22 Jun 2002 04:39:44 -0000	1.1.4.1
+++ tree-simple.c	29 Jun 2002 17:15:38 -0000
@@ -670,21 +670,15 @@ int
 is_simple_call_expr (t)
      tree t;
 {
-  tree decl;
-
   if (t == NULL_TREE)
     return 1;
 
   if (TREE_CODE (t) != CALL_EXPR)
     return 0;
 
-  /* Consider that calls to builtin functions are in SIMPLE form already.
-
-     FIXME: The simplifier will not simplify these calls because some
-	    builtins need specific arguments (e.g., __builtin_stdarg_start
-	    wants one of the function arguments as its last parameters).  */
-  decl = get_callee_fndecl (t);
-  if (decl && DECL_BUILT_IN (decl))
+  /* Some builtins cannot be simplified because the require specific
+     arguments.  */
+  if (!is_simplifiable_builtin (t))
     return 1;
 
   return (is_simple_id (TREE_OPERAND (t, 0))
@@ -1005,4 +999,67 @@ is_simple_exprseq (t)
           || (TREE_CODE (t) == COMPOUND_EXPR
 	      && is_simple_expr (TREE_OPERAND (t, 0))
 	      && is_simple_exprseq (TREE_OPERAND (t, 1))));
+}
+
+/* Return nonzero if FNDECL can be simplified.  This is needed for
+   builtins like __builtin_stdarg_start expects its last parameter to be
+   one of the current function's arguments.  */
+
+int
+is_simplifiable_builtin (expr)
+     tree expr;
+{
+  enum built_in_function fcode;
+  tree decl, t1, t2, t3;
+
+  decl = get_callee_fndecl (expr);
+
+  if (decl == NULL_TREE || !DECL_BUILT_IN (decl))
+    return 1;
+
+  fcode = DECL_FUNCTION_CODE (decl);
+
+  switch (fcode)
+    {
+      /* Many of the string builtins fold certain string patterns into
+         constants.  Make sure we don't simplify something which will
+         be folded by the builtin later.  */
+
+      /* foo (const char *, const char *, ...).  */
+    case BUILT_IN_STRNCMP:
+    case BUILT_IN_STRSPN:
+    case BUILT_IN_STRSTR:
+    case BUILT_IN_STRCSPN:
+      t1 = TREE_VALUE (TREE_OPERAND (expr, 1));
+      t2 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1)));
+
+      return !(string_constant (t1, &t3) || string_constant (t2, &t3));
+
+      /* foo (const char *, ...).  */
+    case BUILT_IN_STRLEN:
+    case BUILT_IN_STRRCHR:
+    case BUILT_IN_STRCHR:
+    case BUILT_IN_INDEX:
+    case BUILT_IN_FPUTS:
+      t1 = TREE_VALUE (TREE_OPERAND (expr, 1));
+
+      return !string_constant (t1, &t3);
+
+      /* foo (..., const char *, ...).  */
+    case BUILT_IN_STRCPY:
+    case BUILT_IN_STRNCPY:
+    case BUILT_IN_STRCAT:
+    case BUILT_IN_STRNCAT:
+      t2 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1)));
+
+      return !string_constant (t2, &t3);
+
+    case BUILT_IN_STDARG_START:
+    case BUILT_IN_VARARGS_START:
+    case BUILT_IN_VA_COPY:
+      return 0;
+
+    default:
+      return 1;
+    }
 }
Index: tree-simple.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.h,v
retrieving revision 1.1.4.1
diff -d -u -p -r1.1.4.1 tree-simple.h
--- tree-simple.h	22 Jun 2002 04:39:45 -0000	1.1.4.1
+++ tree-simple.h	29 Jun 2002 17:15:38 -0000
@@ -64,5 +64,6 @@ int is_simple_exprseq                  P
 int is_simple_constructor              PARAMS ((tree));
 int is_simple_constructor_elt          PARAMS ((tree));
 int is_simple_initializer              PARAMS ((tree));
+int is_simplifiable_builtin            PARAMS ((tree));
 
 #endif /* _TREE_SIMPLE_H */



More information about the Gcc-patches mailing list