From patchwork Thu Mar 21 04:51:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: JunMa X-Patchwork-Id: 1059792 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-498217-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="G0tZ3mgX"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44Pvff67QCz9sQm for ; Thu, 21 Mar 2019 15:57:09 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=KsKaGw0jmZxP/7yWjQpn+E72vgotctQnbdHXwUJARYPXWtf9M7 oURX9x+rMt35lGpOiJzXCD2pnlNQGBDgZrFGynIg6DixOXmdfy/tE57G+4SJ0/Kt FhEw/f68J9I0NptzTZfotlwR6FlNWHV3hR3ETN/9z4aCuGTfwQ4HV6rc0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=OdfqZ3bqI5bEoO94Cl10Svg+30U=; b=G0tZ3mgXbRMs71WHZaNX 03/jik3cVRZAMM+51BOWxuGT8dUSPCDL5vcPXg3ndg5BLH4RYQ+XE0ngr51S/Ksn rNx2FGP6amThmrsTOko4SN/AhqUPuNuLWrRKb3k4VS5ofOj9xdwfjwStGwhkTgK5 +r6DkDS8kFCFJ1n9B78hXqA= Received: (qmail 16155 invoked by alias); 21 Mar 2019 04:57:01 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 16145 invoked by uid 89); 21 Mar 2019 04:57:01 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-34.9 required=5.0 tests=BAYES_00, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS, UNPARSEABLE_RELAY, USER_IN_DEF_SPF_WL autolearn=ham version=3.3.1 spammy= X-HELO: out30-133.freemail.mail.aliyun.com Received: from out30-133.freemail.mail.aliyun.com (HELO out30-133.freemail.mail.aliyun.com) (115.124.30.133) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 21 Mar 2019 04:56:59 +0000 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R181e4; CH=green; DM=||false|; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01f04455; MF=junma@linux.alibaba.com; NM=1; PH=DS; RN=1; SR=0; TI=SMTPD_---0TNFTu-a_1553143906; Received: from MacBook-Pro-3.local(mailfrom:JunMa@linux.alibaba.com fp:SMTPD_---0TNFTu-a_1553143906) by smtp.aliyun-inc.com(127.0.0.1); Thu, 21 Mar 2019 12:51:47 +0800 To: gcc-patches From: JunMa Subject: [PATCH][Tree-optimization/PR89772]fold memchr builtins for character not in constant nul-padded string Message-ID: <40b287af-4c87-f8d2-daeb-774861f430f9@linux.alibaba.com> Date: Thu, 21 Mar 2019 12:51:46 +0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Thunderbird/60.5.3 MIME-Version: 1.0 X-IsSubscribed: yes Hi For now, gcc can not fold code like: const char a[5] = "123" __builtin_memchr (a, '7', sizeof a) It tries to avoid folding out of string length although length of a is 5. This is a bit conservative, it's safe to folding memchr/bcmp/memcmp builtins when constant string stores in array with some trailing nuls. This patch folds these cases by exposing additional length of trailing nuls in c_getstr(). Bootstrapped/regtested on x86_64-linux, ok for trunk? Regards JunMa gcc/ChangeLog 2019-03-21  Jun Ma     PR Tree-optimization/89772     * fold-const.c (c_getstr): Add new parameter to get length of additional     trailing nuls after constant string.     * gimple-fold.c (gimple_fold_builtin_memchr): consider trailing nuls in     out-of-bound accesses checking.     * fold-const-call.c (fold_const_call): Likewise. gcc/testsuite/ChangeLog 2019-03-21  Jun Ma     PR Tree-optimization/89772     * gcc.dg/builtin-memchr-4.c: New test. --- gcc/fold-const-call.c | 14 +++++++------- gcc/fold-const.c | 14 +++++++------- gcc/fold-const.h | 3 ++- gcc/gimple-fold.c | 5 +++-- gcc/testsuite/gcc.dg/builtin-memchr-4.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-memchr-4.c diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 702c8b4..ea81f6a 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -1720,7 +1720,7 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2) { const char *p0, *p1; char c; - unsigned HOST_WIDE_INT s0, s1; + unsigned HOST_WIDE_INT s0, s1, s3, s4; size_t s2 = 0; switch (fn) { @@ -1756,10 +1756,10 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2) && !TREE_SIDE_EFFECTS (arg0) && !TREE_SIDE_EFFECTS (arg1)) return build_int_cst (type, 0); - if ((p0 = c_getstr (arg0, &s0)) - && (p1 = c_getstr (arg1, &s1)) - && s2 <= s0 - && s2 <= s1) + if ((p0 = c_getstr (arg0, &s0, &s3)) + && (p1 = c_getstr (arg1, &s1, &s4)) + && s2 <= s0 + s3 + && s2 <= s1 + s4) return build_cmp_result (type, memcmp (p0, p1, s2)); return NULL_TREE; @@ -1770,8 +1770,8 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2) && !TREE_SIDE_EFFECTS (arg0) && !TREE_SIDE_EFFECTS (arg1)) return build_int_cst (type, 0); - if ((p0 = c_getstr (arg0, &s0)) - && s2 <= s0 + if ((p0 = c_getstr (arg0, &s0, &s3)) + && s2 <= s0 + s3 && target_char_cst_p (arg1, &c)) { const char *r = (const char *) memchr (p0, c, s2); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index ec28b43..413f0f0 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -14607,10 +14607,13 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off) characters within it if SRC is a reference to a string plus some constant offset). If STRLEN is non-null, store the number of bytes in the string constant including the terminating NUL char. *STRLEN is - typically strlen(P) + 1 in the absence of embedded NUL characters. */ + typically strlen(P) + 1 in the absence of embedded NUL characters. + If TRAILINGNULSLEN is non-null, store the number of trailing NUL chars + after terminating NUL char of pointer P. */ const char * -c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */) +c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */, + unsigned HOST_WIDE_INT *trailingnulslen /* =NULL */) { tree offset_node; tree mem_size; @@ -14639,16 +14642,13 @@ c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */) literal is stored in. */ unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src); unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size); - - /* Ideally this would turn into a gcc_checking_assert over time. */ - if (string_length > string_size) - string_length = string_size; - const char *string = TREE_STRING_POINTER (src); /* Ideally this would turn into a gcc_checking_assert over time. */ if (string_length > string_size) string_length = string_size; + if (trailingnulslen) + *trailingnulslen = string_size - string_length; if (string_length == 0 || offset >= string_size) diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 049fee9..5073138 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -187,7 +187,8 @@ extern bool expr_not_equal_to (tree t, const wide_int &); extern tree const_unop (enum tree_code, tree, tree); extern tree const_binop (enum tree_code, tree, tree, tree); extern bool negate_mathfn_p (combined_fn); -extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL); +extern const char *c_getstr (tree, unsigned HOST_WIDE_INT * = NULL, + unsigned HOST_WIDE_INT * = NULL); extern wide_int tree_nonzero_bits (const_tree); /* Return OFF converted to a pointer offset type suitable as offset for diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 62d2e0a..096b950 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2541,14 +2541,15 @@ gimple_fold_builtin_memchr (gimple_stmt_iterator *gsi) unsigned HOST_WIDE_INT length = tree_to_uhwi (len); unsigned HOST_WIDE_INT string_length; - const char *p1 = c_getstr (arg1, &string_length); + unsigned HOST_WIDE_INT trailingnuls_length; + const char *p1 = c_getstr (arg1, &string_length, &trailingnuls_length); if (p1) { const char *r = (const char *)memchr (p1, c, MIN (length, string_length)); if (r == NULL) { - if (length <= string_length) + if (length <= string_length + trailingnuls_length) { replace_call_with_value (gsi, build_int_cst (ptr_type_node, 0)); return true; diff --git a/gcc/testsuite/gcc.dg/builtin-memchr-4.c b/gcc/testsuite/gcc.dg/builtin-memchr-4.c new file mode 100644 index 0000000..c37df60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-memchr-4.c @@ -0,0 +1,30 @@ +/* PR tree-optimization/89772 + Verify that memchr calls with a pointer to a constant character + are folded as expected. + { dg-do compile } + { dg-options "-O1 -Wall -fdump-tree-gimple" } */ + +typedef __SIZE_TYPE__ size_t; +typedef __WCHAR_TYPE__ wchar_t; + +extern void* memchr (const void*, int, size_t); +extern int printf (const char*, ...); +extern void abort (void); + +#define A(expr) \ + ((expr) \ + ? (void)0 \ + : (printf ("assertion failed on line %i: %s\n", \ + __LINE__, #expr), \ + abort ())) + +const char a[8] = {'a',0,'b'}; + +void test_memchr_cst_char (void) +{ + A (!memchr (a, 'c', 2)); + A (!memchr (a, 'c', 5)); + A (!memchr (a, 'c', sizeof a)); +} + +/* { dg-final { scan-tree-dump-not "abort" "gimple" } } */