summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-14 23:36:24 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-14 23:36:24 +0000
commit53e0ea7ee1d078421797d8eb0122a4ad12ffec45 (patch)
tree139b295f03452e9723e5c4b561710542d0d2a2b0 /gcc/fold-const.c
parente9edc08139380b4d3a61d7342c99e9e81ff3b567 (diff)
downloadgcc-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.c27
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.