From patchwork Fri Nov 13 14:37:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 1399837 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=FapCgpBE; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CXgzZ0WZvz9s1l for ; Sat, 14 Nov 2020 01:37:30 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 865663A51412; Fri, 13 Nov 2020 14:37:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 865663A51412 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1605278247; bh=Ln+V0XMZ3hNtxdDGmkAFp1uu9aY6OpnGKEPaOu+GJjA=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=FapCgpBEjqh9RGI5yEIG2pVtS2nOY14GiBRoOJObEX1PWE5eeqzS4qc6u0wgfLk/1 TkpMNMVHGzcamnaaqPOBI1dMxCUGi/ms8onyTbaJRd4SF4kBcG9E+9TcSkqotgNPUb UofDxKg3p7x0WyMNXuaqmJ0RPI8SopfhfR4HDnRE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 6B338386F02C for ; Fri, 13 Nov 2020 14:37:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 6B338386F02C Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-201-jNwa-q9UN0mHV2pjfIylPA-1; Fri, 13 Nov 2020 09:37:19 -0500 X-MC-Unique: jNwa-q9UN0mHV2pjfIylPA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E9A221007468 for ; Fri, 13 Nov 2020 14:37:18 +0000 (UTC) Received: from [10.10.119.201] (ovpn-119-201.rdu2.redhat.com [10.10.119.201]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7CD4C1FDDD for ; Fri, 13 Nov 2020 14:37:16 +0000 (UTC) To: gcc-patches Subject: [PATCH] Cleanup range of address calculations. Message-ID: <2f9d9171-481e-77dd-c669-271302010380@redhat.com> Date: Fri, 13 Nov 2020 09:37:14 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Andrew MacLeod via Gcc-patches From: Andrew MacLeod Reply-To: Andrew MacLeod Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" There were some slight differences between when ranger would get non-zero for &expr and what EVRP was getting. Ive extracted the bits from vrp_stmt_computes_nonzero required and now the 2 versions should be aligned. Ive also renamed the function from the previously cryptic range_of_non_trivial_assignment () to simply range_of_address (). I also discovered we were not tracking integral constants, like 0, (AKA NULL) for pointers, so I added the constant handler in the pointer table. I modified a test from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78655 which shows some cases which track non-zero and zero and verified we remove bits when we can. Disabled all the previous passes so that EVRp actually sees the code and can make decisions. bootstrapped on x86_64-pc-linux-gnu, no regressions. Pushed. Andrew commit 47923622c663ffad8b14aa93706183290d4f6791 Author: Andrew MacLeod Date: Thu Nov 12 11:53:52 2020 -0500 Cleanup range of address calculations. Align EVRP and ranger for how ranges of ADDR_EXPR are calculated. gcc/ * gimple-range.cc: (gimple_ranger::range_of_range_op): Check for ADDR_EXPR and call range_of_address. (gimple_ranger::range_of_address): Rename from range_of_non_trivial_assignment and match vrp_stmt_computes_nonzero. * gimple-range.h: (range_of_address): Renamed. * range-op.cc: (pointer_table): Add INTEGER_CST handler. gcc/testsuite/ * gcc.dg/tree-ssa/pr78655.c: New. diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 92a6335bec5..4f5d5024fa9 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -431,8 +431,9 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s) m_cache.register_dependency (lhs, op2); } - if (range_of_non_trivial_assignment (r, s)) - return true; + if (gimple_code (s) == GIMPLE_ASSIGN + && gimple_assign_rhs_code (s) == ADDR_EXPR) + return range_of_address (r, s); if (range_of_expr (range1, op1, s)) { @@ -446,48 +447,84 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s) return true; } -// Calculate the range of a non-trivial assignment. That is, is one -// inolving arithmetic on an SSA name (for example, an ADDR_EXPR). +// Calculate the range of an assignment containing an ADDR_EXPR. // Return the range in R. -// -// If a range cannot be calculated, return false. +// If a range cannot be calculated, set it to VARYING and return true. bool -gimple_ranger::range_of_non_trivial_assignment (irange &r, gimple *stmt) +gimple_ranger::range_of_address (irange &r, gimple *stmt) { - if (gimple_code (stmt) != GIMPLE_ASSIGN) - return false; + gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN); + gcc_checking_assert (gimple_assign_rhs_code (stmt) == ADDR_EXPR); - tree base = gimple_range_base_of_assignment (stmt); - if (base) + bool strict_overflow_p; + tree expr = gimple_assign_rhs1 (stmt); + poly_int64 bitsize, bitpos; + tree offset; + machine_mode mode; + int unsignedp, reversep, volatilep; + tree base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, + &bitpos, &offset, &mode, &unsignedp, + &reversep, &volatilep); + + + if (base != NULL_TREE + && TREE_CODE (base) == MEM_REF + && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) { - if (TREE_CODE (base) == MEM_REF) + tree ssa = TREE_OPERAND (base, 0); + gcc_checking_assert (irange::supports_type_p (TREE_TYPE (ssa))); + range_of_expr (r, ssa, stmt); + range_cast (r, TREE_TYPE (gimple_assign_rhs1 (stmt))); + + poly_offset_int off = 0; + bool off_cst = false; + if (offset == NULL_TREE || TREE_CODE (offset) == INTEGER_CST) { - if (TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) - { - int_range_max range1; - tree ssa = TREE_OPERAND (base, 0); - if (range_of_expr (range1, ssa, stmt)) - { - tree type = TREE_TYPE (ssa); - range_operator *op = range_op_handler (POINTER_PLUS_EXPR, - type); - int_range<2> offset (TREE_OPERAND (base, 1), - TREE_OPERAND (base, 1)); - op->fold_range (r, type, range1, offset); - return true; - } - } - return false; + off = mem_ref_offset (base); + if (offset) + off += poly_offset_int::from (wi::to_poly_wide (offset), + SIGNED); + off <<= LOG2_BITS_PER_UNIT; + off += bitpos; + off_cst = true; } - if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) + /* If &X->a is equal to X, the range of X is the result. */ + if (off_cst && known_eq (off, 0)) + return true; + else if (flag_delete_null_pointer_checks + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))) + { + /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't + allow going from non-NULL pointer to NULL. */ + if(!range_includes_zero_p (&r)) + return true; + } + /* If MEM_REF has a "positive" offset, consider it non-NULL + always, for -fdelete-null-pointer-checks also "negative" + ones. Punt for unknown offsets (e.g. variable ones). */ + if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)) + && off_cst + && known_ne (off, 0) + && (flag_delete_null_pointer_checks || known_gt (off, 0))) { - // Handle "= &a" and return non-zero. r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } + r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; } - return false; + + // Handle "= &a". + if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p)) + { + r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; + } + + // Otherwise return varying. + r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + return true; } // Calculate a range for phi statement S and return it in R. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 88d2ada324b..dde41e9e743 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -62,7 +62,7 @@ protected: ranger_cache m_cache; private: bool range_of_phi (irange &r, gphi *phi); - bool range_of_non_trivial_assignment (irange &r, gimple *s); + bool range_of_address (irange &r, gimple *s); bool range_of_builtin_call (irange &r, gcall *call); bool range_with_loop_info (irange &r, tree name); void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 86d1af7fe54..b746aadb603 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3328,6 +3328,7 @@ pointer_table::pointer_table () set (GT_EXPR, op_gt); set (GE_EXPR, op_ge); set (SSA_NAME, op_identity); + set (INTEGER_CST, op_integer_cst); set (ADDR_EXPR, op_addr); set (NOP_EXPR, op_convert); set (CONVERT_EXPR, op_convert); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c new file mode 100644 index 00000000000..e9158e07268 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78655.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fdump-tree-evrp" } */ + +struct A{int a,b;}; +inline int*f1(struct A*p){return&p->a;} /* offset of 0. */ +inline int*f2(struct A*p){return&p->b;} /* Offset of non-zero. */ +inline int*g(struct A*p){return(int*)p+1;} /* Always non-zero offet. */ + +/* Should be able to eliminate all calls to bad(). */ + +void bad(void); + +int +main() +{ + struct A* ptr = 0; + struct A addr; + + if (f1 (ptr) != 0) + bad(); + if (f1 (&addr) == 0) + bad(); + + if (f2 (ptr) == 0) + bad(); + if (f2 (&addr) == 0) + bad(); + + if (g (ptr) == 0) + bad(); + if (g (&addr) == 0) + bad(); + +} + +/* { dg-final { scan-tree-dump-not "bad" "evrp"} } */ +