diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-11-14 23:36:24 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-11-14 23:36:24 +0000 |
commit | 53e0ea7ee1d078421797d8eb0122a4ad12ffec45 (patch) | |
tree | 139b295f03452e9723e5c4b561710542d0d2a2b0 /gcc/fold-const.c | |
parent | e9edc08139380b4d3a61d7342c99e9e81ff3b567 (diff) | |
download | gcc-53e0ea7ee1d078421797d8eb0122a4ad12ffec45.tar.gz |
* fold-const.c (fold): Optimize strlen comparisons against zero.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47029 138bc75d-0d04-0410-961f-82ee72b054a4
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 a60930bade6..d6769d6f232 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. |