From patchwork Wed Feb 2 23:35:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 50689 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 050053857C5B for ; Wed, 2 Feb 2022 23:38:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 050053857C5B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1643845137; bh=+UincTgxRKKgIAa8xXr2999XonQ32orGMBybaa+lJs0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=PlsZ7GW7heTEEjcQtm1DqtyX1DS0s9U5xbhu1EtgiFqyEDe6dZwsSL1Wlg/r5BYRA fXh1+pEt5p/uA9KniMKkMDRDgkaxbXcnf31kbtxMA+42H7dqw7u/UQt9pfbeMWqb95 dPnocsnb97REB/qFgKuWQXwWKQXHTTlxeGUdfYJM= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-io1-xd33.google.com (mail-io1-xd33.google.com [IPv6:2607:f8b0:4864:20::d33]) by sourceware.org (Postfix) with ESMTPS id B26413858D37 for ; Wed, 2 Feb 2022 23:35:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B26413858D37 Received: by mail-io1-xd33.google.com with SMTP id c188so1099493iof.6 for ; Wed, 02 Feb 2022 15:35: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:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+UincTgxRKKgIAa8xXr2999XonQ32orGMBybaa+lJs0=; b=pF/jy9EvpmRLYhoCqREhjWK4O60iQMgj4wU+8KFabaa7EkoKn/3z6lMCikqyZhUrso arlm8zud8ll0jNeLs8HP780c1C6OlwWMPp0IFkh2XHT5KH2QA/NLsoQyaMKRBxo2h1i5 dw2bn4XPU38YPq/8DYQFb5cChXMhnnACnI7h+oXC58EzJoyDoPQSXxK9FL+UeeEn4bs2 H4TX7I77tv+PkaijwgxA1+YD66m5I3+JmdEzOD54j8Un4McjduQRLU2ymuAwwYZH1yJB 7F/96TRGiVIxsyk+Oi+FlG8On15HQbqJIShsAc3Uk5xRcOCPKMFXHvhWdZCqV4eHVUQ7 fE5w== X-Gm-Message-State: AOAM532yLGevkKluErc70FspJHwKd8o0lGfr6tAGc4R6gV2Ds2Jvm6ab ma7A3ZzvBSQpytTE0HeOAWiBCueSIBumoQ== X-Google-Smtp-Source: ABdhPJxl2MtobZDz8Wt35Z5Auf9+PLqY1GoNxKLjeDFYYf716TsVTX42dqtgV8DGlv/rFpR7OS/C1g== X-Received: by 2002:a05:6638:25c6:: with SMTP id u6mr9405756jat.187.1643844938838; Wed, 02 Feb 2022 15:35:38 -0800 (PST) Received: from bigbox.redhat.com (97-118-100-142.hlrn.qwest.net. [97.118.100.142]) by smtp.googlemail.com with ESMTPSA id l1sm7481267iln.29.2022.02.02.15.35.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Feb 2022 15:35:38 -0800 (PST) X-Google-Original-From: Martin Sebor To: gcc-patches@gcc.gnu.org Subject: [PATCH 3/3] Enable pointer_query caching for -Wrestrict. Date: Wed, 2 Feb 2022 16:35:30 -0700 Message-Id: <20220202233530.2568647-4-msebor@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220202233530.2568647-1-msebor@redhat.com> References: <20220202233530.2568647-1-msebor@redhat.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.1 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, T_SCC_BODY_TEXT_LINE 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" The third patch in the series adds a pointer_query instance to the wrestrict pass and uses it for each invocation to check a function. gcc/ChangeLog: * gimple-ssa-warn-restrict.cc (class pass_wrestrict): Outline ctor. (pass_wrestrict::m_ptr_qry): New member. (wrestrict_walk): Rename... (pass_wrestrict::check_block): ...to this. (pass_wrestrict::execute): Set up and tear down pointer_query and ranger. (builtin_memref::builtin_memref): Change ctor argument. Simplify. (builtin_access::builtin_access): Same. (builtin_access::m_ptr_qry): New member. (check_call): Rename... (pass_wrestrict::check_call): ...to this. (check_bounds_or_overlap): Change argument. * gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Same. --- gcc/gimple-ssa-warn-restrict.cc | 126 ++++++++++++++++---------------- gcc/gimple-ssa-warn-restrict.h | 2 +- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc index d1beb01fe89..72418398dad 100644 --- a/gcc/gimple-ssa-warn-restrict.cc +++ b/gcc/gimple-ssa-warn-restrict.cc @@ -62,46 +62,63 @@ const pass_data pass_data_wrestrict = { class pass_wrestrict : public gimple_opt_pass { public: - pass_wrestrict (gcc::context *ctxt) - : gimple_opt_pass (pass_data_wrestrict, ctxt) - { } + pass_wrestrict (gcc::context *); - opt_pass *clone () { return new pass_wrestrict (m_ctxt); } + // opt_pass *clone () { return new pass_wrestrict (m_ctxt); } virtual bool gate (function *); virtual unsigned int execute (function *); + + void check_call (gimple *); + + void check_block (basic_block); + + /* A pointer_query object to store information about pointers and + their targets in. */ + pointer_query m_ptr_qry; }; +pass_wrestrict::pass_wrestrict (gcc::context *ctxt) + : gimple_opt_pass (pass_data_wrestrict, ctxt), + m_ptr_qry () +{ } + bool pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED) { return warn_array_bounds || warn_restrict || warn_stringop_overflow; } -static void check_call (range_query *, gimple *); - -static void -wrestrict_walk (range_query *query, basic_block bb) +void +pass_wrestrict::check_block (basic_block bb) { /* Iterate over statements, looking for function calls. */ - for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); - gsi_next (&si)) + for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) { gimple *stmt = gsi_stmt (si); if (!is_gimple_call (stmt)) continue; - check_call (query, stmt); + check_call (stmt); } } unsigned pass_wrestrict::execute (function *fun) { - gimple_ranger ranger; + /* Create a new ranger instance and associate it with FUN. */ + m_ptr_qry.rvals = enable_ranger (fun); + basic_block bb; FOR_EACH_BB_FN (bb, fun) - wrestrict_walk (&ranger, bb); + check_block (bb); + + m_ptr_qry.flush_cache (); + + /* Release the ranger instance and replace it with a global ranger. + Also reset the pointer since calling disable_ranger() deletes it. */ + disable_ranger (fun); + m_ptr_qry.rvals = NULL; return 0; } @@ -145,7 +162,7 @@ public: only the destination reference is. */ bool strbounded_p; - builtin_memref (range_query *, gimple *, tree, tree); + builtin_memref (pointer_query &, gimple *, tree, tree); tree offset_out_of_bounds (int, offset_int[3]) const; @@ -153,7 +170,7 @@ private: /* Call statement to the built-in. */ gimple *stmt; - range_query *query; + pointer_query &m_ptr_qry; /* Ctor helper to set or extend OFFRANGE based on argument. */ void extend_offset_range (tree); @@ -187,7 +204,8 @@ class builtin_access && detect_overlap != &builtin_access::no_overlap); } - builtin_access (range_query *, gimple *, builtin_memref &, builtin_memref &); + builtin_access (pointer_query &, gimple *, + builtin_memref &, builtin_memref &); /* Entry point to determine overlap. */ bool overlap (); @@ -225,7 +243,7 @@ class builtin_access a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed to be unknown. STMT is the statement in which expr appears in. */ -builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, +builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr, tree size) : ptr (expr), ref (), @@ -238,7 +256,7 @@ builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, maxobjsize (tree_to_shwi (max_object_size ())), strbounded_p (), stmt (stmt), - query (query) + m_ptr_qry (ptrqry) { /* Unfortunately, wide_int default ctor is a no-op so array members of the type must be set individually. */ @@ -257,7 +275,7 @@ builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, tree range[2]; /* Determine the size range, allowing for the result to be [0, 0] for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */ - get_size_range (query, size, stmt, range, SR_ALLOW_ZERO); + get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO); sizrange[0] = wi::to_offset (range[0]); sizrange[1] = wi::to_offset (range[1]); /* get_size_range returns SIZE_MAX for the maximum size. @@ -334,23 +352,10 @@ builtin_memref::extend_offset_range (tree offset) /* A pointer offset is represented as sizetype but treated as signed. */ wide_int min, max; - value_range_kind rng; + value_range_kind rng = VR_VARYING; value_range vr; - if (query && query->range_of_expr (vr, offset, stmt)) - { - rng = vr.kind (); - if (!vr.undefined_p ()) - { - min = wi::to_wide (vr.min ()); - max = wi::to_wide (vr.max ()); - } - } - else + if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt)) { - /* There is a global version here because - check_bounds_or_overlap may be called from gimple - fold during gimple lowering. */ - get_range_query (cfun)->range_of_expr (vr, offset, stmt); rng = vr.kind (); if (!vr.undefined_p ()) { @@ -358,6 +363,7 @@ builtin_memref::extend_offset_range (tree offset) max = wi::to_wide (vr.max ()); } } + if (rng == VR_ANTI_RANGE && wi::lts_p (max, min)) { /* Convert an anti-range whose upper bound is less than @@ -674,7 +680,7 @@ builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const /* Create an association between the memory references DST and SRC for access by a call EXPR to a memory or string built-in funtion. */ -builtin_access::builtin_access (range_query *query, gimple *call, +builtin_access::builtin_access (pointer_query &ptrqry, gimple *call, builtin_memref &dst, builtin_memref &src) : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (), @@ -766,39 +772,28 @@ builtin_access::builtin_access (range_query *query, gimple *call, return; } - const offset_int maxobjsize = dst.maxobjsize; - /* Try to determine the size of the base object. compute_objsize expects a pointer so create one if BASE is a non-pointer object. */ - tree addr; if (dst.basesize < 0) { - addr = dst.base; - if (!POINTER_TYPE_P (TREE_TYPE (addr))) - addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - - 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; + access_ref aref; + if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0) + dst.basesize = aref.sizrng[1]; else - dst.basesize = maxobjsize; + dst.basesize = HOST_WIDE_INT_MIN; } if (src.base && src.basesize < 0) { - addr = src.base; - if (!POINTER_TYPE_P (TREE_TYPE (addr))) - addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - - 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; + access_ref aref; + if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0) + src.basesize = aref.sizrng[1]; else - src.basesize = maxobjsize; + src.basesize = HOST_WIDE_INT_MIN; } + const offset_int maxobjsize = dst.maxobjsize; + /* Make adjustments for references to the same object by string built-in functions to reflect the constraints imposed by the function. */ @@ -814,7 +809,7 @@ builtin_access::builtin_access (range_query *query, gimple *call, tree size = gimple_call_arg (call, sizeargno); tree range[2]; - if (get_size_range (query, size, call, range, true)) + if (get_size_range (ptrqry.rvals, size, call, range, true)) { bounds[0] = wi::to_offset (range[0]); bounds[1] = wi::to_offset (range[1]); @@ -1895,8 +1890,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, /* Check a CALL statement for restrict-violations and issue warnings if/when appropriate. */ -static void -check_call (range_query *query, gimple *call) +void +pass_wrestrict::check_call (gimple *call) { /* Avoid checking the call if it has already been diagnosed for some reason. */ @@ -1986,7 +1981,7 @@ check_call (range_query *query, gimple *call) || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) return; - opt_code opt = check_bounds_or_overlap (query, call, dst, src, dstwr, + opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr, NULL_TREE); /* Avoid diagnosing the call again. */ suppress_warning (call, opt); @@ -2006,25 +2001,26 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) { - return check_bounds_or_overlap (/*range_query=*/NULL, + pointer_query ptrqry (get_range_query (cfun)); + return check_bounds_or_overlap (ptrqry, call, dst, src, dstsize, srcsize, bounds_only, do_warn); } opt_code -check_bounds_or_overlap (range_query *query, +check_bounds_or_overlap (pointer_query &ptrqry, gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) { tree func = gimple_call_fndecl (call); - builtin_memref dstref (query, call, dst, dstsize); - builtin_memref srcref (query, call, src, srcsize); + builtin_memref dstref (ptrqry, call, dst, dstsize); + builtin_memref srcref (ptrqry, call, src, srcsize); /* Create a descriptor of the access. This may adjust both DSTREF and SRCREF based on one another and the kind of the access. */ - builtin_access acs (query, call, dstref, srcref); + builtin_access acs (ptrqry, call, dstref, srcref); /* Set STRICT to the value of the -Warray-bounds=N argument for string functions or when N > 1. */ diff --git a/gcc/gimple-ssa-warn-restrict.h b/gcc/gimple-ssa-warn-restrict.h index 1c60f51b500..2bdde030023 100644 --- a/gcc/gimple-ssa-warn-restrict.h +++ b/gcc/gimple-ssa-warn-restrict.h @@ -22,7 +22,7 @@ extern opt_code check_bounds_or_overlap (gimple *, tree, tree, tree, tree, bool = false, bool = true); -extern opt_code check_bounds_or_overlap (class range_query *, gimple *, +extern opt_code check_bounds_or_overlap (class pointer_query &, gimple *, tree, tree, tree, tree, bool = false, bool = true);