From patchwork Mon Dec 6 17:31:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 48540 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 3824E3858426 for ; Mon, 6 Dec 2021 17:31:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3824E3858426 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638811915; bh=mGWhyToW8VPs8TAlWjoZB3bX46ZQol26aIEZ3vbBm7c=; h=Subject:To:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=BqG4WWHu7yGi3jnZGSH67NynjygHjOXn9S54NuNyOK8iLdZl4UfvOkY3JHNSQY895 hsPfJBgHNCMsA8QR8ijs82ciI3kkmVCEaLAUaUH233pKnFOU+dAqufpAr7nLezf4HL hq5rsDrtFZu9RH9AlqcIqzztawrbKTBeGgIR8tdQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by sourceware.org (Postfix) with ESMTPS id 390A93858D28 for ; Mon, 6 Dec 2021 17:31:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 390A93858D28 Received: by mail-ot1-x331.google.com with SMTP id i5-20020a05683033e500b0057a369ac614so14529525otu.10 for ; Mon, 06 Dec 2021 09:31:25 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=mGWhyToW8VPs8TAlWjoZB3bX46ZQol26aIEZ3vbBm7c=; b=jtEK1gQS2mbRP6J4HelkMDww+Etd+9MGYg0NMSVgKFhDnOG8GOihY6bAkGXNuBs1EJ OFnQwJBMNwCt728cZBSjEQCIEBNE0nZ8dBTtUAqUXn4aHM6QzSP+pgedGkAZ30V+9ctR KC7Fovypn8d/R6BBtNo7zrBGN48lxB8JWWMw8ZabNuaGgcW36+Xa7/VPVKTu3BI1xBvd Z6fUpeorLM//cu0Re816fJB2UhaYE/lCNV6gIWbXaap7uIhrlDTPlyzfY4bFqmsre/tr 3Ci6+F89W0rludvznqfJ1deCbazSQ9lsyBppSP94y3GmbkDvZxwFyj3EhbldR5NwEKU/ Q3Eg== X-Gm-Message-State: AOAM532PmT9Cf5T9OwiIgoDz8XXn4BkMGKGc+X0U3Gn1glLwActrW7ub MzbeKOiLbONglBHxwmsEm8UDaETqDEI= X-Google-Smtp-Source: ABdhPJy219gg1SyJu3YLUng5VshibgKCWbQY/kRhvW7JXx5yJe11kTA+Ujz7PREL84l5WZxsgdgyXQ== X-Received: by 2002:a9d:69ce:: with SMTP id v14mr30537539oto.312.1638811884449; Mon, 06 Dec 2021 09:31:24 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id k14sm2823923oil.38.2021.12.06.09.31.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 09:31:24 -0800 (PST) Subject: [PATCH v2] fix PR 103143 To: Jeff Law , gcc-patches References: <65d1e530-a4cc-de27-1198-0dcaa08274bd@gmail.com> Message-ID: Date: Mon, 6 Dec 2021 10:31:23 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" I have broken up the patch into a series of six. Attached is part (1), the fix for the typo that causes PR 103143. On 12/3/21 5:00 PM, Jeff Law wrote: > > > On 11/8/2021 7:34 PM, Martin Sebor via Gcc-patches wrote: >> The pointer-query code that implements compute_objsize() that's >> in turn used by most middle end access warnings now has a few >> warts in it and (at least) one bug.  With the exception of >> the bug the warts aren't behind any user-visible bugs that >> I know of but they do cause problems in new code I've been >> implementing on top of it.  Besides fixing the one bug (just >> a typo) the attached patch cleans up these latent issues: >> >> 1) It moves the bndrng member from the access_ref class to >>    access_data.  As a FIXME in the code notes, the member never >>    did belong in the former and only takes up space in the cache. >> >> 2) The compute_objsize_r() function is big, unwieldy, and tedious >>    to step through because of all the if statements that are better >>    coded as one switch statement.  This change factors out more >>    of its code into smaller handler functions as has been suggested >>    and done a few times before. >> >> 3) (2) exposed a few places where I fail to pass the current >>    GIMPLE statement down to ranger.  This leads to worse quality >>    range info, including possible false positives and negatives. >>    I just spotted these problems in code review but I haven't >>    taken the time to come up with test cases.  This change fixes >>    these oversights as well. >> >> 4) The handling of PHI statements is also in one big, hard-to- >>    follow function.  This change moves the handling of each PHI >>    argument into its own handler which merges it into the previous >>    argument.  This makes the code easier to work with and opens it >>    to reuse also for MIN_EXPR and MAX_EXPR.  (This is primarily >>    used to print informational notes after warnings.) >> >> 5) Finally, the patch factors code to dump each access_ref >>    cached by the pointer_query cache out of pointer_query::dump >>    and into access_ref::dump.  This helps with debugging. >> >> These changes should have no user-visible effect and other than >> a regression test for the typo (PR 103143) come with no tests. >> They've been tested on x86_64-linux. > Sigh.  You've identified 6 distinct changes above.  The 5 you've > enumerated plus a typo fix somewhere.  There's no reason why they need > to be a single patch and many reasons why they should be a series of > independent patches.    Combining them into a single patch isn't how we > do things and it hides the actual bugfix in here. > > Please send a fix for the typo first since that should be able to > trivially go forward.  Then  a patch for item #1.  That should be > trivial to review when it's pulled out from teh rest of the patch. > Beyond that, your choice on ordering, but you need to break this down. > > > > > Jeff > commit 9a5bb7a2b0cdb8654061d9cba543c1408fa7adc9 Author: Martin Sebor Date: Sat Dec 4 16:22:07 2021 -0700 Use the recursive form of compute_objsize [PR 103143]. gcc/ChangeLog: PR middle-end/103143 * pointer-query.cc (gimple_call_return_array): Call compute_objsize_r. gcc/testsuite/ChangeLog: PR middle-end/103143 * gcc.dg/Wstringop-overflow-83.c: New test. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 2ead0271617..25ce4303849 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -199,7 +199,7 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2], bool *past_end, of the source object. */ access_ref aref; tree src = gimple_call_arg (stmt, 1); - if (compute_objsize (src, stmt, 1, &aref, qry) + if (compute_objsize_r (src, stmt, 1, &aref, snlim, qry) && aref.sizrng[1] < offrng[1]) offrng[1] = aref.sizrng[1]; } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-83.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-83.c new file mode 100644 index 00000000000..6928ee4d559 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-83.c @@ -0,0 +1,19 @@ +/* PR middle-end/103143 - ICE due to infinite recursion in pointer-query.cc + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +void foo (size_t x) +{ + struct T { char buf[64]; char buf2[64]; } t; + char *p = &t.buf[8]; + char *r = t.buf2; + size_t i; + + for (i = 0; i < x; i++) + { + r = __builtin_mempcpy (r, p, i); + p = r + 1; + } +} From patchwork Mon Dec 6 17:31:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 48542 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 565423858423 for ; Mon, 6 Dec 2021 17:33:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 565423858423 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638812035; bh=LPBRuagF4rgRdPZeKqIM85I9cZ9o+hfmle/LxrNIRlQ=; h=Subject:To:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Es8I6oXsk6R5V3ym+BZRyOjDU6OIvtWuUR3gXsN+Lm2/+/HvkY3vsOgZiI8K1U3mY 3InbTXv363q8AhOSjzV1BZbKPTRaYGL8MBeLVDv+egVjmqqQ1HJ2cvl630Y3XmLDK1 yIHF/dBa9iYEZja5Fcwc+HA+mafZdW5tL63uUjKg= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oi1-x234.google.com (mail-oi1-x234.google.com [IPv6:2607:f8b0:4864:20::234]) by sourceware.org (Postfix) with ESMTPS id 81E343858002 for ; Mon, 6 Dec 2021 17:31:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 81E343858002 Received: by mail-oi1-x234.google.com with SMTP id n66so22673493oia.9 for ; Mon, 06 Dec 2021 09:31:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=LPBRuagF4rgRdPZeKqIM85I9cZ9o+hfmle/LxrNIRlQ=; b=ZSFTLcZub3GckTl9y95c1jKcnc6jKhU5I/qYoZbGwa/gK3/QIxQLsIObdKEv48VhQ8 3SsC43jiuhWFX0aTsznBNvZslReN0gmpvv4S450Z7bchYHiGiHMxCAqOFgRp4b9kT4sc qIJLih2FVvuR0CJ7gRNXOsfM/03ZvRSqKhjzmmbLQE+ikRfcj8sqpLBapdyAENkB2BpM lMiu+GQTzRu5AQN+blv3UhYj51gPqt5rWUoNvmsy36kloG4AiVDvgFZfjBmtdaoBVLu0 R1f8bxYa4YyBvB+OaXjUMXECFUQyNICTpMKdo5yrYZgYaWFUxu6147QjWOKRaitWA87D ijgQ== X-Gm-Message-State: AOAM533qPewI4vVoQDfI/mP+AqJFAtmm/DZBJVaqYlU8x9lx+GkYZPZH nl/3u/xvRUfXAINVSBaxM6tuUEGiaZs= X-Google-Smtp-Source: ABdhPJxkwg5MR5svQBRVkCkLtclNN2LM092rG6esrKegVLxGBjjNY1nMkFBDMZQOPVcdIb6BM8JrVg== X-Received: by 2002:aca:2319:: with SMTP id e25mr25840956oie.164.1638811900841; Mon, 06 Dec 2021 09:31:40 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id b1sm2317817otj.5.2021.12.06.09.31.40 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 09:31:40 -0800 (PST) Subject: [PATCH v2 2/5] fix up compute_objsize: pass GIMPLE statement to it To: Jeff Law , gcc-patches References: <65d1e530-a4cc-de27-1198-0dcaa08274bd@gmail.com> Message-ID: Date: Mon, 6 Dec 2021 10:31:39 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Attached is the subset of the patch in part (3) below: Pass GIMPLE statement to compute_objsize. It applies on top of patch 1/5. On 12/3/21 5:00 PM, Jeff Law wrote: > > > On 11/8/2021 7:34 PM, Martin Sebor via Gcc-patches wrote: >> The pointer-query code that implements compute_objsize() that's >> in turn used by most middle end access warnings now has a few >> warts in it and (at least) one bug.  With the exception of >> the bug the warts aren't behind any user-visible bugs that >> I know of but they do cause problems in new code I've been >> implementing on top of it.  Besides fixing the one bug (just >> a typo) the attached patch cleans up these latent issues: >> >> 1) It moves the bndrng member from the access_ref class to >>    access_data.  As a FIXME in the code notes, the member never >>    did belong in the former and only takes up space in the cache. >> >> 2) The compute_objsize_r() function is big, unwieldy, and tedious >>    to step through because of all the if statements that are better >>    coded as one switch statement.  This change factors out more >>    of its code into smaller handler functions as has been suggested >>    and done a few times before. >> >> 3) (2) exposed a few places where I fail to pass the current >>    GIMPLE statement down to ranger.  This leads to worse quality >>    range info, including possible false positives and negatives. >>    I just spotted these problems in code review but I haven't >>    taken the time to come up with test cases.  This change fixes >>    these oversights as well. >> >> 4) The handling of PHI statements is also in one big, hard-to- >>    follow function.  This change moves the handling of each PHI >>    argument into its own handler which merges it into the previous >>    argument.  This makes the code easier to work with and opens it >>    to reuse also for MIN_EXPR and MAX_EXPR.  (This is primarily >>    used to print informational notes after warnings.) >> >> 5) Finally, the patch factors code to dump each access_ref >>    cached by the pointer_query cache out of pointer_query::dump >>    and into access_ref::dump.  This helps with debugging. >> >> These changes should have no user-visible effect and other than >> a regression test for the typo (PR 103143) come with no tests. >> They've been tested on x86_64-linux. > Sigh.  You've identified 6 distinct changes above.  The 5 you've > enumerated plus a typo fix somewhere.  There's no reason why they need > to be a single patch and many reasons why they should be a series of > independent patches.    Combining them into a single patch isn't how we > do things and it hides the actual bugfix in here. > > Please send a fix for the typo first since that should be able to > trivially go forward.  Then  a patch for item #1.  That should be > trivial to review when it's pulled out from teh rest of the patch. > Beyond that, your choice on ordering, but you need to break this down. > > > > > Jeff > commit 64d34f249fb98d53ae8fcb3b36b01c2b9b05ea4f Author: Martin Sebor Date: Sat Dec 4 16:57:48 2021 -0700 Pass GIMPLE statement to compute_objsize. gcc/ChangeLog: * gimple-ssa-warn-restrict.c (builtin_access::builtin_access): Pass GIMPLE statement to compute_objsize. * pointer-query.cc (compute_objsize): Add a statement argument. * pointer-query.h (compute_objsize): Define a new overload. diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index d1df9ca8d4f..ca2d4c2c32e 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -777,7 +777,7 @@ builtin_access::builtin_access (range_query *query, gimple *call, if (!POINTER_TYPE_P (TREE_TYPE (addr))) addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - if (tree dstsize = compute_objsize (addr, ostype)) + if (tree dstsize = compute_objsize (addr, call, ostype)) dst.basesize = wi::to_offset (dstsize); else if (POINTER_TYPE_P (TREE_TYPE (addr))) dst.basesize = HOST_WIDE_INT_MIN; @@ -791,7 +791,7 @@ builtin_access::builtin_access (range_query *query, gimple *call, if (!POINTER_TYPE_P (TREE_TYPE (addr))) addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - if (tree srcsize = compute_objsize (addr, ostype)) + if (tree srcsize = compute_objsize (addr, call, ostype)) src.basesize = wi::to_offset (srcsize); else if (POINTER_TYPE_P (TREE_TYPE (addr))) src.basesize = HOST_WIDE_INT_MIN; diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index a8c9671e3ba..c75c4da6b60 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -1645,7 +1645,7 @@ handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype, offset_int orng[2]; tree off = pref->eval (TREE_OPERAND (aref, 1)); range_query *const rvals = qry ? qry->rvals : NULL; - if (!get_offset_range (off, NULL, orng, rvals)) + if (!get_offset_range (off, stmt, orng, rvals)) { /* Set ORNG to the maximum offset representable in ptrdiff_t. */ orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); @@ -1732,7 +1732,7 @@ handle_mem_ref (tree mref, gimple *stmt, int ostype, access_ref *pref, offset_int orng[2]; tree off = pref->eval (TREE_OPERAND (mref, 1)); range_query *const rvals = qry ? qry->rvals : NULL; - if (!get_offset_range (off, NULL, orng, rvals)) + if (!get_offset_range (off, stmt, orng, rvals)) { /* Set ORNG to the maximum offset representable in ptrdiff_t. */ orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); @@ -1948,7 +1948,7 @@ compute_objsize_r (tree ptr, gimple *stmt, int ostype, access_ref *pref, offset_int orng[2]; tree off = pref->eval (TREE_OPERAND (ptr, 1)); - if (get_offset_range (off, NULL, orng, rvals)) + if (get_offset_range (off, stmt, orng, rvals)) pref->add_offset (orng[0], orng[1]); else pref->add_max_offset (); @@ -2197,13 +2197,13 @@ compute_objsize (tree ptr, gimple *stmt, int ostype, access_ref *pref, once callers transition to one of the two above. */ tree -compute_objsize (tree ptr, int ostype, tree *pdecl /* = NULL */, +compute_objsize (tree ptr, gimple *stmt, int ostype, tree *pdecl /* = NULL */, tree *poff /* = NULL */, range_query *rvals /* = NULL */) { /* Set the initial offsets to zero and size to negative to indicate none has been computed yet. */ access_ref ref; - tree size = compute_objsize (ptr, nullptr, ostype, &ref, rvals); + tree size = compute_objsize (ptr, stmt, ostype, &ref, rvals); if (!size || !ref.base0) return NULL_TREE; diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index 82cb81b3987..cbc87c86ed3 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -260,8 +260,13 @@ inline tree compute_objsize (tree ptr, int ostype, access_ref *pref) } /* Legacy/transitional API. Should not be used in new code. */ -extern tree compute_objsize (tree, int, tree * = nullptr, tree * = nullptr, - range_query * = nullptr); +extern tree compute_objsize (tree, gimple *, int, tree * = nullptr, + tree * = nullptr, range_query * = nullptr); +inline tree compute_objsize (tree ptr, int ostype, tree *pdecl = nullptr, + tree *poff = nullptr, range_query *rvals = nullptr) +{ + return compute_objsize (ptr, nullptr, ostype, pdecl, poff, rvals); +} /* Return the field at the constant offset. */ extern tree field_at_offset (tree, tree, HOST_WIDE_INT, From patchwork Mon Dec 6 17:32:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 48543 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 E92073858426 for ; Mon, 6 Dec 2021 17:34:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E92073858426 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638812091; bh=G4Ti/TmNGIbQ4m6VsxapX3vxRc8XbdPg62o68fc/qww=; h=Subject:To:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=YYm70UP2P0WjipLYSsfbEVHnQBwOfzl3BatVCHao+GzYqrtzBvayZuqt1i76fWbkv ZJzqXBNhuAYF2kubOgoll0n5Q6zZ6IciYGhzsQorxZkvKUvzz0SI7DdQeRcak5jr0V JqeNTxtGNRC4KzVwqXRWlkfFaVWd7LZThY6S6ZlU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oi1-x236.google.com (mail-oi1-x236.google.com [IPv6:2607:f8b0:4864:20::236]) by sourceware.org (Postfix) with ESMTPS id DCB1D3858434 for ; Mon, 6 Dec 2021 17:32:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DCB1D3858434 Received: by mail-oi1-x236.google.com with SMTP id t23so22802999oiw.3 for ; Mon, 06 Dec 2021 09:32:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=G4Ti/TmNGIbQ4m6VsxapX3vxRc8XbdPg62o68fc/qww=; b=1k9n/ZhWEDqPvpMBTKI97ImVO1rqQH9lQnKH38YsLGZ6ApRvDrT4zTDJNQs52UhO5h XcimIwmXWNOC3+I6k8t/1ApnGFUkdv0pFTLbhaof0PcOmnwudgoKHlu9393bxWz3rvUc 4fHLj97odVxvtF+mmBpcjAxuY/w5AOy88AHefVTUslpbxXSTg0/QHrgonMhrrLvndIJA 0R0N4IELZf4wbOmQcg6xQMStxIXe9BP02c2FjYFlXbTLSylxQzO2mr3400/IRrvnEsnA iyyzmhmoQtN2ciBvFGvZZ7mZrIGbgUwfeaVEapgJG5Y+scH2wxeBuBxjapdjFrpgwm5Q ivJg== X-Gm-Message-State: AOAM530le1tXYSOcuLtkNGC9M0qD2qTDowgZgUwHhO4Wdhm6BAB/mpfN IpJAVhU7ZJ6fzJgzExCoSlfFDIK6e3E= X-Google-Smtp-Source: ABdhPJx7W0QzoLTjQiW+PNOuluxgWyzfyu3XIiY1Y/bI51s42u15CUcXnMZj4IanfE2xizDKvangzA== X-Received: by 2002:aca:1811:: with SMTP id h17mr24788140oih.178.1638811941270; Mon, 06 Dec 2021 09:32:21 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id h6sm2280758otb.60.2021.12.06.09.32.20 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 09:32:20 -0800 (PST) Subject: [PATCH v2 3/5] fix up compute_objsize: factor out PHI handling To: Jeff Law , gcc-patches References: <65d1e530-a4cc-de27-1198-0dcaa08274bd@gmail.com> Message-ID: Date: Mon, 6 Dec 2021 10:32:19 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Attached is subset of the patch in part (4) below: factor out PHI handling. It applies on top of patch 3/5. On 12/3/21 5:00 PM, Jeff Law wrote: > > > On 11/8/2021 7:34 PM, Martin Sebor via Gcc-patches wrote: >> The pointer-query code that implements compute_objsize() that's >> in turn used by most middle end access warnings now has a few >> warts in it and (at least) one bug.  With the exception of >> the bug the warts aren't behind any user-visible bugs that >> I know of but they do cause problems in new code I've been >> implementing on top of it.  Besides fixing the one bug (just >> a typo) the attached patch cleans up these latent issues: >> >> 1) It moves the bndrng member from the access_ref class to >>    access_data.  As a FIXME in the code notes, the member never >>    did belong in the former and only takes up space in the cache. >> >> 2) The compute_objsize_r() function is big, unwieldy, and tedious >>    to step through because of all the if statements that are better >>    coded as one switch statement.  This change factors out more >>    of its code into smaller handler functions as has been suggested >>    and done a few times before. >> >> 3) (2) exposed a few places where I fail to pass the current >>    GIMPLE statement down to ranger.  This leads to worse quality >>    range info, including possible false positives and negatives. >>    I just spotted these problems in code review but I haven't >>    taken the time to come up with test cases.  This change fixes >>    these oversights as well. >> >> 4) The handling of PHI statements is also in one big, hard-to- >>    follow function.  This change moves the handling of each PHI >>    argument into its own handler which merges it into the previous >>    argument.  This makes the code easier to work with and opens it >>    to reuse also for MIN_EXPR and MAX_EXPR.  (This is primarily >>    used to print informational notes after warnings.) >> >> 5) Finally, the patch factors code to dump each access_ref >>    cached by the pointer_query cache out of pointer_query::dump >>    and into access_ref::dump.  This helps with debugging. >> >> These changes should have no user-visible effect and other than >> a regression test for the typo (PR 103143) come with no tests. >> They've been tested on x86_64-linux. > Sigh.  You've identified 6 distinct changes above.  The 5 you've > enumerated plus a typo fix somewhere.  There's no reason why they need > to be a single patch and many reasons why they should be a series of > independent patches.    Combining them into a single patch isn't how we > do things and it hides the actual bugfix in here. > > Please send a fix for the typo first since that should be able to > trivially go forward.  Then  a patch for item #1.  That should be > trivial to review when it's pulled out from teh rest of the patch. > Beyond that, your choice on ordering, but you need to break this down. > > > > > Jeff > commit 6ac1d37947ad5cf07fe133faaf8414f00e0eed13 Author: Martin Sebor Date: Mon Dec 6 09:23:22 2021 -0700 Introduce access_ref::merge_ref. gcc/ChangeLog: * pointer-query.cc (access_ref::merge_ref): Define new function. (access_ref::get_ref): Move code into merge_ref and call it. * pointer-query.h (access_ref::merge_ref): Declare new function. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index c75c4da6b60..24fbac84ec4 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -624,6 +624,97 @@ access_ref::phi () const return as_a (def_stmt); } +/* Determine the size and offset for ARG, append it to ALL_REFS, and + merge the result with *THIS. Ignore ARG if SKIP_NULL is set and + ARG refers to the null pointer. Return true on success and false + on failure. */ + +bool +access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt, + int ostype, bool skip_null, + ssa_name_limit_t &snlim, pointer_query &qry) +{ + access_ref aref; + if (!compute_objsize_r (arg, stmt, ostype, &aref, snlim, &qry) + || aref.sizrng[0] < 0) + /* This may be a PHI with all null pointer arguments. */ + return false; + + if (all_refs) + { + access_ref dummy_ref; + aref.get_ref (all_refs, &dummy_ref, ostype, &snlim, &qry); + } + + if (TREE_CODE (arg) == SSA_NAME) + qry.put_ref (arg, aref, ostype); + + if (all_refs) + all_refs->safe_push (aref); + + aref.deref += deref; + + bool merged_parmarray = aref.parmarray; + + const bool nullp = skip_null && integer_zerop (arg); + const offset_int maxobjsize = wi::to_offset (max_object_size ()); + offset_int minsize = sizrng[0]; + + if (sizrng[0] < 0) + { + /* If *THIS doesn't contain a meaningful result yet set it to AREF + unless the argument is null and it's okay to ignore it. */ + if (!nullp) + *this = aref; + + /* Set if the current argument refers to one or more objects of + known size (or range of sizes), as opposed to referring to + one or more unknown object(s). */ + const bool arg_known_size = (aref.sizrng[0] != 0 + || aref.sizrng[1] != maxobjsize); + if (arg_known_size) + sizrng[0] = aref.sizrng[0]; + + return true; + } + + /* Disregard null pointers in PHIs with two or more arguments. + TODO: Handle this better! */ + if (nullp) + return true; + + const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize); + + if (known_size && aref.sizrng[0] < minsize) + minsize = aref.sizrng[0]; + + /* Determine the amount of remaining space in the argument. */ + offset_int argrem[2]; + argrem[1] = aref.size_remaining (argrem); + + /* Determine the amount of remaining space computed so far and + if the remaining space in the argument is more use it instead. */ + offset_int merged_rem[2]; + merged_rem[1] = size_remaining (merged_rem); + + /* Reset the PHI's BASE0 flag if any of the nonnull arguments + refers to an object at an unknown offset. */ + if (!aref.base0) + base0 = false; + + if (merged_rem[1] < argrem[1] + || (merged_rem[1] == argrem[1] + && sizrng[1] < aref.sizrng[1])) + /* Use the argument with the most space remaining as the result, + or the larger one if the space is equal. */ + *this = aref; + + sizrng[0] = minsize; + parmarray = merged_parmarray; + + return true; +} + /* Determine and return the largest object to which *THIS refers. If *THIS refers to a PHI and PREF is nonnull, fill *PREF with the details of the object determined by compute_objsize(ARG, OSTYPE) for each PHI @@ -636,9 +727,8 @@ access_ref::get_ref (vec *all_refs, ssa_name_limit_t *psnlim /* = NULL */, pointer_query *qry /* = NULL */) const { - gphi *phi_stmt = this->phi (); - if (!phi_stmt) - return ref; + if (!ref || TREE_CODE (ref) != SSA_NAME) + return NULL; /* FIXME: Calling get_ref() with a null PSNLIM is dangerous and might cause unbounded recursion. */ @@ -646,13 +736,49 @@ access_ref::get_ref (vec *all_refs, if (!psnlim) psnlim = &snlim_buf; - if (!psnlim->visit_phi (ref)) - return NULL_TREE; - pointer_query empty_qry; if (!qry) qry = &empty_qry; + if (gimple *def_stmt = SSA_NAME_DEF_STMT (ref)) + { + if (is_gimple_assign (def_stmt)) + { + tree_code code = gimple_assign_rhs_code (def_stmt); + if (code != MIN_EXPR && code != MAX_EXPR) + return NULL_TREE; + + access_ref aref; + tree arg1 = gimple_assign_rhs1 (def_stmt); + if (!aref.merge_ref (all_refs, arg1, def_stmt, ostype, false, + *psnlim, *qry)) + return NULL_TREE; + + tree arg2 = gimple_assign_rhs2 (def_stmt); + if (!aref.merge_ref (all_refs, arg2, def_stmt, ostype, false, + *psnlim, *qry)) + return NULL_TREE; + + if (pref && pref != this) + { + tree ref = pref->ref; + *pref = aref; + pref->ref = ref; + } + + return aref.ref; + } + } + else + return NULL_TREE; + + gphi *phi_stmt = this->phi (); + if (!phi_stmt) + return ref; + + if (!psnlim->visit_phi (ref)) + return NULL_TREE; + /* The conservative result of the PHI reflecting the offset and size of the largest PHI argument, regardless of whether or not they all refer to the same object. */ @@ -670,91 +796,17 @@ access_ref::get_ref (vec *all_refs, phi_ref = *pref; } - /* Set if any argument is a function array (or VLA) parameter not - declared [static]. */ - bool parmarray = false; - /* The size of the smallest object referenced by the PHI arguments. */ - offset_int minsize = 0; - const offset_int maxobjsize = wi::to_offset (max_object_size ()); - const unsigned nargs = gimple_phi_num_args (phi_stmt); for (unsigned i = 0; i < nargs; ++i) { access_ref phi_arg_ref; + bool skip_null = i || i + 1 < nargs; tree arg = gimple_phi_arg_def (phi_stmt, i); - if (!compute_objsize_r (arg, phi_stmt, ostype, &phi_arg_ref, *psnlim, - qry) - || phi_arg_ref.sizrng[0] < 0) - /* A PHI with all null pointer arguments. */ + if (!phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null, + *psnlim, *qry)) return NULL_TREE; - - if (TREE_CODE (arg) == SSA_NAME) - qry->put_ref (arg, phi_arg_ref); - - if (all_refs) - all_refs->safe_push (phi_arg_ref); - - parmarray |= phi_arg_ref.parmarray; - - const bool nullp = integer_zerop (arg) && (i || i + 1 < nargs); - - if (phi_ref.sizrng[0] < 0) - { - /* If PHI_REF doesn't contain a meaningful result yet set it - to the result for the first argument. */ - if (!nullp) - phi_ref = phi_arg_ref; - - /* Set if the current argument refers to one or more objects of - known size (or range of sizes), as opposed to referring to - one or more unknown object(s). */ - const bool arg_known_size = (phi_arg_ref.sizrng[0] != 0 - || phi_arg_ref.sizrng[1] != maxobjsize); - if (arg_known_size) - minsize = phi_arg_ref.sizrng[0]; - - continue; - } - - const bool phi_known_size = (phi_ref.sizrng[0] != 0 - || phi_ref.sizrng[1] != maxobjsize); - - if (phi_known_size && phi_arg_ref.sizrng[0] < minsize) - minsize = phi_arg_ref.sizrng[0]; - - /* Disregard null pointers in PHIs with two or more arguments. - TODO: Handle this better! */ - if (nullp) - continue; - - /* Determine the amount of remaining space in the argument. */ - offset_int argrem[2]; - argrem[1] = phi_arg_ref.size_remaining (argrem); - - /* Determine the amount of remaining space computed so far and - if the remaining space in the argument is more use it instead. */ - offset_int phirem[2]; - phirem[1] = phi_ref.size_remaining (phirem); - - /* Reset the PHI's BASE0 flag if any of the nonnull arguments - refers to an object at an unknown offset. */ - if (!phi_arg_ref.base0) - phi_ref.base0 = false; - - if (phirem[1] < argrem[1] - || (phirem[1] == argrem[1] - && phi_ref.sizrng[1] < phi_arg_ref.sizrng[1])) - /* Use the argument with the most space remaining as the result, - or the larger one if the space is equal. */ - phi_ref = phi_arg_ref; } - /* Replace the lower bound of the largest argument with the size - of the smallest argument, and set PARMARRAY if any argument - was one. */ - phi_ref.sizrng[0] = minsize; - phi_ref.parmarray = parmarray; - if (phi_ref.sizrng[0] < 0) { /* Fail if none of the PHI's arguments resulted in updating PHI_REF @@ -766,7 +818,14 @@ access_ref::get_ref (vec *all_refs, /* Avoid changing *THIS. */ if (pref && pref != this) - *pref = phi_ref; + { + /* Keep the SSA_NAME of the PHI unchanged so that all PHI arguments + can be referred to later if necessary. This is useful even if + they all refer to the same object. */ + tree ref = pref->ref; + *pref = phi_ref; + pref->ref = ref; + } psnlim->leave_phi (ref); diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index cbc87c86ed3..fe46f711e96 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -66,6 +66,10 @@ struct access_ref /* Return the PHI node REF refers to or null if it doesn't. */ gphi *phi () const; + /* Merge the result for a pointer with *THIS. */ + bool merge_ref (vec *all_refs, tree, gimple *, int, bool, + ssa_name_limit_t &, pointer_query &); + /* Return the object to which REF refers. */ tree get_ref (vec *, access_ref * = nullptr, int = 1, ssa_name_limit_t * = nullptr, pointer_query * = nullptr) const; From patchwork Mon Dec 6 17:32:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 48544 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 E0E323858436 for ; Mon, 6 Dec 2021 17:35:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E0E323858436 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638812157; bh=n7pUa5qynPpQphe5V9LeJQjN1Yfj5wahmzxogwxKdWE=; h=Subject:To:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=U0TQi/wgl+mXnPBQOUaE4DGVNEgmWzcdo5lDWARNLKcEggGNb0jt7A9wPKmxHeWCh 9IuepyPR8EN5D6e10zMyz3LbxP/dZstWdFxH5KSFpmxDROx+PkC/GeiWEULmsN0xbv Skb2U56vqztGovXgoZ3tIta9m+c+11tr9JADFjUU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oi1-x22a.google.com (mail-oi1-x22a.google.com [IPv6:2607:f8b0:4864:20::22a]) by sourceware.org (Postfix) with ESMTPS id 03F9D3858401 for ; Mon, 6 Dec 2021 17:32:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 03F9D3858401 Received: by mail-oi1-x22a.google.com with SMTP id be32so22671409oib.11 for ; Mon, 06 Dec 2021 09:32:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=n7pUa5qynPpQphe5V9LeJQjN1Yfj5wahmzxogwxKdWE=; b=5GZOaqXEpycwHw+dHDqH/dqxfF5nQbEekCi98uI9IZ2cb3yUxsyePQa6B0YrDMQ/B3 xi/5JWD1xs3KTCcmJeKbj+OxkqAILEI5sRxE/hBzbIvs4xyFp6uTQxW8IJ5i+KHi8HgI ysIlX370EsIiCTDdfWLOr+/4TURJe8JYza1EXVl/Fm3IGVKfpjn/f3w/qhJ1yN0iCgOL PiD8SO3gLUAm38lZ087Uh6id6ykxixS575vNUieUjM++2oO2k4SzhTj77M/irzwYwJBb xKy+BsorcyVWKIJRc+/Sol3ty5gT8Gn29GimQEcCYjmpgridYB/oPFvK7qLpQRbNbAQl h6jw== X-Gm-Message-State: AOAM532m+7V2Pyr/2UyN3eHBAvx6Wqml/GBbDGLTt4BgvxBhoRS7GPGp gBmDDgkV/UAFhzXaRzzOQacUx/WPV4s= X-Google-Smtp-Source: ABdhPJy5HQF7PaLsOqdxIJ0srRNWuoGy2andU1pv/HxFgTSb7wisbBZc/vqfC4M1Xxq5tLwB6UQKgw== X-Received: by 2002:aca:2b02:: with SMTP id i2mr24827160oik.140.1638811959319; Mon, 06 Dec 2021 09:32:39 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id u40sm2922799oiw.56.2021.12.06.09.32.38 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 09:32:39 -0800 (PST) Subject: [PATCH v2 4/5] fix up compute_objsize: refactor it into helpers To: Jeff Law , gcc-patches References: <65d1e530-a4cc-de27-1198-0dcaa08274bd@gmail.com> Message-ID: Date: Mon, 6 Dec 2021 10:32:38 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Attached is the subset of the patch in part (2) below: refactor compute_objsize_r into helpers. It applies on top of patch 3/5. On 12/3/21 5:00 PM, Jeff Law wrote: > > > On 11/8/2021 7:34 PM, Martin Sebor via Gcc-patches wrote: >> The pointer-query code that implements compute_objsize() that's >> in turn used by most middle end access warnings now has a few >> warts in it and (at least) one bug.  With the exception of >> the bug the warts aren't behind any user-visible bugs that >> I know of but they do cause problems in new code I've been >> implementing on top of it.  Besides fixing the one bug (just >> a typo) the attached patch cleans up these latent issues: >> >> 1) It moves the bndrng member from the access_ref class to >>    access_data.  As a FIXME in the code notes, the member never >>    did belong in the former and only takes up space in the cache. >> >> 2) The compute_objsize_r() function is big, unwieldy, and tedious >>    to step through because of all the if statements that are better >>    coded as one switch statement.  This change factors out more >>    of its code into smaller handler functions as has been suggested >>    and done a few times before. >> >> 3) (2) exposed a few places where I fail to pass the current >>    GIMPLE statement down to ranger.  This leads to worse quality >>    range info, including possible false positives and negatives. >>    I just spotted these problems in code review but I haven't >>    taken the time to come up with test cases.  This change fixes >>    these oversights as well. >> >> 4) The handling of PHI statements is also in one big, hard-to- >>    follow function.  This change moves the handling of each PHI >>    argument into its own handler which merges it into the previous >>    argument.  This makes the code easier to work with and opens it >>    to reuse also for MIN_EXPR and MAX_EXPR.  (This is primarily >>    used to print informational notes after warnings.) >> >> 5) Finally, the patch factors code to dump each access_ref >>    cached by the pointer_query cache out of pointer_query::dump >>    and into access_ref::dump.  This helps with debugging. >> >> These changes should have no user-visible effect and other than >> a regression test for the typo (PR 103143) come with no tests. >> They've been tested on x86_64-linux. > Sigh.  You've identified 6 distinct changes above.  The 5 you've > enumerated plus a typo fix somewhere.  There's no reason why they need > to be a single patch and many reasons why they should be a series of > independent patches.    Combining them into a single patch isn't how we > do things and it hides the actual bugfix in here. > > Please send a fix for the typo first since that should be able to > trivially go forward.  Then  a patch for item #1.  That should be > trivial to review when it's pulled out from teh rest of the patch. > Beyond that, your choice on ordering, but you need to break this down. > > > > > Jeff > commit 7d1d8cc18678ccaec5f274919e0c9910ccfea86e Author: Martin Sebor Date: Mon Dec 6 09:33:32 2021 -0700 Refactor compute_objsize_r into helpers. gcc/ChangeLog: * pointer-query.cc (compute_objsize_r): Add an argument. (gimple_call_return_array): Pass a new argument to compute_objsize_r. (access_ref::merge_ref): Same. (access_ref::inform_access): Add an argument and use it. (access_data::access_data): Initialize new member. (handle_min_max_size): Pass a new argument to compute_objsize_r. (handle_decl): New function. (handle_array_ref): Pass a new argument to compute_objsize_r. Avoid incrementing deref. (set_component_ref_size): New function. (handle_component_ref): New function. (handle_mem_ref): Pass a new argument to compute_objsize_r. Only increment deref after successfully computing object size. (handle_ssa_name): New function. (compute_objsize_r): Move code into helpers and call them. (compute_objsize): Pass a new argument to compute_objsize_r. * pointer-query.h (access_ref::inform_access): Add an argument. (access_data::ostype): New member. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 24fbac84ec4..3f583110c71 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -43,7 +43,7 @@ #include "tree-ssanames.h" #include "target.h" -static bool compute_objsize_r (tree, gimple *, int, access_ref *, +static bool compute_objsize_r (tree, gimple *, bool, int, access_ref *, ssa_name_limit_t &, pointer_query *); /* Wrapper around the wide_int overload of get_range that accepts @@ -199,7 +199,7 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2], bool *past_end, of the source object. */ access_ref aref; tree src = gimple_call_arg (stmt, 1); - if (compute_objsize_r (src, stmt, 1, &aref, snlim, qry) + if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry) && aref.sizrng[1] < offrng[1]) offrng[1] = aref.sizrng[1]; } @@ -233,7 +233,7 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2], bool *past_end, { access_ref aref; tree src = gimple_call_arg (stmt, 1); - if (compute_objsize_r (src, stmt, 1, &aref, snlim, qry)) + if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry)) offrng[1] = aref.sizrng[1] - 1; else offrng[1] = HOST_WIDE_INT_M1U; @@ -258,7 +258,7 @@ gimple_call_return_array (gimple *stmt, offset_int offrng[2], bool *past_end, of the source object. */ access_ref aref; tree src = gimple_call_arg (stmt, 1); - if (compute_objsize_r (src, stmt, 1, &aref, snlim, qry) + if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry) && aref.sizrng[1] < offrng[1]) offrng[1] = aref.sizrng[1]; } @@ -635,7 +635,7 @@ access_ref::merge_ref (vec *all_refs, tree arg, gimple *stmt, ssa_name_limit_t &snlim, pointer_query &qry) { access_ref aref; - if (!compute_objsize_r (arg, stmt, ostype, &aref, snlim, &qry) + if (!compute_objsize_r (arg, stmt, false, ostype, &aref, snlim, &qry) || aref.sizrng[0] < 0) /* This may be a PHI with all null pointer arguments. */ return false; @@ -997,42 +997,45 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max) WRITE is set for a write access and clear for a read access. */ void -access_ref::inform_access (access_mode mode) const +access_ref::inform_access (access_mode mode, int ostype /* = 1 */) const { const access_ref &aref = *this; if (!aref.ref) return; - if (aref.phi ()) + if (phi ()) { /* Set MAXREF to refer to the largest object and fill ALL_REFS with data for all objects referenced by the PHI arguments. */ access_ref maxref; auto_vec all_refs; - if (!get_ref (&all_refs, &maxref)) + if (!get_ref (&all_refs, &maxref, ostype)) return; - /* Except for MAXREF, the rest of the arguments' offsets need not - reflect one added to the PHI itself. Determine the latter from - MAXREF on which the result is based. */ - const offset_int orng[] = + if (all_refs.length ()) { - offrng[0] - maxref.offrng[0], - wi::smax (offrng[1] - maxref.offrng[1], offrng[0]), - }; + /* Except for MAXREF, the rest of the arguments' offsets need not + reflect one added to the PHI itself. Determine the latter from + MAXREF on which the result is based. */ + const offset_int orng[] = + { + offrng[0] - maxref.offrng[0], + wi::smax (offrng[1] - maxref.offrng[1], offrng[0]), + }; - /* Add the final PHI's offset to that of each of the arguments - and recurse to issue an inform message for it. */ - for (unsigned i = 0; i != all_refs.length (); ++i) - { - /* Skip any PHIs; those could lead to infinite recursion. */ - if (all_refs[i].phi ()) - continue; + /* Add the final PHI's offset to that of each of the arguments + and recurse to issue an inform message for it. */ + for (unsigned i = 0; i != all_refs.length (); ++i) + { + /* Skip any PHIs; those could lead to infinite recursion. */ + if (all_refs[i].phi ()) + continue; - all_refs[i].add_offset (orng[0], orng[1]); - all_refs[i].inform_access (mode); + all_refs[i].add_offset (orng[0], orng[1]); + all_refs[i].inform_access (mode, ostype); + } + return; } - return; } /* Convert offset range and avoid including a zero range since it @@ -1244,7 +1247,7 @@ access_data::access_data (range_query *query, gimple *stmt, access_mode mode, bool minwrite /* = false */, tree maxread /* = NULL_TREE */, bool minread /* = false */) - : stmt (stmt), call (), dst (), src (), mode (mode) + : stmt (stmt), call (), dst (), src (), mode (mode), ostype () { set_bound (dst_bndrng, maxwrite, minwrite, query, stmt); set_bound (src_bndrng, maxread, minread, query, stmt); @@ -1257,7 +1260,7 @@ access_data::access_data (range_query *query, tree expr, access_mode mode, bool minwrite /* = false */, tree maxread /* = NULL_TREE */, bool minread /* = false */) - : stmt (), call (expr), dst (), src (), mode (mode) + : stmt (), call (expr), dst (), src (), mode (mode), ostype () { set_bound (dst_bndrng, maxwrite, minwrite, query, stmt); set_bound (src_bndrng, maxread, minread, query, stmt); @@ -1406,7 +1409,8 @@ pointer_query::get_ref (tree ptr, int ostype /* = 1 */) const there or compute it and insert it into the cache if it's nonnonull. */ bool -pointer_query::get_ref (tree ptr, gimple *stmt, access_ref *pref, int ostype /* = 1 */) +pointer_query::get_ref (tree ptr, gimple *stmt, access_ref *pref, + int ostype /* = 1 */) { const unsigned version = TREE_CODE (ptr) == SSA_NAME ? SSA_NAME_VERSION (ptr) : 0; @@ -1606,7 +1610,7 @@ handle_min_max_size (tree ptr, int ostype, access_ref *pref, for the expression. */ access_ref aref[2] = { *pref, *pref }; tree arg1 = gimple_assign_rhs1 (stmt); - if (!compute_objsize_r (arg1, stmt, ostype, &aref[0], snlim, qry)) + if (!compute_objsize_r (arg1, stmt, false, ostype, &aref[0], snlim, qry)) { aref[0].base0 = false; aref[0].offrng[0] = aref[0].offrng[1] = 0; @@ -1615,7 +1619,7 @@ handle_min_max_size (tree ptr, int ostype, access_ref *pref, } tree arg2 = gimple_assign_rhs2 (stmt); - if (!compute_objsize_r (arg2, stmt, ostype, &aref[1], snlim, qry)) + if (!compute_objsize_r (arg2, stmt, false, ostype, &aref[1], snlim, qry)) { aref[1].base0 = false; aref[1].offrng[0] = aref[1].offrng[1] = 0; @@ -1678,6 +1682,46 @@ handle_min_max_size (tree ptr, int ostype, access_ref *pref, return true; } +/* A helper of compute_objsize_r() to determine the size of a DECL. + Return true on success and (possibly in the future) false on failure. */ + +static bool +handle_decl (tree decl, bool addr, access_ref *pref) +{ + tree decl_type = TREE_TYPE (decl); + + pref->ref = decl; + + /* Reset the offset in case it was set by a prior call and not + cleared by the caller. The offset is only adjusted after + the identity of the object has been determined. */ + pref->offrng[0] = pref->offrng[1] = 0; + + if (!addr && POINTER_TYPE_P (decl_type)) + { + /* Set the maximum size if the reference is to the pointer + itself (as opposed to what it points to), and clear + BASE0 since the offset isn't necessarily zero-based. */ + pref->set_max_size_range (); + pref->base0 = false; + return true; + } + + /* Valid offsets into the object are nonnegative. */ + pref->base0 = true; + + if (tree size = decl_init_size (decl, false)) + if (TREE_CODE (size) == INTEGER_CST) + { + pref->sizrng[0] = wi::to_offset (size); + pref->sizrng[1] = pref->sizrng[0]; + return true; + } + + pref->set_max_size_range (); + return true; +} + /* A helper of compute_objsize_r() to determine the size from ARRAY_REF AREF. ADDR is true if PTR is the operand of ADDR_EXPR. Return true on success and false on failure. */ @@ -1689,8 +1733,6 @@ handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype, { gcc_assert (TREE_CODE (aref) == ARRAY_REF); - ++pref->deref; - tree arefop = TREE_OPERAND (aref, 0); tree reftype = TREE_TYPE (arefop); if (!addr && TREE_CODE (TREE_TYPE (reftype)) == POINTER_TYPE) @@ -1698,7 +1740,7 @@ handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype, of known bound. */ return false; - if (!compute_objsize_r (arefop, stmt, ostype, pref, snlim, qry)) + if (!compute_objsize_r (arefop, stmt, addr, ostype, pref, snlim, qry)) return false; offset_int orng[2]; @@ -1759,6 +1801,96 @@ handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype, return true; } +/* Given a COMPONENT_REF CREF, set *PREF size to the size of the referenced + member. */ + +static void +set_component_ref_size (tree cref, access_ref *pref) +{ + const tree base = TREE_OPERAND (cref, 0); + const tree base_type = TREE_TYPE (base); + + /* SAM is set for array members that might need special treatment. */ + special_array_member sam; + tree size = component_ref_size (cref, &sam); + if (sam == special_array_member::int_0) + pref->sizrng[0] = pref->sizrng[1] = 0; + else if (!pref->trail1special && sam == special_array_member::trail_1) + pref->sizrng[0] = pref->sizrng[1] = 1; + else if (size && TREE_CODE (size) == INTEGER_CST) + pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size); + else + { + /* When the size of the member is unknown it's either a flexible + array member or a trailing special array member (either zero + length or one-element). Set the size to the maximum minus + the constant size of the base object's type. */ + pref->sizrng[0] = 0; + pref->sizrng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); + if (tree base_size = TYPE_SIZE_UNIT (base_type)) + if (TREE_CODE (base_size) == INTEGER_CST) + pref->sizrng[1] -= wi::to_offset (base_size); + } +} + +/* A helper of compute_objsize_r() to determine the size from COMPONENT_REF + CREF. Return true on success and false on failure. */ + +static bool +handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype, + access_ref *pref, ssa_name_limit_t &snlim, + pointer_query *qry) +{ + gcc_assert (TREE_CODE (cref) == COMPONENT_REF); + + const tree base = TREE_OPERAND (cref, 0); + const tree base_type = TREE_TYPE (base); + if (TREE_CODE (base_type) == UNION_TYPE) + /* In accesses through union types consider the entire unions + rather than just their members. */ + ostype = 0; + + tree field = TREE_OPERAND (cref, 1); + + if (ostype == 0) + { + /* In OSTYPE zero (for raw memory functions like memcpy), use + the maximum size instead if the identity of the enclosing + object cannot be determined. */ + if (!compute_objsize_r (base, stmt, addr, ostype, pref, snlim, qry)) + return false; + + /* Otherwise, use the size of the enclosing object and add + the offset of the member to the offset computed so far. */ + tree offset = byte_position (field); + if (TREE_CODE (offset) == INTEGER_CST) + pref->add_offset (wi::to_offset (offset)); + else + pref->add_max_offset (); + + if (!pref->ref) + /* PREF->REF may have been already set to an SSA_NAME earlier + to provide better context for diagnostics. In that case, + leave it unchanged. */ + pref->ref = base; + + return true; + } + + pref->ref = field; + + if (!addr && POINTER_TYPE_P (TREE_TYPE (field))) + { + /* Set maximum size if the reference is to the pointer member + itself (as opposed to what it points to). */ + pref->set_max_size_range (); + return true; + } + + set_component_ref_size (cref, pref); + return true; +} + /* A helper of compute_objsize_r() to determine the size from MEM_REF MREF. Return true on success and false on failure. */ @@ -1768,10 +1900,9 @@ handle_mem_ref (tree mref, gimple *stmt, int ostype, access_ref *pref, { gcc_assert (TREE_CODE (mref) == MEM_REF); - ++pref->deref; - - if (VECTOR_TYPE_P (TREE_TYPE (mref))) - { + tree mreftype = TYPE_MAIN_VARIANT (TREE_TYPE (mref)); + if (VECTOR_TYPE_P (mreftype)) + { /* Hack: Handle MEM_REFs of vector types as those to complete objects; those may be synthesized from multiple assignments to consecutive data members (see PR 93200 and 96963). @@ -1785,9 +1916,11 @@ handle_mem_ref (tree mref, gimple *stmt, int ostype, access_ref *pref, } tree mrefop = TREE_OPERAND (mref, 0); - if (!compute_objsize_r (mrefop, stmt, ostype, pref, snlim, qry)) + if (!compute_objsize_r (mrefop, stmt, false, ostype, pref, snlim, qry)) return false; + ++pref->deref; + offset_int orng[2]; tree off = pref->eval (TREE_OPERAND (mref, 1)); range_query *const rvals = qry ? qry->rvals : NULL; @@ -1802,168 +1935,283 @@ handle_mem_ref (tree mref, gimple *stmt, int ostype, access_ref *pref, return true; } -/* Helper to compute the size of the object referenced by the PTR - expression which must have pointer type, using Object Size type - OSTYPE (only the least significant 2 bits are used). - On success, sets PREF->REF to the DECL of the referenced object - if it's unique, otherwise to null, PREF->OFFRNG to the range of - offsets into it, and PREF->SIZRNG to the range of sizes of - the object(s). - SNLIM is used to avoid visiting the same PHI operand multiple - times, and, when nonnull, RVALS to determine range information. - Returns true on success, false when a meaningful size (or range) - cannot be determined. - - The function is intended for diagnostics and should not be used - to influence code generation or optimization. */ +/* A helper of compute_objsize_r() to determine the size from SSA_NAME + PTR. Return true on success and false on failure. */ static bool -compute_objsize_r (tree ptr, gimple *stmt, int ostype, access_ref *pref, - ssa_name_limit_t &snlim, pointer_query *qry) +handle_ssa_name (tree ptr, bool addr, int ostype, + access_ref *pref, ssa_name_limit_t &snlim, + pointer_query *qry) { - STRIP_NOPS (ptr); + if (!snlim.next ()) + return false; - const bool addr = TREE_CODE (ptr) == ADDR_EXPR; - if (addr) + /* Only process an SSA_NAME if the recursion limit has not yet + been reached. */ + if (qry) { - --pref->deref; - ptr = TREE_OPERAND (ptr, 0); + if (++qry->depth > qry->max_depth) + qry->max_depth = qry->depth; + if (const access_ref *cache_ref = qry->get_ref (ptr, ostype)) + { + /* Add the number of DEREFerences accummulated so far. */ + const int deref = pref->deref; + *pref = *cache_ref; + pref->deref += deref; + return true; + } } - if (DECL_P (ptr)) - { - pref->ref = ptr; - - /* Reset the offset in case it was set by a prior call and not - cleared by the caller. The offset is only adjusted after - the identity of the object has been determined. */ - pref->offrng[0] = pref->offrng[1] = 0; + gimple *stmt = SSA_NAME_DEF_STMT (ptr); + if (is_gimple_call (stmt)) + { + /* If STMT is a call to an allocation function get the size + from its argument(s). If successful, also set *PREF->REF + to PTR for the caller to include in diagnostics. */ + wide_int wr[2]; + range_query *const rvals = qry ? qry->rvals : NULL; + if (gimple_call_alloc_size (stmt, wr, rvals)) + { + pref->ref = ptr; + pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED); + pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED); + /* Constrain both bounds to a valid size. */ + offset_int maxsize = wi::to_offset (max_object_size ()); + if (pref->sizrng[0] > maxsize) + pref->sizrng[0] = maxsize; + if (pref->sizrng[1] > maxsize) + pref->sizrng[1] = maxsize; + } + else + { + /* For functions known to return one of their pointer arguments + try to determine what the returned pointer points to, and on + success add OFFRNG which was set to the offset added by + the function (e.g., memchr) to the overall offset. */ + bool past_end; + offset_int offrng[2]; + if (tree ret = gimple_call_return_array (stmt, offrng, &past_end, + snlim, qry)) + { + if (!compute_objsize_r (ret, stmt, addr, ostype, pref, snlim, qry)) + return false; + + /* Cap OFFRNG[1] to at most the remaining size of + the object. */ + offset_int remrng[2]; + remrng[1] = pref->size_remaining (remrng); + if (remrng[1] != 0 && !past_end) + /* Decrement the size for functions that never return + a past-the-end pointer. */ + remrng[1] -= 1; + + if (remrng[1] < offrng[1]) + offrng[1] = remrng[1]; + pref->add_offset (offrng[0], offrng[1]); + } + else + { + /* For other calls that might return arbitrary pointers + including into the middle of objects set the size + range to maximum, clear PREF->BASE0, and also set + PREF->REF to include in diagnostics. */ + pref->set_max_size_range (); + pref->base0 = false; + pref->ref = ptr; + } + } + qry->put_ref (ptr, *pref, ostype); + return true; + } - if (!addr && POINTER_TYPE_P (TREE_TYPE (ptr))) + if (gimple_nop_p (stmt)) + { + /* For a function argument try to determine the byte size + of the array from the current function declaratation + (e.g., attribute access or related). */ + wide_int wr[2]; + bool static_array = false; + if (tree ref = gimple_parm_array_size (ptr, wr, &static_array)) { - /* Set the maximum size if the reference is to the pointer - itself (as opposed to what it points to), and clear - BASE0 since the offset isn't necessarily zero-based. */ - pref->set_max_size_range (); - pref->base0 = false; + pref->parmarray = !static_array; + pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED); + pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED); + pref->ref = ref; + qry->put_ref (ptr, *pref, ostype); return true; } - /* Valid offsets into the object are nonnegative. */ - pref->base0 = true; - - if (tree size = decl_init_size (ptr, false)) - if (TREE_CODE (size) == INTEGER_CST) - { - pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size); - return true; - } - pref->set_max_size_range (); + pref->base0 = false; + pref->ref = ptr; + qry->put_ref (ptr, *pref, ostype); return true; } - const tree_code code = TREE_CODE (ptr); - range_query *const rvals = qry ? qry->rvals : NULL; - - if (code == BIT_FIELD_REF) + if (gimple_code (stmt) == GIMPLE_PHI) { - tree ref = TREE_OPERAND (ptr, 0); - if (!compute_objsize_r (ref, stmt, ostype, pref, snlim, qry)) + /* Pass PTR to get_ref() via PREF. If all PHI arguments refer + to the same object the function will replace it with it. */ + pref->ref = ptr; + access_ref phi_ref = *pref; + if (!pref->get_ref (NULL, &phi_ref, ostype, &snlim, qry)) return false; + *pref = phi_ref; + qry->put_ref (ptr, *pref, ostype); + return true; + } - offset_int off = wi::to_offset (pref->eval (TREE_OPERAND (ptr, 2))); - pref->add_offset (off / BITS_PER_UNIT); + if (!is_gimple_assign (stmt)) + { + /* Clear BASE0 since the assigned pointer might point into + the middle of the object, set the maximum size range and, + if the SSA_NAME refers to a function argumnent, set + PREF->REF to it. */ + pref->base0 = false; + pref->set_max_size_range (); + pref->ref = ptr; return true; } - if (code == COMPONENT_REF) + tree_code code = gimple_assign_rhs_code (stmt); + + if (code == MAX_EXPR || code == MIN_EXPR) { - tree ref = TREE_OPERAND (ptr, 0); - if (TREE_CODE (TREE_TYPE (ref)) == UNION_TYPE) - /* In accesses through union types consider the entire unions - rather than just their members. */ - ostype = 0; - tree field = TREE_OPERAND (ptr, 1); + if (!handle_min_max_size (ptr, ostype, pref, snlim, qry)) + return false; - if (ostype == 0) - { - /* In OSTYPE zero (for raw memory functions like memcpy), use - the maximum size instead if the identity of the enclosing - object cannot be determined. */ - if (!compute_objsize_r (ref, stmt, ostype, pref, snlim, qry)) - return false; - - /* Otherwise, use the size of the enclosing object and add - the offset of the member to the offset computed so far. */ - tree offset = byte_position (field); - if (TREE_CODE (offset) == INTEGER_CST) - pref->add_offset (wi::to_offset (offset)); - else - pref->add_max_offset (); + qry->put_ref (ptr, *pref, ostype); + return true; + } - if (!pref->ref) - /* REF may have been already set to an SSA_NAME earlier - to provide better context for diagnostics. In that case, - leave it unchanged. */ - pref->ref = ref; - return true; - } + tree rhs = gimple_assign_rhs1 (stmt); - pref->ref = field; + if (code == ASSERT_EXPR) + { + rhs = TREE_OPERAND (rhs, 0); + return compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry); + } - if (!addr && POINTER_TYPE_P (TREE_TYPE (field))) - { - /* Set maximum size if the reference is to the pointer member - itself (as opposed to what it points to). */ - pref->set_max_size_range (); - return true; - } + if (code == POINTER_PLUS_EXPR + && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE) + { + /* Compute the size of the object first. */ + if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry)) + return false; - /* SAM is set for array members that might need special treatment. */ - special_array_member sam; - tree size = component_ref_size (ptr, &sam); - if (sam == special_array_member::int_0) - pref->sizrng[0] = pref->sizrng[1] = 0; - else if (!pref->trail1special && sam == special_array_member::trail_1) - pref->sizrng[0] = pref->sizrng[1] = 1; - else if (size && TREE_CODE (size) == INTEGER_CST) - pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size); + offset_int orng[2]; + tree off = gimple_assign_rhs2 (stmt); + range_query *const rvals = qry ? qry->rvals : NULL; + if (get_offset_range (off, stmt, orng, rvals)) + pref->add_offset (orng[0], orng[1]); else - { - /* When the size of the member is unknown it's either a flexible - array member or a trailing special array member (either zero - length or one-element). Set the size to the maximum minus - the constant size of the type. */ - pref->sizrng[0] = 0; - pref->sizrng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); - if (tree recsize = TYPE_SIZE_UNIT (TREE_TYPE (ref))) - if (TREE_CODE (recsize) == INTEGER_CST) - pref->sizrng[1] -= wi::to_offset (recsize); - } + pref->add_max_offset (); + + qry->put_ref (ptr, *pref, ostype); return true; } - if (code == ARRAY_REF) - return handle_array_ref (ptr, stmt, addr, ostype, pref, snlim, qry); - - if (code == MEM_REF) - return handle_mem_ref (ptr, stmt, ostype, pref, snlim, qry); + if (code == ADDR_EXPR || code == SSA_NAME) + { + if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry)) + return false; + qry->put_ref (ptr, *pref, ostype); + return true; + } - if (code == TARGET_MEM_REF) + if (ostype > 1 && POINTER_TYPE_P (TREE_TYPE (rhs))) { - tree ref = TREE_OPERAND (ptr, 0); - if (!compute_objsize_r (ref, stmt, ostype, pref, snlim, qry)) + /* When determining the qualifiers follow the pointer but + avoid caching the result. As the pointer is added to + and/or dereferenced the computed size and offset need + not be meaningful for other queries involving the same + pointer. */ + if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry)) return false; - /* TODO: Handle remaining operands. Until then, add maximum offset. */ - pref->ref = ptr; - pref->add_max_offset (); - return true; + rhs = pref->ref; } - if (code == INTEGER_CST) + /* (This could also be an assignment from a nonlocal pointer.) Save + PTR to mention in diagnostics but otherwise treat it as a pointer + to an unknown object. */ + pref->ref = rhs; + pref->base0 = false; + pref->set_max_size_range (); + return true; +} + +/* Helper to compute the size of the object referenced by the PTR + expression which must have pointer type, using Object Size type + OSTYPE (only the least significant 2 bits are used). + On success, sets PREF->REF to the DECL of the referenced object + if it's unique, otherwise to null, PREF->OFFRNG to the range of + offsets into it, and PREF->SIZRNG to the range of sizes of + the object(s). + ADDR is true for an enclosing ADDR_EXPR. + SNLIM is used to avoid visiting the same PHI operand multiple + times, and, when nonnull, RVALS to determine range information. + Returns true on success, false when a meaningful size (or range) + cannot be determined. + + The function is intended for diagnostics and should not be used + to influence code generation or optimization. */ + +static bool +compute_objsize_r (tree ptr, gimple *stmt, bool addr, int ostype, + access_ref *pref, ssa_name_limit_t &snlim, + pointer_query *qry) +{ + STRIP_NOPS (ptr); + + if (DECL_P (ptr)) + return handle_decl (ptr, addr, pref); + + switch (TREE_CODE (ptr)) { + case ADDR_EXPR: + { + tree ref = TREE_OPERAND (ptr, 0); + if (!compute_objsize_r (ref, stmt, true, ostype, pref, snlim, qry)) + return false; + + --pref->deref; + return true; + } + + case BIT_FIELD_REF: + { + tree ref = TREE_OPERAND (ptr, 0); + if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry)) + return false; + + offset_int off = wi::to_offset (pref->eval (TREE_OPERAND (ptr, 2))); + pref->add_offset (off / BITS_PER_UNIT); + return true; + } + + case ARRAY_REF: + return handle_array_ref (ptr, stmt, addr, ostype, pref, snlim, qry); + + case COMPONENT_REF: + return handle_component_ref (ptr, stmt, addr, ostype, pref, snlim, qry); + + case MEM_REF: + return handle_mem_ref (ptr, stmt, ostype, pref, snlim, qry); + + case TARGET_MEM_REF: + { + tree ref = TREE_OPERAND (ptr, 0); + if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry)) + return false; + + /* TODO: Handle remaining operands. Until then, add maximum offset. */ + pref->ref = ptr; + pref->add_max_offset (); + return true; + } + + case INTEGER_CST: /* Pointer constants other than null are most likely the result of erroneous null pointer addition/subtraction. Unless zero is a valid address set size to zero. For null pointers, set @@ -1984,21 +2232,17 @@ compute_objsize_r (tree ptr, gimple *stmt, int ostype, access_ref *pref, pref->sizrng[0] = pref->sizrng[1] = 0; pref->ref = ptr; - return true; - } - if (code == STRING_CST) - { + case STRING_CST: pref->sizrng[0] = pref->sizrng[1] = TREE_STRING_LENGTH (ptr); pref->ref = ptr; return true; - } - if (code == POINTER_PLUS_EXPR) + case POINTER_PLUS_EXPR: { tree ref = TREE_OPERAND (ptr, 0); - if (!compute_objsize_r (ref, stmt, ostype, pref, snlim, qry)) + if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry)) return false; /* Clear DEREF since the offset is being applied to the target @@ -2007,200 +2251,22 @@ compute_objsize_r (tree ptr, gimple *stmt, int ostype, access_ref *pref, offset_int orng[2]; tree off = pref->eval (TREE_OPERAND (ptr, 1)); - if (get_offset_range (off, stmt, orng, rvals)) + if (get_offset_range (off, stmt, orng, qry->rvals)) pref->add_offset (orng[0], orng[1]); else pref->add_max_offset (); return true; } - if (code == VIEW_CONVERT_EXPR) - { + case VIEW_CONVERT_EXPR: ptr = TREE_OPERAND (ptr, 0); - return compute_objsize_r (ptr, stmt, ostype, pref, snlim, qry); - } + return compute_objsize_r (ptr, stmt, addr, ostype, pref, snlim, qry); - if (code == SSA_NAME) - { - if (!snlim.next ()) - return false; + case SSA_NAME: + return handle_ssa_name (ptr, addr, ostype, pref, snlim, qry); - /* Only process an SSA_NAME if the recursion limit has not yet - been reached. */ - if (qry) - { - if (++qry->depth) - qry->max_depth = qry->depth; - if (const access_ref *cache_ref = qry->get_ref (ptr)) - { - /* If the pointer is in the cache set *PREF to what it refers - to and return success. */ - *pref = *cache_ref; - return true; - } - } - - stmt = SSA_NAME_DEF_STMT (ptr); - if (is_gimple_call (stmt)) - { - /* If STMT is a call to an allocation function get the size - from its argument(s). If successful, also set *PREF->REF - to PTR for the caller to include in diagnostics. */ - wide_int wr[2]; - if (gimple_call_alloc_size (stmt, wr, rvals)) - { - pref->ref = ptr; - pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED); - pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED); - /* Constrain both bounds to a valid size. */ - offset_int maxsize = wi::to_offset (max_object_size ()); - if (pref->sizrng[0] > maxsize) - pref->sizrng[0] = maxsize; - if (pref->sizrng[1] > maxsize) - pref->sizrng[1] = maxsize; - } - else - { - /* For functions known to return one of their pointer arguments - try to determine what the returned pointer points to, and on - success add OFFRNG which was set to the offset added by - the function (e.g., memchr) to the overall offset. */ - bool past_end; - offset_int offrng[2]; - if (tree ret = gimple_call_return_array (stmt, offrng, - &past_end, snlim, qry)) - { - if (!compute_objsize_r (ret, stmt, ostype, pref, snlim, qry)) - return false; - - /* Cap OFFRNG[1] to at most the remaining size of - the object. */ - offset_int remrng[2]; - remrng[1] = pref->size_remaining (remrng); - if (remrng[1] != 0 && !past_end) - /* Decrement the size for functions that never return - a past-the-end pointer. */ - remrng[1] -= 1; - - if (remrng[1] < offrng[1]) - offrng[1] = remrng[1]; - pref->add_offset (offrng[0], offrng[1]); - } - else - { - /* For other calls that might return arbitrary pointers - including into the middle of objects set the size - range to maximum, clear PREF->BASE0, and also set - PREF->REF to include in diagnostics. */ - pref->set_max_size_range (); - pref->base0 = false; - pref->ref = ptr; - } - } - qry->put_ref (ptr, *pref); - return true; - } - - if (gimple_nop_p (stmt)) - { - /* For a function argument try to determine the byte size - of the array from the current function declaratation - (e.g., attribute access or related). */ - wide_int wr[2]; - bool static_array = false; - if (tree ref = gimple_parm_array_size (ptr, wr, &static_array)) - { - pref->parmarray = !static_array; - pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED); - pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED); - pref->ref = ref; - qry->put_ref (ptr, *pref); - return true; - } - - pref->set_max_size_range (); - pref->base0 = false; - pref->ref = ptr; - qry->put_ref (ptr, *pref); - return true; - } - - if (gimple_code (stmt) == GIMPLE_PHI) - { - pref->ref = ptr; - access_ref phi_ref = *pref; - if (!pref->get_ref (NULL, &phi_ref, ostype, &snlim, qry)) - return false; - *pref = phi_ref; - pref->ref = ptr; - qry->put_ref (ptr, *pref); - return true; - } - - if (!is_gimple_assign (stmt)) - { - /* Clear BASE0 since the assigned pointer might point into - the middle of the object, set the maximum size range and, - if the SSA_NAME refers to a function argumnent, set - PREF->REF to it. */ - pref->base0 = false; - pref->set_max_size_range (); - pref->ref = ptr; - return true; - } - - tree_code code = gimple_assign_rhs_code (stmt); - - if (code == MAX_EXPR || code == MIN_EXPR) - { - if (!handle_min_max_size (ptr, ostype, pref, snlim, qry)) - return false; - - qry->put_ref (ptr, *pref); - return true; - } - - tree rhs = gimple_assign_rhs1 (stmt); - - if (code == ASSERT_EXPR) - { - rhs = TREE_OPERAND (rhs, 0); - return compute_objsize_r (rhs, stmt, ostype, pref, snlim, qry); - } - - if (code == POINTER_PLUS_EXPR - && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE) - { - /* Compute the size of the object first. */ - if (!compute_objsize_r (rhs, stmt, ostype, pref, snlim, qry)) - return false; - - offset_int orng[2]; - tree off = gimple_assign_rhs2 (stmt); - if (get_offset_range (off, stmt, orng, rvals)) - pref->add_offset (orng[0], orng[1]); - else - pref->add_max_offset (); - - qry->put_ref (ptr, *pref); - return true; - } - - if (code == ADDR_EXPR || code == SSA_NAME) - { - if (!compute_objsize_r (rhs, stmt, ostype, pref, snlim, qry)) - return false; - qry->put_ref (ptr, *pref); - return true; - } - - /* (This could also be an assignment from a nonlocal pointer.) Save - PTR to mention in diagnostics but otherwise treat it as a pointer - to an unknown object. */ - pref->ref = rhs; - pref->base0 = false; - pref->set_max_size_range (); - return true; + default: + break; } /* Assume all other expressions point into an unknown object @@ -2231,7 +2297,7 @@ compute_objsize (tree ptr, gimple *stmt, int ostype, access_ref *pref, pref->sizrng[0] = pref->sizrng[1] = -1; ssa_name_limit_t snlim; - if (!compute_objsize_r (ptr, stmt, ostype, pref, snlim, ptr_qry)) + if (!compute_objsize_r (ptr, stmt, false, ostype, pref, snlim, ptr_qry)) return NULL_TREE; offset_int maxsize = pref->size_remaining (); diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index fe46f711e96..a7ac7d34370 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -122,7 +122,7 @@ struct access_ref /* Issue an informational message describing the target of an access with the given mode. */ - void inform_access (access_mode) const; + void inform_access (access_mode, int = 1) const; /* Reference to the accessed object(s). */ tree ref; @@ -234,6 +234,8 @@ struct access_data /* Read-only for functions like memcmp or strlen, write-only for memset, read-write for memcpy or strcat. */ access_mode mode; + /* The object size type. */ + int ostype; }; enum size_range_flags From patchwork Mon Dec 6 17:32:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 48545 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 303AA3858436 for ; Mon, 6 Dec 2021 17:37:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 303AA3858436 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638812224; bh=q7AbiopmBV4auUZVeywj3S9KNvpJzQyDH+Bo1e0+ut8=; h=Subject:To:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=t0Zr7v1SIDkkNNd2sqs9IGUoflhHvUMpjtFfHLBRnJFjgB6HTIvEyojr8WW+NAheu 0HQbzdoulpGDyvgv/lMMsbMfz1/sK+rQBXFnwrua9sdMAssVtv+Vp35fX2YiN7OabK H3u6qbXqp34+GWX762lxQMCTdNbUcByXlpf+jP7c= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oo1-xc2f.google.com (mail-oo1-xc2f.google.com [IPv6:2607:f8b0:4864:20::c2f]) by sourceware.org (Postfix) with ESMTPS id DD91E3858438 for ; Mon, 6 Dec 2021 17:32:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DD91E3858438 Received: by mail-oo1-xc2f.google.com with SMTP id w5-20020a4a2745000000b002c2649b8d5fso4577902oow.10 for ; Mon, 06 Dec 2021 09:32:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=q7AbiopmBV4auUZVeywj3S9KNvpJzQyDH+Bo1e0+ut8=; b=XZi0WQHCSLEOMb0AOFFR07Fhoc5SkuNpJ/doHZ2MTv+XcbviIQuQqm1JPQwvvwnCz6 Cvo6Zhb/gibrOMUOUzvajLXlxGy+IpfiEBLCronbdEdFxw6Uu2Y9Oxs6YOiLSqQwjfvH 6JoaIjd9Sx/uerhUDEWSJOad1eJBfvFjB1mowNq6ImqIbYCvrzx52V604xa+PTVjG4fk 5/2VmRrF3spEgUnKczpklqvhRPPd9pF0gZuVZYi/LmzBWgmG4UatEvP5MLQ8LHfG/VRf tzKR+LZv8nnKdZ5yX4iryQe11b8mZ3FONL43mIjOJhP/ovq+Ik1h2ABuKeP5kNINDtId ueYQ== X-Gm-Message-State: AOAM5318l1BZd1AICXOxFglFh0w2/PbuVxLTxzvrUMRLmLsid2tzGEa7 rursgMC7nepXTxIYm+cgbqGRR3j27mA= X-Google-Smtp-Source: ABdhPJxf1F4PG6OTIXcfTvUrZ3kQHzPRHoWVOnyFzHpPJT0/e6lngpswcvxeFWCdOvEePKmBOQg81g== X-Received: by 2002:a4a:bb90:: with SMTP id h16mr22715547oop.20.1638811965261; Mon, 06 Dec 2021 09:32:45 -0800 (PST) Received: from [192.168.0.41] (184-96-227-137.hlrn.qwest.net. [184.96.227.137]) by smtp.gmail.com with ESMTPSA id z12sm2236268oor.45.2021.12.06.09.32.44 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 06 Dec 2021 09:32:44 -0800 (PST) Subject: [PATCH v2 5/5] fix up compute_objsize: add a dump function To: Jeff Law , gcc-patches References: <65d1e530-a4cc-de27-1198-0dcaa08274bd@gmail.com> Message-ID: Date: Mon, 6 Dec 2021 10:32:44 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, 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: Martin Sebor via Gcc-patches From: Martin Sebor Reply-To: Martin Sebor Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Attached is the subset of the patch in part (5) below: Add a new dump function. It applies on top of patch 4/5. On 12/3/21 5:00 PM, Jeff Law wrote: > > > On 11/8/2021 7:34 PM, Martin Sebor via Gcc-patches wrote: >> The pointer-query code that implements compute_objsize() that's >> in turn used by most middle end access warnings now has a few >> warts in it and (at least) one bug.  With the exception of >> the bug the warts aren't behind any user-visible bugs that >> I know of but they do cause problems in new code I've been >> implementing on top of it.  Besides fixing the one bug (just >> a typo) the attached patch cleans up these latent issues: >> >> 1) It moves the bndrng member from the access_ref class to >>    access_data.  As a FIXME in the code notes, the member never >>    did belong in the former and only takes up space in the cache. >> >> 2) The compute_objsize_r() function is big, unwieldy, and tedious >>    to step through because of all the if statements that are better >>    coded as one switch statement.  This change factors out more >>    of its code into smaller handler functions as has been suggested >>    and done a few times before. >> >> 3) (2) exposed a few places where I fail to pass the current >>    GIMPLE statement down to ranger.  This leads to worse quality >>    range info, including possible false positives and negatives. >>    I just spotted these problems in code review but I haven't >>    taken the time to come up with test cases.  This change fixes >>    these oversights as well. >> >> 4) The handling of PHI statements is also in one big, hard-to- >>    follow function.  This change moves the handling of each PHI >>    argument into its own handler which merges it into the previous >>    argument.  This makes the code easier to work with and opens it >>    to reuse also for MIN_EXPR and MAX_EXPR.  (This is primarily >>    used to print informational notes after warnings.) >> >> 5) Finally, the patch factors code to dump each access_ref >>    cached by the pointer_query cache out of pointer_query::dump >>    and into access_ref::dump.  This helps with debugging. >> >> These changes should have no user-visible effect and other than >> a regression test for the typo (PR 103143) come with no tests. >> They've been tested on x86_64-linux. > Sigh.  You've identified 6 distinct changes above.  The 5 you've > enumerated plus a typo fix somewhere.  There's no reason why they need > to be a single patch and many reasons why they should be a series of > independent patches.    Combining them into a single patch isn't how we > do things and it hides the actual bugfix in here. > > Please send a fix for the typo first since that should be able to > trivially go forward.  Then  a patch for item #1.  That should be > trivial to review when it's pulled out from teh rest of the patch. > Beyond that, your choice on ordering, but you need to break this down. > > > > > Jeff > commit 2054b01fb383560b96d51fabfe9dee6dbd611f4a Author: Martin Sebor Date: Mon Dec 6 09:52:32 2021 -0700 Add a new dump function. gcc/ChangeLog: * pointer-query.cc (access_ref::dump): Define new function (pointer_query::dump): Call it. * pointer-query.h (access_ref::dump): Declare new function. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 3f583110c71..e618c4d7276 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -1240,6 +1240,63 @@ access_ref::inform_access (access_mode mode, int ostype /* = 1 */) const sizestr, allocfn); } +/* Dump *THIS to FILE. */ + +void +access_ref::dump (FILE *file) const +{ + for (int i = deref; i < 0; ++i) + fputc ('&', file); + + for (int i = 0; i < deref; ++i) + fputc ('*', file); + + if (gphi *phi_stmt = phi ()) + { + fputs ("PHI <", file); + unsigned nargs = gimple_phi_num_args (phi_stmt); + for (unsigned i = 0; i != nargs; ++i) + { + tree arg = gimple_phi_arg_def (phi_stmt, i); + print_generic_expr (file, arg); + if (i + 1 < nargs) + fputs (", ", file); + } + fputc ('>', file); + } + else + print_generic_expr (file, ref); + + if (offrng[0] != offrng[1]) + fprintf (file, " + [%lli, %lli]", + (long long) offrng[0].to_shwi (), + (long long) offrng[1].to_shwi ()); + else if (offrng[0] != 0) + fprintf (file, " %c %lli", + offrng[0] < 0 ? '-' : '+', + (long long) offrng[0].to_shwi ()); + + if (base0) + fputs (" (base0)", file); + + fputs ("; size: ", file); + if (sizrng[0] != sizrng[1]) + { + offset_int maxsize = wi::to_offset (max_object_size ()); + if (sizrng[0] == 0 && sizrng[1] >= maxsize) + fputs ("unknown", file); + else + fprintf (file, "[%llu, %llu]", + (unsigned long long) sizrng[0].to_uhwi (), + (unsigned long long) sizrng[1].to_uhwi ()); + } + else if (sizrng[0] != 0) + fprintf (file, "%llu", + (unsigned long long) sizrng[0].to_uhwi ()); + + fputc ('\n', file); +} + /* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1 when MINWRITE or MINREAD, respectively, is set. */ access_data::access_data (range_query *query, gimple *stmt, access_mode mode, @@ -1498,6 +1555,9 @@ pointer_query::flush_cache () void pointer_query::dump (FILE *dump_file, bool contents /* = false */) { + if (!var_cache) + return; + unsigned nused = 0, nrefs = 0; unsigned nidxs = var_cache->indices.length (); for (unsigned i = 0; i != nidxs; ++i) @@ -1558,35 +1618,40 @@ pointer_query::dump (FILE *dump_file, bool contents /* = false */) else fprintf (dump_file, " _%u = ", ver); - if (gphi *phi = aref.phi ()) - { - fputs ("PHI <", dump_file); - unsigned nargs = gimple_phi_num_args (phi); - for (unsigned i = 0; i != nargs; ++i) - { - tree arg = gimple_phi_arg_def (phi, i); - print_generic_expr (dump_file, arg); - if (i + 1 < nargs) - fputs (", ", dump_file); - } - fputc ('>', dump_file); - } - else - print_generic_expr (dump_file, aref.ref); - - if (aref.offrng[0] != aref.offrng[1]) - fprintf (dump_file, " + [%lli, %lli]", - (long long) aref.offrng[0].to_shwi (), - (long long) aref.offrng[1].to_shwi ()); - else if (aref.offrng[0] != 0) - fprintf (dump_file, " %c %lli", - aref.offrng[0] < 0 ? '-' : '+', - (long long) aref.offrng[0].to_shwi ()); - - fputc ('\n', dump_file); + aref.dump (dump_file); } fputc ('\n', dump_file); + + { + fputs ("\npointer_query cache contents (again):\n", dump_file); + + tree var; + unsigned i; + FOR_EACH_SSA_NAME (i, var, cfun) + { + if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE) + continue; + + for (unsigned ost = 0; ost != 2; ++ost) + { + if (const access_ref *cache_ref = get_ref (var, ost)) + { + unsigned ver = SSA_NAME_VERSION (var); + fprintf (dump_file, " %u.%u: ", ver, ost); + if (tree name = ssa_name (ver)) + { + print_generic_expr (dump_file, name); + fputs (" = ", dump_file); + } + else + fprintf (dump_file, " _%u = ", ver); + + cache_ref->dump (dump_file); + } + } + } + } } /* A helper of compute_objsize_r() to determine the size from an assignment diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index a7ac7d34370..25101b75e25 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -124,6 +124,9 @@ struct access_ref with the given mode. */ void inform_access (access_mode, int = 1) const; + /* Dump *THIS to a file. */ + void dump (FILE *) const; + /* Reference to the accessed object(s). */ tree ref;