diff options
author | Roger Sayle <roger@eyesopen.com> | 2001-11-14 23:36:24 +0000 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-11-14 15:36:24 -0800 |
commit | d59b3b679c686f86430a4a6fc5f24058ce2e5174 (patch) | |
tree | 139b295f03452e9723e5c4b561710542d0d2a2b0 /gcc/fold-const.c | |
parent | 81bc01c265b5115163d06812174653e1db13d537 (diff) | |
download | gcc-d59b3b679c686f86430a4a6fc5f24058ce2e5174.zip gcc-d59b3b679c686f86430a4a6fc5f24058ce2e5174.tar.gz gcc-d59b3b679c686f86430a4a6fc5f24058ce2e5174.tar.bz2 |
* fold-const.c (fold): Optimize strlen comparisons against zero.
From-SVN: r47029
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a60930b..d6769d6 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6899,6 +6899,33 @@ fold (expr) fold (build (code, type, imag0, imag1)))); } + /* Optimize comparisons of strlen vs zero to a compare of the + first character of the string vs zero. To wit, + strlen(ptr) == 0 => *ptr == 0 + strlen(ptr) != 0 => *ptr != 0 + Other cases should reduce to one of these two (or a constant) + due to the return value of strlen being unsigned. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && 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)) + return fold (build (code, type, + build1 (INDIRECT_REF, char_type_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. |