This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Optimize strlen comparisons against zero (take 2)
- To: <gcc-patches at gcc dot gnu dot org>
- Subject: [PATCH] Optimize strlen comparisons against zero (take 2)
- From: Roger Sayle <roger at eyesopen dot com>
- Date: Mon, 5 Nov 2001 18:18:25 -0700 (MST)
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