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]

Re: [PR other/31852] Add __builtin_memchr


Hi again,

everything considered, I would rather propose a very simple variant of my first try - only adds a check on len - consistent with our current memcmp. It's safe and we can always improve the optimization later on. Tested x86_64-linux.

Ok this one for mainline?

Paolo.

////////////////
2007-05-11  Paolo Carlini  <pcarlini@suse.de>

	PR other/31852
	* builtin-types.def: Add BT_FN_PTR_CONST_PTR_INT_SIZE.
	* builtins.def: Add BUILT_IN_MEMCHR, use the latter.
	* builtins.c (fold_builtin_memchr): New.
	(expand_builtin_memchr): Call the latter.
	(expand_builtin, fold_builtin_3): Deal with BUILT_IN_MEMCHR.
	* doc/extend.texi ([Other built-in functions provided by GCC]):
	Document memchr.

/testsuite
2007-05-11  Paolo Carlini  <pcarlini@suse.de>

	PR other/31852
	* gcc.c-torture/execute/builtins/memchr.c: New.
	* gcc.c-torture/execute/builtins/memchr-lib.c: New.
	* gcc.c-torture/execute/builtins/lib/memchr.c: New.
Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 124559)
+++ doc/extend.texi	(working copy)
@@ -5592,6 +5592,7 @@
 @findex lroundf
 @findex lroundl
 @findex malloc
+@findex memchr
 @findex memcmp
 @findex memcpy
 @findex mempcpy
@@ -5836,14 +5837,14 @@
 @code{isgraph}, @code{islower}, @code{isprint}, @code{ispunct},
 @code{isspace}, @code{isupper}, @code{isxdigit}, @code{tolower},
 @code{toupper}, @code{labs}, @code{ldexp}, @code{log10}, @code{log},
-@code{malloc}, @code{memcmp}, @code{memcpy}, @code{memset}, @code{modf},
-@code{pow}, @code{printf}, @code{putchar}, @code{puts}, @code{scanf},
-@code{sinh}, @code{sin}, @code{snprintf}, @code{sprintf}, @code{sqrt},
-@code{sscanf}, @code{strcat}, @code{strchr}, @code{strcmp},
-@code{strcpy}, @code{strcspn}, @code{strlen}, @code{strncat},
-@code{strncmp}, @code{strncpy}, @code{strpbrk}, @code{strrchr},
-@code{strspn}, @code{strstr}, @code{tanh}, @code{tan}, @code{vfprintf},
-@code{vprintf} and @code{vsprintf}
+@code{malloc}, @code{memchr}, @code{memcmp}, @code{memcpy},
+@code{memset}, @code{modf}, @code{pow}, @code{printf}, @code{putchar},
+@code{puts}, @code{scanf}, @code{sinh}, @code{sin}, @code{snprintf},
+@code{sprintf}, @code{sqrt}, @code{sscanf}, @code{strcat},
+@code{strchr}, @code{strcmp}, @code{strcpy}, @code{strcspn},
+@code{strlen}, @code{strncat}, @code{strncmp}, @code{strncpy},
+@code{strpbrk}, @code{strrchr}, @code{strspn}, @code{strstr},
+@code{tanh}, @code{tan}, @code{vfprintf}, @code{vprintf} and @code{vsprintf}
 are all recognized as built-in functions unless
 @option{-fno-builtin} is specified (or @option{-fno-builtin-@var{function}}
 is specified for an individual function).  All of these functions have
Index: builtins.c
===================================================================
--- builtins.c	(revision 124559)
+++ builtins.c	(working copy)
@@ -105,6 +105,7 @@
 static rtx expand_builtin_va_start (tree);
 static rtx expand_builtin_va_end (tree);
 static rtx expand_builtin_va_copy (tree);
+static rtx expand_builtin_memchr (tree, rtx, enum machine_mode);
 static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
@@ -172,6 +173,7 @@
 static tree fold_builtin_bitop (tree, tree);
 static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int);
 static tree fold_builtin_strchr (tree, tree, tree);
+static tree fold_builtin_memchr (tree, tree, tree, tree);
 static tree fold_builtin_memcmp (tree, tree, tree);
 static tree fold_builtin_strcmp (tree, tree);
 static tree fold_builtin_strncmp (tree, tree, tree);
@@ -3978,6 +3980,26 @@
 				     const0_rtx, VOIDmode, exp);
 }
 
+/* Expand a call to the memchr builtin.  Return NULL_RTX if we failed the
+   caller should emit a normal call, otherwise try to get the result
+   in TARGET, if convenient (and in mode MODE if that's convenient).  */
+
+static rtx
+expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode)
+{
+  if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE,
+			INTEGER_TYPE, VOID_TYPE))
+    {
+      tree type = TREE_TYPE (exp);
+      tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0),
+					 CALL_EXPR_ARG (exp, 1),
+					 CALL_EXPR_ARG (exp, 2), type);
+      if (result)
+	return expand_expr (result, target, mode, EXPAND_NORMAL);
+    }
+  return NULL_RTX;
+}
+
 /* Expand expression EXP, which is a call to the memcmp built-in function.
    Return NULL_RTX if we failed and the
    caller should emit a normal call, otherwise try to get the result in
@@ -6345,6 +6367,12 @@
 	return target;
       break;
 
+    case BUILT_IN_MEMCHR:
+      target = expand_builtin_memchr (exp, target, mode);
+      if (target)
+	return target;
+      break;
+
     case BUILT_IN_BCMP:
     case BUILT_IN_MEMCMP:
       target = expand_builtin_memcmp (exp, target, mode);
@@ -8654,6 +8682,48 @@
 		       build_call_expr (fn, 3, dest, src, len));
 }
 
+/* Fold function call to builtin memchr.  ARG1, ARG2 and LEN are the
+   arguments to the call, and TYPE is its return type.
+   Return NULL_TREE if no simplification can be made.  */
+
+static tree
+fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type)
+{
+  if (!validate_arg (arg1, POINTER_TYPE)
+      || !validate_arg (arg2, INTEGER_TYPE)
+      || !validate_arg (len, INTEGER_TYPE))
+    return NULL_TREE;
+  else
+    {
+      const char *p1;
+
+      if (TREE_CODE (arg2) != INTEGER_CST
+	  || !host_integerp (len, 1))
+	return NULL_TREE;
+
+      p1 = c_getstr (arg1);
+      if (p1 && compare_tree_int (len, strlen (p1) + 1) <= 0)
+	{
+	  char c;
+	  const char *r;
+	  tree tem;
+
+	  if (target_char_cast (arg2, &c))
+	    return NULL_TREE;
+
+	  r = memchr (p1, c, tree_low_cst (len, 1));
+
+	  if (r == NULL)
+	    return build_int_cst (TREE_TYPE (arg1), 0);
+
+	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (arg1), arg1,
+			     build_int_cst (TREE_TYPE (arg1), r - p1));
+	  return fold_convert (type, tem);
+	}
+      return NULL_TREE;
+    }
+}
+
 /* Fold function call to builtin memcmp with arguments ARG1 and ARG2.
    Return NULL_TREE if no simplification can be made.  */
 
@@ -9983,6 +10053,9 @@
     case BUILT_IN_STRNCMP:
       return fold_builtin_strncmp (arg0, arg1, arg2);
 
+    case BUILT_IN_MEMCHR:
+      return fold_builtin_memchr (arg0, arg1, arg2, type);
+
     case BUILT_IN_BCMP:
     case BUILT_IN_MEMCMP:
       return fold_builtin_memcmp (arg0, arg1, arg2);;
Index: testsuite/gcc.c-torture/execute/builtins/memchr.c
===================================================================
--- testsuite/gcc.c-torture/execute/builtins/memchr.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/builtins/memchr.c	(revision 0)
@@ -0,0 +1,38 @@
+/* Copyright (C) 2007  Free Software Foundation.
+
+   Ensure all expected transformations of builtin memchr occur
+   and perform correctly.
+
+   Written by Paolo Carlini, 10/5/2007.  */
+
+extern void abort (void);
+typedef __SIZE_TYPE__ size_t;
+extern void *memchr (const void *, int, size_t);
+
+void
+main_test (void)
+{
+  const char* const foo1 = "hello world";
+
+  if (memchr (foo1, 'x', 11))
+    abort ();
+  if (memchr (foo1, 'o', 11) != foo1 + 4)
+    abort ();
+  if (memchr (foo1, 'w', 2))
+    abort ();
+  if (memchr (foo1 + 5, 'o', 6) != foo1 + 7)
+    abort ();
+  if (memchr (foo1, 'd', 11) != foo1 + 10)
+    abort ();
+  if (memchr (foo1, 'd', 10))
+    abort ();
+  if (memchr (foo1, '\0', 11))
+    abort ();
+  if (memchr (foo1, '\0', 12) != foo1 + 11)
+    abort ();
+
+  /* Test at least one instance of the __builtin_ style.  We do this
+     to ensure that it works and that the prototype is correct.  */
+  if (__builtin_memchr (foo1, 'r', 11) != foo1 + 8)
+    abort ();
+}
Index: testsuite/gcc.c-torture/execute/builtins/lib/memchr.c
===================================================================
--- testsuite/gcc.c-torture/execute/builtins/lib/memchr.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/builtins/lib/memchr.c	(revision 0)
@@ -0,0 +1,21 @@
+extern void abort(void);
+extern int inside_main;
+
+void *
+memchr (const void *s, int c, __SIZE_TYPE__ n)
+{
+  const unsigned char uc = c;
+  const unsigned char *sp;
+
+#ifdef __OPTIMIZE__
+  if (inside_main)
+    abort ();
+#endif
+
+  sp = s;
+  for (; n != 0; ++sp, --n)
+    if (*sp == uc)
+      return (void *) sp;
+
+  return 0;
+}
Index: testsuite/gcc.c-torture/execute/builtins/memchr-lib.c
===================================================================
--- testsuite/gcc.c-torture/execute/builtins/memchr-lib.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/builtins/memchr-lib.c	(revision 0)
@@ -0,0 +1 @@
+#include "lib/memchr.c"
Index: builtin-types.def
===================================================================
--- builtin-types.def	(revision 124559)
+++ builtin-types.def	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -371,6 +371,8 @@
 		     BT_I16, BT_I16)
 DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
 		     BT_PTR, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_INT_SIZE, BT_PTR,
+		     BT_CONST_PTR, BT_INT, BT_SIZE)
 
 DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
 		     BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
Index: builtins.def
===================================================================
--- builtins.def	(revision 124559)
+++ builtins.def	(working copy)
@@ -502,6 +502,7 @@
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL)
+DEF_LIB_BUILTIN        (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL)
 DEF_LIB_BUILTIN        (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL)
 DEF_LIB_BUILTIN        (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
 DEF_LIB_BUILTIN        (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)

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