This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch]: cleanup some redundant builtins code


As discussed here:
http://gcc.gnu.org/ml/gcc/2004-09/msg01172.html
there are some cleanups possible in the builtins code.

After Eric's patch to eliminate the "simplify_builtin_" variants:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02319.html
there's still a few things we can do as cleanups from the tree-ssa merge.

One issue is that the expand_builtin_ variants often duplicate a bunch
of tree folding from the fold_builtin_ functions, then simply call
expand_expr() on the result to produce RTL.  The obvious downside is
that we have a lot of duplicated tree munching code.

I went and deleted some of the low-hanging fruit and managed to make
builtins.c around 300 lines smaller.  I left the expanders in place
since we may do additional optimizations.

I found one discrepancy in that fold_builtin_fputs honored
`optmize_size' while the expand_builtin_ variant didn't.  We now rely
on the folder's behavior always.

Bootstrapped on sparc-sun-solaris2.9 (without java since it's broken),
there were no regressions.


Ok for mainline?

		Thanks,
		--Kaveh


2004-09-29  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (expand_builtin_strstr, expand_builtin_strchr,
	expand_builtin_strrchr, expand_builtin_strpbrk,
	expand_builtin_strncat, expand_builtin_strspn,
	expand_builtin_strcspn, expand_builtin_fputs): Eliminate duplicate
	code.
	
diff -rcp orig/egcc-CVS20040928/gcc/builtins.c egcc-CVS20040928/gcc/builtins.c
*** orig/egcc-CVS20040928/gcc/builtins.c	Sun Sep 26 20:00:58 2004
--- egcc-CVS20040928/gcc/builtins.c	Wed Sep 29 12:46:54 2004
*************** expand_builtin_strlen (tree arglist, rtx
*** 2464,2514 ****
  static rtx
  expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       tree fn, tmp;
!       const char *p1, *p2;
! 
!       p2 = c_getstr (s2);
!       if (p2 == NULL)
! 	return 0;
! 
!       p1 = c_getstr (s1);
!       if (p1 != NULL)
! 	{
! 	  const char *r = strstr (p1, p2);
! 
! 	  if (r == NULL)
! 	    return const0_rtx;
! 
! 	  /* Return an offset into the constant string argument.  */
! 	  tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
! 			      fold_convert (TREE_TYPE (s1),
! 					    ssize_int (r - p1))));
! 	  return expand_expr (tmp, target, mode, EXPAND_NORMAL);
! 	}
! 
!       if (p2[0] == '\0')
! 	return expand_expr (s1, target, mode, EXPAND_NORMAL);
! 
!       if (p2[1] != '\0')
! 	return 0;
! 
!       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
!       if (!fn)
! 	return 0;
! 
!       /* New argument list transforming strstr(s1, s2) to
! 	 strchr(s1, s2[0]).  */
!       arglist = build_tree_list (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p2[0]));
!       arglist = tree_cons (NULL_TREE, s1, arglist);
!       return expand_expr (build_function_call_expr (fn, arglist),
! 			  target, mode, EXPAND_NORMAL);
      }
  }
  
  /* Expand a call to the strchr builtin.  Return 0 if we failed the
--- 2464,2476 ----
  static rtx
  expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strstr (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Expand a call to the strchr builtin.  Return 0 if we failed the
*************** expand_builtin_strstr (tree arglist, rtx
*** 2518,2559 ****
  static rtx
  expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       const char *p1;
! 
!       if (TREE_CODE (s2) != INTEGER_CST)
! 	return 0;
! 
!       p1 = c_getstr (s1);
!       if (p1 != NULL)
! 	{
! 	  char c;
! 	  const char *r;
! 	  tree tmp;
! 
! 	  if (target_char_cast (s2, &c))
! 	    return 0;
! 
! 	  r = strchr (p1, c);
! 
! 	  if (r == NULL)
! 	    return const0_rtx;
  
! 	  /* Return an offset into the constant string argument.  */
! 	  tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
! 			      fold_convert (TREE_TYPE (s1),
! 					    ssize_int (r - p1))));
! 	  return expand_expr (tmp, target, mode, EXPAND_NORMAL);
! 	}
! 
!       /* FIXME: Should use here strchrM optab so that ports can optimize
! 	 this.  */
!       return 0;
      }
  }
  
  /* Expand a call to the strrchr builtin.  Return 0 if we failed the
--- 2480,2494 ----
  static rtx
  expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strchr (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
  
!       /* FIXME: Should use strchrM optab so that ports can optimize this.  */
      }
+   return 0;
  }
  
  /* Expand a call to the strrchr builtin.  Return 0 if we failed the
*************** expand_builtin_strchr (tree arglist, rtx
*** 2563,2611 ****
  static rtx
  expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       tree fn, tmp;
!       const char *p1;
! 
!       if (TREE_CODE (s2) != INTEGER_CST)
! 	return 0;
! 
!       p1 = c_getstr (s1);
!       if (p1 != NULL)
! 	{
! 	  char c;
! 	  const char *r;
! 
! 	  if (target_char_cast (s2, &c))
! 	    return 0;
! 
! 	  r = strrchr (p1, c);
! 
! 	  if (r == NULL)
! 	    return const0_rtx;
! 
! 	  /* Return an offset into the constant string argument.  */
! 	  tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
! 			      fold_convert (TREE_TYPE (s1),
! 					    ssize_int (r - p1))));
! 	  return expand_expr (tmp, target, mode, EXPAND_NORMAL);
! 	}
! 
!       if (! integer_zerop (s2))
! 	return 0;
! 
!       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
!       if (!fn)
! 	return 0;
! 
!       /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
!       return expand_expr (build_function_call_expr (fn, arglist),
! 			  target, mode, EXPAND_NORMAL);
      }
  }
  
  /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
--- 2498,2510 ----
  static rtx
  expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strrchr (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
*************** expand_builtin_strrchr (tree arglist, rt
*** 2615,2671 ****
  static rtx
  expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       tree fn, tmp;
!       const char *p1, *p2;
! 
!       p2 = c_getstr (s2);
!       if (p2 == NULL)
! 	return 0;
! 
!       p1 = c_getstr (s1);
!       if (p1 != NULL)
! 	{
! 	  const char *r = strpbrk (p1, p2);
! 
! 	  if (r == NULL)
! 	    return const0_rtx;
! 
! 	  /* Return an offset into the constant string argument.  */
! 	  tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
! 			      fold_convert (TREE_TYPE (s1),
! 					    ssize_int (r - p1))));
! 	  return expand_expr (tmp, target, mode, EXPAND_NORMAL);
! 	}
! 
!       if (p2[0] == '\0')
! 	{
! 	  /* strpbrk(x, "") == NULL.
! 	     Evaluate and ignore the arguments in case they had
! 	     side-effects.  */
! 	  expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  return const0_rtx;
! 	}
! 
!       if (p2[1] != '\0')
! 	return 0;  /* Really call strpbrk.  */
! 
!       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
!       if (!fn)
! 	return 0;
! 
!       /* New argument list transforming strpbrk(s1, s2) to
! 	 strchr(s1, s2[0]).  */
!       arglist = build_tree_list (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p2[0]));
!       arglist = tree_cons (NULL_TREE, s1, arglist);
!       return expand_expr (build_function_call_expr (fn, arglist),
! 			  target, mode, EXPAND_NORMAL);
      }
  }
  
  /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
--- 2514,2526 ----
  static rtx
  expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strpbrk (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
*************** expand_builtin_strcat (tree arglist, rtx
*** 3982,4027 ****
  static rtx
  expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist,
! 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree dst = TREE_VALUE (arglist),
! 	src = TREE_VALUE (TREE_CHAIN (arglist)),
! 	len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
!       const char *p = c_getstr (src);
! 
!       /* If the requested length is zero, or the src parameter string
!           length is zero, return the dst parameter.  */
!       if (integer_zerop (len) || (p && *p == '\0'))
! 	{
! 	  /* Evaluate and ignore the src and len parameters in case
! 	     they have side-effects.  */
! 	  expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  return expand_expr (dst, target, mode, EXPAND_NORMAL);
! 	}
! 
!       /* If the requested len is greater than or equal to the string
!          length, call strcat.  */
!       if (TREE_CODE (len) == INTEGER_CST && p
! 	  && compare_tree_int (len, strlen (p)) >= 0)
! 	{
! 	  tree newarglist
! 	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
! 	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
! 
! 	  /* If the replacement _DECL isn't initialized, don't do the
! 	     transformation.  */
! 	  if (!fn)
! 	    return 0;
! 
! 	  return expand_expr (build_function_call_expr (fn, newarglist),
! 			      target, mode, EXPAND_NORMAL);
! 	}
!       return 0;
      }
  }
  
  /* Expand expression EXP, which is a call to the strspn builtin.
--- 3837,3850 ----
  static rtx
  expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist,
! 			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strncat (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Expand expression EXP, which is a call to the strspn builtin.
*************** expand_builtin_strncat (tree arglist, rt
*** 4031,4061 ****
  static rtx
  expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
! 
!       /* If both arguments are constants, evaluate at compile-time.  */
!       if (p1 && p2)
! 	{
! 	  const size_t r = strspn (p1, p2);
! 	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
! 	}
! 
!       /* If either argument is "", return 0.  */
!       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
! 	{
! 	  /* Evaluate and ignore both arguments in case either one has
! 	     side-effects.  */
! 	  expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  return const0_rtx;
! 	}
!       return 0;
      }
  }
  
  /* Expand expression EXP, which is a call to the strcspn builtin.
--- 3854,3866 ----
  static rtx
  expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strspn (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Expand expression EXP, which is a call to the strcspn builtin.
*************** expand_builtin_strspn (tree arglist, rtx
*** 4065,4109 ****
  static rtx
  expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
!   else
      {
!       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
!       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
! 
!       /* If both arguments are constants, evaluate at compile-time.  */
!       if (p1 && p2)
! 	{
! 	  const size_t r = strcspn (p1, p2);
! 	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
! 	}
! 
!       /* If the first argument is "", return 0.  */
!       if (p1 && *p1 == '\0')
! 	{
! 	  /* Evaluate and ignore argument s2 in case it has
! 	     side-effects.  */
! 	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 	  return const0_rtx;
! 	}
! 
!       /* If the second argument is "", return __builtin_strlen(s1).  */
!       if (p2 && *p2 == '\0')
! 	{
! 	  tree newarglist = build_tree_list (NULL_TREE, s1),
! 	    fn = implicit_built_in_decls[BUILT_IN_STRLEN];
! 
! 	  /* If the replacement _DECL isn't initialized, don't do the
! 	     transformation.  */
! 	  if (!fn)
! 	    return 0;
! 
! 	  return expand_expr (build_function_call_expr (fn, newarglist),
! 			      target, mode, EXPAND_NORMAL);
! 	}
!       return 0;
      }
  }
  
  /* Expand a call to __builtin_saveregs, generating the result in TARGET,
--- 3870,3882 ----
  static rtx
  expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
  {
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_strcspn (arglist);
!       if (result)
! 	return expand_expr (result, target, mode, EXPAND_NORMAL);
      }
+   return 0;
  }
  
  /* Expand a call to __builtin_saveregs, generating the result in TARGET,
*************** expand_builtin_unop (enum machine_mode t
*** 4678,4755 ****
  static rtx
  expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
  {
-   tree len, fn;
-   tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
-     : implicit_built_in_decls[BUILT_IN_FPUTC];
-   tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
-     : implicit_built_in_decls[BUILT_IN_FWRITE];
- 
-   /* If the return value is used, or the replacement _DECL isn't
-      initialized, don't do the transformation.  */
-   if (target != const0_rtx || !fn_fputc || !fn_fwrite)
-     return 0;
- 
    /* Verify the arguments in the original call.  */
!   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
!     return 0;
! 
!   /* Get the length of the string passed to fputs.  If the length
!      can't be determined, punt.  */
!   if (!(len = c_strlen (TREE_VALUE (arglist), 1))
!       || TREE_CODE (len) != INTEGER_CST)
!     return 0;
! 
!   switch (compare_tree_int (len, 1))
      {
!     case -1: /* length is 0, delete the call entirely .  */
!       {
! 	/* Evaluate and ignore the argument in case it has
!            side-effects.  */
! 	expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
! 		     VOIDmode, EXPAND_NORMAL);
! 	return const0_rtx;
!       }
!     case 0: /* length is 1, call fputc.  */
!       {
! 	const char *p = c_getstr (TREE_VALUE (arglist));
! 
! 	if (p != NULL)
! 	  {
! 	    /* New argument list transforming fputs(string, stream) to
! 	       fputc(string[0], stream).  */
! 	    arglist = build_tree_list (NULL_TREE,
! 				       TREE_VALUE (TREE_CHAIN (arglist)));
! 	    arglist = tree_cons (NULL_TREE,
! 				 build_int_cst (NULL_TREE, p[0]),
! 				 arglist);
! 	    fn = fn_fputc;
! 	    break;
! 	  }
!       }
!       /* Fall through.  */
!     case 1: /* length is greater than 1, call fwrite.  */
!       {
! 	tree string_arg;
! 
! 	/* If optimizing for size keep fputs.  */
! 	if (optimize_size)
! 	  return 0;
! 	string_arg = TREE_VALUE (arglist);
! 	/* New argument list transforming fputs(string, stream) to
! 	   fwrite(string, 1, len, stream).  */
! 	arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
! 	arglist = tree_cons (NULL_TREE, len, arglist);
! 	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
! 	arglist = tree_cons (NULL_TREE, string_arg, arglist);
! 	fn = fn_fwrite;
! 	break;
!       }
!     default:
!       gcc_unreachable ();
      }
! 
!   return expand_expr (build_function_call_expr (fn, arglist),
! 		      const0_rtx, VOIDmode, EXPAND_NORMAL);
  }
  
  /* Expand a call to __builtin_expect.  We return our argument and emit a
--- 4451,4465 ----
  static rtx
  expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
  {
    /* Verify the arguments in the original call.  */
!   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
      {
!       tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
! 					unlocked, NULL_TREE);
!       if (result)
! 	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
      }
!   return 0;
  }
  
  /* Expand a call to __builtin_expect.  We return our argument and emit a
*************** fold_builtin_strchr (tree arglist)
*** 8728,8736 ****
  	  return fold (build2 (PLUS_EXPR, TREE_TYPE (s1),
  			       s1, build_int_cst (TREE_TYPE (s1), r - p1)));
  	}
- 
-       /* FIXME: Should use here strchrM optab so that ports can optimize
- 	 this.  */
        return 0;
      }
  }
--- 8438,8443 ----



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]