From patchwork Sun Dec 5 21:58:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 48518 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B4719385842B for ; Sun, 5 Dec 2021 21:59:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B4719385842B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638741544; bh=kb2M543GvK/iyZ+QCHi0t7MZsIA/bQfI2LfZB3ApUqA=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=jLmoJkI1uWHSXLrod4Z0JXO2INVDWZuRZzvuUEClaCfbAPtTKF2Vi/473WwgaZPpT sSEquuJpKyCTKE7VvJz5xyFvz7mNrufbHuIn1xRLXvNlOJzpy32/3g/eLHRU4Wk+z7 jRd3piQ7tfMunYJhnnQof+iI7w5uDiFFjxgASIHA= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 19F283858422 for ; Sun, 5 Dec 2021 21:58:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 19F283858422 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D55BF113E for ; Sun, 5 Dec 2021 13:58:33 -0800 (PST) Received: from localhost (e121540-lin.manchester.arm.com [10.32.98.88]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7782F3F5A1 for ; Sun, 5 Dec 2021 13:58:33 -0800 (PST) To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [PATCH] alias: Optimise call_may_clobber_ref_p Date: Sun, 05 Dec 2021 21:58:32 +0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Richard Sandiford via Gcc-patches From: Richard Sandiford Reply-To: Richard Sandiford Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" When compiling an optabs.ii at -O2 with a release-checking build, we spent a lot of time in call_may_clobber_ref_p. One of the first things the function tries is the get_modref_function_summary approach, but that also seems to be the most expensive check. At least for the optabs.ii test, most of the things g_m_f_s could handle could also be handled by points-to analysis, which is much cheaper. This patch therefore rearranges the tests in approximate order of cheapness. One wart is that points-to analysis can't be used on its own for this purpose; it has to be used in conjunction with check_fnspec. This is because the argument information in the fnspec is not reflected in the points-to information, which instead contains overly optimistic (rather than conservatively pessimistic) information. Specifically, find_func_aliases_for_builtin_call short-circuits the handle_rhs_call/handle_call_arg logic and doesn't itself add any compensating information about the arguments. This means that: free (foo) does not have an points-to information for foo (it has an empty set instead). It would be good to fix that for compile-time reasons if nothing else. Doing points-to analysis without check_fnspec gave a measureable speed-up, since PTA resolved the vast majority of queries, and (as expected) the vast majority of calls had no fnspec. This gave about a ~2% compile-time improvement for the test above. Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? Richard gcc/ * tree-ssa-alias.c (call_may_clobber_ref_p_1): Reorder checks to the cheaper ones come first. --- gcc/tree-ssa-alias.c | 145 +++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 75 deletions(-) diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 88fd7821c5e..573766278bc 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2952,9 +2952,6 @@ ref_maybe_used_by_stmt_p (gimple *stmt, tree ref, bool tbaa_p) bool call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) { - tree base; - tree callee; - /* If the call is pure or const it cannot clobber anything. */ if (gimple_call_flags (call) & (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS)) @@ -2977,9 +2974,64 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) break; } - callee = gimple_call_fndecl (call); + tree base = ao_ref_base (ref); + if (base + && (TREE_CODE (base) == SSA_NAME + || CONSTANT_CLASS_P (base))) + return false; + + /* A call that is not without side-effects might involve volatile + accesses and thus conflicts with all other volatile accesses. */ + if (ref->volatile_p) + return true; + + bool independent_pt = false; + if (base && DECL_P (base)) + { + /* If the reference is based on a decl that is not aliased the call + cannot possibly clobber it. */ + if (!may_be_aliased (base) + /* But local non-readonly statics can be modified through + recursion or the call may implement a threading barrier which + we must treat as may-def. */ + && (TREE_READONLY (base) + || !is_global_var (base))) + return false; - if (callee != NULL_TREE && !ref->volatile_p) + auto clobbers = gimple_call_clobber_set (call); + independent_pt = !pt_solution_includes (clobbers, base); + } + else if (base + && (TREE_CODE (base) == MEM_REF + || TREE_CODE (base) == TARGET_MEM_REF) + && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) + { + tree addr = TREE_OPERAND (base, 0); + + /* If the reference is based on a pointer that points to memory that + may not be written to then the call cannot possibly clobber it. */ + if (SSA_NAME_POINTS_TO_READONLY_MEMORY (addr)) + return false; + + /* Check if the base variable is call-clobbered. */ + if (auto *pi = SSA_NAME_PTR_INFO (addr)) + { + auto clobbers = gimple_call_clobber_set (call); + independent_pt = !pt_solutions_intersect (clobbers, &pi->pt); + } + } + + /* Points-to information needs to be tested in conjunction with + check_fnspec. The fnspec argument information for built-in + functions is excluded from the PT sets. */ + int res = check_fnspec (call, ref, true); + if (res >= 0) + return res; + + if (independent_pt) + return false; + + if (tree callee = gimple_call_fndecl (call)) { struct cgraph_node *node = cgraph_node::get (callee); if (node) @@ -3017,77 +3069,20 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool tbaa_p) return false; } alias_stats.modref_clobber_may_alias++; - } - } - } - - base = ao_ref_base (ref); - if (!base) - return true; - - if (TREE_CODE (base) == SSA_NAME - || CONSTANT_CLASS_P (base)) - return false; - - /* A call that is not without side-effects might involve volatile - accesses and thus conflicts with all other volatile accesses. */ - if (ref->volatile_p) - return true; - - /* If the reference is based on a decl that is not aliased the call - cannot possibly clobber it. */ - if (DECL_P (base) - && !may_be_aliased (base) - /* But local non-readonly statics can be modified through recursion - or the call may implement a threading barrier which we must - treat as may-def. */ - && (TREE_READONLY (base) - || !is_global_var (base))) - return false; - - /* If the reference is based on a pointer that points to memory - that may not be written to then the call cannot possibly clobber it. */ - if ((TREE_CODE (base) == MEM_REF - || TREE_CODE (base) == TARGET_MEM_REF) - && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME - && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base, 0))) - return false; - - if (int res = check_fnspec (call, ref, true)) - { - if (res == 1) - return true; - } - else - return false; - - /* Check if base is a global static variable that is not written - by the function. */ - if (callee != NULL_TREE && VAR_P (base) && TREE_STATIC (base)) - { - struct cgraph_node *node = cgraph_node::get (callee); - bitmap written; - int id; - - if (node - && (id = ipa_reference_var_uid (base)) != -1 - && (written = ipa_reference_get_written_global (node)) - && !bitmap_bit_p (written, id)) - return false; - } - - /* Check if the base variable is call-clobbered. */ - if (DECL_P (base)) - return pt_solution_includes (gimple_call_clobber_set (call), base); - else if ((TREE_CODE (base) == MEM_REF - || TREE_CODE (base) == TARGET_MEM_REF) - && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) - { - struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)); - if (!pi) - return true; + } - return pt_solutions_intersect (gimple_call_clobber_set (call), &pi->pt); + /* Check if base is a global static variable that is not written + by the function. */ + bitmap written; + int id; + if (base + && VAR_P (base) + && TREE_STATIC (base) + && (id = ipa_reference_var_uid (base)) != -1 + && (written = ipa_reference_get_written_global (node)) + && !bitmap_bit_p (written, id)) + return false; + } } return true;