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]

[PATCH] Optimize strlen comparisons against zero (take 2)



Opps.  I noticed that first time around I'd forgot to include a
ChangeLog entry for this patch.


The following patch optimizes comparisons of the return value from
strlen against zero.  This optimization transforms the expression
"strlen(ptr) > 0" into the equivalent "*((const char*)ptr) != 0",
where the call is actually to the GCC builtin.  Checking whether
the first character of the string is NUL is more efficient than
calculating the entire string length, only to ignore the actual
result.

Tested by "make bootstrap" and "make check-gcc" on i686-pc-linux-gnu
with no new regressions.  The patch includes a test case to check that
the transformation is being applied and that it doesn't change program
behaviour.


2001-11-03  Roger Sayle <roger@eyesopen.com>

	* fold-const.c (fold): Optimize strlen comparisons against zero.
	* string-opt-13.c: New testcase.


*** fold-const.c	2001/10/21 21:31:59	1.172
--- fold-const.c	2001/11/03 18:49:54
*************** fold (expr)
*** 6858,6863 ****
--- 6858,6892 ----
  			      fold (build (code, type, imag0, imag1))));
  	}

+         /* Optimize "strlen(ptr) == 0" to "*((const char*)ptr) == 0"
+            and "strlen(ptr) != 0" to "*((const char*)ptr) != 0".  */
+         if (integer_zerop (arg1)
+             && TREE_CODE (arg0) == CALL_EXPR
+             && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
+           {
+             tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+             tree arglist;
+
+             if (TREE_CODE (fndecl) == FUNCTION_DECL
+                 && DECL_BUILT_IN (fndecl)
+                 && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+                 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+                 && (arglist = TREE_OPERAND (arg0, 1))
+                 && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist)))
+                    == POINTER_TYPE
+                 && ! TREE_CHAIN (arglist))
+             {
+               tree cst_char_node = build_type_variant (char_type_node, 1, 0);
+               tree cst_char_ptr_node = build_pointer_type (cst_char_node);
+               return fold (build (code, type,
+                                   build1 (INDIRECT_REF, cst_char_node,
+                                           build1 (NOP_EXPR,
+                                                   cst_char_ptr_node,
+                                                   TREE_VALUE(arglist))),
+                                   integer_zero_node));
+             }
+           }
+
        /* From here on, the only cases we handle are when the result is
  	 known to be a constant.

*** /dev/null
--- gcc.c-torture/execute/string-opt-13.c	Sat Nov  3 11:53:33 2001
***************
*** 0 ****
--- 1,58 ----
+ /* Copyright (C) 2001  Free Software Foundation.
+
+    Ensure all builtin strlen comparisons against zero are optimized
+    and perform correctly. The multiple calls to strcpy are to prevent
+    the potentially "pure" strlen calls from being removed by CSE.
+
+    Written by Roger Sayle, 11/02/2001.  */
+
+ extern void abort (void);
+ typedef __SIZE_TYPE__ size_t;
+ extern size_t strlen (const char *);
+ extern char *strcpy (char *, const char *);
+
+ int
+ main ()
+ {
+   char str[8];
+   char *ptr;
+
+   ptr = str;
+   strcpy (ptr, "nts");
+   if (strlen (ptr) == 0)
+     abort ();
+
+   strcpy (ptr, "nts");
+   if (strlen (ptr) < 1)
+     abort ();
+
+   strcpy (ptr, "nts");
+   if (strlen (ptr) <= 0)
+     abort ();
+
+   strcpy (ptr, "nts");
+   if (strlen (ptr+3) != 0)
+     abort ();
+
+   strcpy (ptr, "nts");
+   if (strlen (ptr+3) > 0)
+     abort ();
+
+   strcpy (ptr, "nts");
+   if (strlen (str+3) >= 1)
+     abort ();
+
+   return 0;
+ }
+
+ #ifdef __OPTIMIZE__
+ /* When optimizing, all the above cases should be transformed into
+    something else.  So any remaining calls to the original function
+    should abort.  */
+ static size_t
+ strlen (const char *s)
+ {
+   abort ();
+ }
+ #endif
+


--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-438-3470




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