From patchwork Thu Aug 11 10:36:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prathamesh Kulkarni X-Patchwork-Id: 73733 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp37391qga; Thu, 11 Aug 2016 03:36:39 -0700 (PDT) X-Received: by 10.98.50.2 with SMTP id y2mr15797483pfy.138.1470911799917; Thu, 11 Aug 2016 03:36:39 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id dg3si2676133pad.63.2016.08.11.03.36.39 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Aug 2016 03:36:39 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-433777-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-433777-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-433777-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; q=dns; s=default; b=b+4PjTRV4iGlNpB ilc5I9NcwU5ddi/E1bNK8ndImoQ6ZM/VfpHmcQzdyGLKisLOXLaYddEjy1RpImpL Wwq+mjkoOSYSTmvjNGKEmqP73EFLDq15F/KAo5N2tv5WaiJYlfK7iryoHvefGOl9 XcZRGGT2+FqD8uZ+d1dHGoki5N8Q= 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 :mime-version:in-reply-to:references:from:date:message-id :subject:to:cc:content-type; s=default; bh=iL+Yjf+DJrnlHAIcsBcwX OfDiDQ=; b=Tsz33AoNb9AtGHbVTbJg1Xm+LcJVyp/Q0NsCaiMUKau+O0OYNXSMx nHpZCZSxFOLPa5iysvOVC96mviKKo0DMf26NRLroVL4Y/22MQ011tOUnxHWUcU5n AoJBfcHz9AeUyxoSzkLa8B9BVqy3sxc3oPDPUjF1/cFgauunVrvNfA= Received: (qmail 27899 invoked by alias); 11 Aug 2016 10:36:23 -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 27877 invoked by uid 89); 11 Aug 2016 10:36:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_05, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:fdumpt, sk:fdump-t, sk:todo_up, sk:todo_fl X-HELO: mail-io0-f175.google.com Received: from mail-io0-f175.google.com (HELO mail-io0-f175.google.com) (209.85.223.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 11 Aug 2016 10:36:12 +0000 Received: by mail-io0-f175.google.com with SMTP id m101so2107429ioi.2 for ; Thu, 11 Aug 2016 03:36:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=MK1iSAjLhWXt4liu70bYUHxmxOFELsM1UTEh8vbx80M=; b=BbzWTAIVHDH0l4dwfA+1QEeE0eJ/KHOJQrpdN5cW0pYMSJlYgx6gd2hANq8bQNoCqK y9KlU2qTqCa8NKI36bG1piYehInBVuAywgPbfj+ym5YuMLloBEgINUmsxi71U6CgcaXd 5uj3tzpu/nPMb1U/HjfWq4hZK/bmJwm9cEwUnn1CxAXGiJ7CNEKxPtm4PyVMvhxiuNbQ H806CimBZQeHieBc6uNEdf8oJZNTOerPeuwty2wyFlBjEU/OU9yReLUB9Kx/WVm4rhWb xyOH2jAOQZc4C8VFFkEnp2HP/VbxfTSH8ai+wKuxWNjxxrVLnGTgbmtlEiFuQuujKCWs XLzQ== X-Gm-Message-State: AEkoousewuxA/0/LfpWx582SU3mDXa7+Vkp4b0D3cCmC+WjW08cj646usakxDK3j/GbCfM/oJncWW2v/joJ6XJJi X-Received: by 10.107.159.147 with SMTP id i141mr10290124ioe.29.1470911770846; Thu, 11 Aug 2016 03:36:10 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.208.18 with HTTP; Thu, 11 Aug 2016 03:36:10 -0700 (PDT) In-Reply-To: References: From: Prathamesh Kulkarni Date: Thu, 11 Aug 2016 16:06:10 +0530 Message-ID: Subject: Re: fold strlen (s) eq/ne 0 to *s eq/ne 0 on GIMPLE To: Richard Biener Cc: gcc Patches X-IsSubscribed: yes On 1 August 2016 at 17:03, Richard Biener wrote: > On Mon, 1 Aug 2016, Prathamesh Kulkarni wrote: > >> Hi Richard, >> The attached patch tries to fold strlen (s) eq/ne 0 to *s eq/ne 0 on GIMPLE. >> I am not sure where was the ideal place to put this transform in and ended up >> adding it to strlen_optimize_stmt(). >> Does that look OK ? >> >> I needed to add TODO_update_ssa to strlen pass, otherwise we hit the >> following assert in execute_todo(): >> if (flag_checking >> && cfun >> && need_ssa_update_p (cfun)) >> gcc_assert (flags & TODO_update_ssa_any); >> >> Bootstrap+test in progress on x86_64-unknown-linux-gnu. > > I believe you should factor small-size part of handle_builtin_memcmp and > re-use that for the code generation part. > > You should also remove the corresponding fold-const.c code I think. Hi, In the attached version, I removed code from fold-const.c, and factored code-gen part into replace_call_cmp. The previous patch incorrectly applied the transform when result of strlen() had multiple uses, thus restricting it to has_single_use. However I suppose we could do better by checking if each immediate use of the result is involved in compare against 0 and in that case perform the transform ? Bootstrap + test in progress on x86_64-unknown-linux-gnu Thanks, Prathamesh > > Richard. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c5d9a79..309ef38 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10676,30 +10676,6 @@ fold_binary_loc (location_t loc, return t1; } - /* 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 (TREE_CODE (arg0) == CALL_EXPR - && integer_zerop (arg1)) - { - tree fndecl = get_callee_fndecl (arg0); - - if (fndecl - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN - && call_expr_nargs (arg0) == 1 - && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE) - { - tree iref = build_fold_indirect_ref_loc (loc, - CALL_EXPR_ARG (arg0, 0)); - return fold_build2_loc (loc, code, type, iref, - build_int_cst (TREE_TYPE (iref), 0)); - } - } - /* Fold (X >> C) != 0 into X < 0 if C is one less than the width of X. Similarly fold (X >> C) == 0 into X >= 0. */ if (TREE_CODE (arg0) == RSHIFT_EXPR diff --git a/gcc/testsuite/gcc.dg/strlenopt-30.c b/gcc/testsuite/gcc.dg/strlenopt-30.c new file mode 100644 index 0000000..b041d86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-30.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-strlen" } */ + +__attribute__((noinline, no_icf)) +_Bool f1(const char *s) +{ + unsigned long len = __builtin_strlen (s); + _Bool ret = (len == 0); + return ret; +} + +/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 9d7b4df..4ada2ee 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -45,6 +45,8 @@ along with GCC; see the file COPYING3. If not see #include "ipa-chkp.h" #include "tree-hash-traits.h" #include "builtins.h" +#include "tree-pretty-print.h" +#include "tree-cfg.h" /* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value is an index into strinfo vector, negative value stands for @@ -1937,6 +1939,36 @@ handle_builtin_memset (gimple_stmt_iterator *gsi) return false; } +static void +replace_call_by_cmp (gimple_stmt_iterator *gsi, location_t loc, + tree type, tree arg1, tree arg2, + tree res_type, enum tree_code cmp_code) +{ + tree ptrtype = build_pointer_type_for_mode (char_type_node, ptr_mode, true); + tree off = build_int_cst (ptrtype, 0); + arg1 = build2_loc (loc, MEM_REF, type, arg1, off); + tree tem1 = fold_const_aggregate_ref (arg1); + if (tem1) + arg1 = tem1; + + if (POINTER_TYPE_P (TREE_TYPE (arg2))) + { + arg2 = build2_loc (loc, MEM_REF, type, arg2, off); + tree tem2 = fold_const_aggregate_ref (arg2); + if (tem2) + arg2 = tem2; + } + else + gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (arg2))); + + tree res = fold_convert_loc (loc, res_type, + fold_build2_loc (loc, cmp_code, + boolean_type_node, + arg1, arg2)); + + gimplify_and_update_call_from_tree (gsi, res); +} + /* Handle a call to memcmp. We try to handle small comparisons by converting them to load and compare, and replacing the call to memcmp with a __builtin_memcmp_eq call where possible. */ @@ -1994,25 +2026,11 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi) && (align >= leni || !SLOW_UNALIGNED_ACCESS (mode, align))) { location_t loc = gimple_location (stmt2); - tree type, off; + tree type; type = build_nonstandard_integer_type (leni, 1); gcc_assert (GET_MODE_BITSIZE (TYPE_MODE (type)) == leni); - tree ptrtype = build_pointer_type_for_mode (char_type_node, - ptr_mode, true); - off = build_int_cst (ptrtype, 0); - arg1 = build2_loc (loc, MEM_REF, type, arg1, off); - arg2 = build2_loc (loc, MEM_REF, type, arg2, off); - tree tem1 = fold_const_aggregate_ref (arg1); - if (tem1) - arg1 = tem1; - tree tem2 = fold_const_aggregate_ref (arg2); - if (tem2) - arg2 = tem2; - res = fold_convert_loc (loc, TREE_TYPE (res), - fold_build2_loc (loc, NE_EXPR, - boolean_type_node, - arg1, arg2)); - gimplify_and_update_call_from_tree (gsi, res); + replace_call_by_cmp (gsi, loc, type, arg1, arg2, + TREE_TYPE (res), NE_EXPR); return false; } } @@ -2302,6 +2320,41 @@ strlen_optimize_stmt (gimple_stmt_iterator *gsi) else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) handle_pointer_plus (gsi); } + /* strlen (s) eq/ne 0 -> *s eq/ne 0. */ + else if (TREE_CODE (lhs) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (lhs))) + { + tree rhs2 = gimple_assign_rhs2 (stmt); + tree_code code = gimple_assign_rhs_code (stmt); + + if ((code == EQ_EXPR || code == NE_EXPR) && integer_zerop (rhs2)) + { + tree rhs1 = gimple_assign_rhs1 (stmt); + if (TREE_CODE (rhs1) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (rhs1); + if (gcall *call_stmt = dyn_cast (def_stmt)) + { + tree callee = gimple_call_fndecl (call_stmt); + if (valid_builtin_call (call_stmt) + && DECL_FUNCTION_CODE (callee) == BUILT_IN_STRLEN) + { + tree call_arg = gimple_call_arg (call_stmt, 0); + tree call_lhs = gimple_call_lhs (call_stmt); + + if (has_single_use (call_lhs)) + { + gimple_stmt_iterator call_gsi = gsi_for_stmt (call_stmt); + replace_call_by_cmp (&call_gsi, gimple_location (call_stmt), + TREE_TYPE (rhs2), call_arg, rhs2, TREE_TYPE (call_lhs), + code); + gimple_assign_set_rhs_with_ops (gsi, CONVERT_EXPR, call_lhs); + update_stmt (stmt); + } + } + } + } + } + } else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs)) { tree type = TREE_TYPE (lhs); @@ -2505,7 +2558,7 @@ const pass_data pass_data_strlen = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_update_ssa_only_virtuals, /* todo_flags_finish */ }; class pass_strlen : public gimple_opt_pass