From patchwork Sun Sep 5 07:21:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 63820 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DCBE8B6EF0 for ; Sun, 5 Sep 2010 17:21:56 +1000 (EST) Received: (qmail 18132 invoked by alias); 5 Sep 2010 07:21:53 -0000 Received: (qmail 18124 invoked by uid 22791); 5 Sep 2010 07:21:49 -0000 X-SWARE-Spam-Status: No, hits=-5.0 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 05 Sep 2010 07:21:42 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o857Ld06013819 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 5 Sep 2010 03:21:39 -0400 Received: from freie.oliva.athome.lsd.ic.unicamp.br (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o857LZAM008067 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 5 Sep 2010 03:21:38 -0400 Received: from livre.localdomain (livre.oliva.athome.lsd.ic.unicamp.br [172.31.160.2]) by freie.oliva.athome.lsd.ic.unicamp.br (8.14.4/8.14.4) with ESMTP id o857LYEK002539 for ; Sun, 5 Sep 2010 04:21:34 -0300 Received: from livre.localdomain (aoliva@localhost [127.0.0.1]) by livre.localdomain (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id o857LWuh014332; Sun, 5 Sep 2010 04:21:32 -0300 Received: (from aoliva@localhost) by livre.localdomain (8.14.3/8.14.3/Submit) id o857LSnO014330; Sun, 5 Sep 2010 04:21:28 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR debug/45130] fix MEM_REF -fcompare-debug regression Date: Sun, 05 Sep 2010 04:21:27 -0300 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org MEM_REFs introduced some -fcompare-debug regressions. There are two main issues, both related with caching of MEM attributes. One is that top-level qualifiers in the types of the two MEM_REF operands, although irrelevant, are regarded as conversions by the tree dumpers. When e.g. copyprop replaces a non-const-qualified variable to a MEM_REF that was built out of a const-qualified temporary, we end up with a type mismatch, dumped as an explicit type conversion in the MEM_REF operand. This, compounded with the second issue, that types are disregarded by the hash and compare functions used to build the MEM attribute cache, means that the presence of debug expressions with or without the mismatches may cause a different-typed expression to be cached. Then, non-debug expressions that share the same cached MEM attrs may be dumped one way or another, failing -fcompare-debug. As it turns out, disregarding top-level qualifiers is not enough to fix the problem, because other unrelated types happen to share the same cache entry, particularly when expressions that dereference NULL are involved. To avoid this inappropriate sharing, I've added the OEP_SAME_TYPE flag to operand_equal_p, as well as to iterative_hash_expr. This would render useless the first hunk, to disregard top-level qualifiers in MEM_REF dumping, but since such mismatches are just noise anyway, I decided to leave it in. This patch enabled bootstrap with -fcompare-debug to succeed for all of stage3, including target libraries, with otherwise standard flags, on x86_64-linux-gnu and i686-pc-linux-gnu, and for stage3 similar bootstrap to succeed with -O1 and -O3 all the way to bootstrap-compare, on both platforms as well. Regression testing also passed on both platforms. Ok to install? for gcc/ChangeLog from Alexandre Oliva PR debug/45419 PR debug/45408 * tree-pretty-print.c (dump_generic_node): Disregard top-level qualifiers in otherwise equal types. * emit-rtl.c (mem_attrs_htab_hash): Hash with OEP_SAME_TYPE. (mem_attrs_htab_eq): Compare with OEP_SAME_TYPE. * fold-const.c (operand_equal_p): Handle OEP_SAME_TYPE. * tree.c (iterative_hash_expr_1): Support OEP_SAME_TYPE. Renamed from... (iterative_hash_expr): This. New wrapper. (iterative_hash_expr_flags): New. * tree.h (OEP_SAME_TYPE): New enumerator in operand_equal_flag. (iterative_hash_expr_flags): Declare. Index: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c.orig 2010-09-04 05:55:51.000000000 -0300 +++ gcc/tree-pretty-print.c 2010-09-04 05:56:06.000000000 -0300 @@ -807,8 +807,6 @@ dump_generic_node (pretty_printer *buffe == TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 1)))) && (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 0))) == TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 1)))) - && (TYPE_QUALS (TREE_TYPE (TREE_OPERAND (node, 0))) - == TYPE_QUALS (TREE_TYPE (TREE_OPERAND (node, 1)))) /* Same value types ignoring qualifiers. */ && (TYPE_MAIN_VARIANT (TREE_TYPE (node)) == TYPE_MAIN_VARIANT Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c.orig 2010-09-04 05:54:18.881551941 -0300 +++ gcc/emit-rtl.c 2010-09-04 05:56:07.000000000 -0300 @@ -260,7 +260,7 @@ mem_attrs_htab_hash (const void *x) ^ (p->addrspace * 4000) ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) ^ ((p->size ? INTVAL (p->size) : 0) * 2500000) - ^ (size_t) iterative_hash_expr (p->expr, 0)); + ^ (size_t) iterative_hash_expr_flags (p->expr, 0, OEP_SAME_TYPE)); } /* Returns nonzero if the value represented by X (which is really a @@ -278,7 +278,7 @@ mem_attrs_htab_eq (const void *x, const && p->addrspace == q->addrspace && (p->expr == q->expr || (p->expr != NULL_TREE && q->expr != NULL_TREE - && operand_equal_p (p->expr, q->expr, 0)))); + && operand_equal_p (p->expr, q->expr, OEP_SAME_TYPE)))); } /* Allocate a new mem_attrs structure and insert it into the hash table if Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c.orig 2010-09-04 05:54:18.000000000 -0300 +++ gcc/fold-const.c 2010-09-04 05:56:07.000000000 -0300 @@ -2388,7 +2388,9 @@ combine_comparisons (location_t loc, If OEP_PURE_SAME is set, then pure functions with identical arguments are considered the same. It is used when the caller has other ways - to ensure that global memory is unchanged in between. */ + to ensure that global memory is unchanged in between. + + If OEP_SAME_TYPE is set, then mismatched types */ int operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) @@ -2404,6 +2406,9 @@ operand_equal_p (const_tree arg0, const_ if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1)) return 0; + if ((flags & OEP_SAME_TYPE) && TREE_TYPE (arg0) != TREE_TYPE (arg1)) + return 0; + /* Check equality of integer constants before bailing out due to precision differences. */ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) @@ -2527,7 +2532,7 @@ operand_equal_p (const_tree arg0, const_ case ADDR_EXPR: return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), - 0); + (flags & OEP_SAME_TYPE)); default: break; } Index: gcc/tree.c =================================================================== --- gcc/tree.c.orig 2010-09-04 05:55:51.881551941 -0300 +++ gcc/tree.c 2010-09-04 12:20:57.000000000 -0300 @@ -6669,11 +6669,12 @@ commutative_ternary_tree_code (enum tree /* Generate a hash value for an expression. This can be used iteratively by passing a previous result as the VAL argument. - This function is intended to produce the same hash for expressions which - would compare equal using operand_equal_p. */ + This function is intended to produce the same hash for expressions + which would compare equal using operand_equal_p, called with the + same FLAGS. */ -hashval_t -iterative_hash_expr (const_tree t, hashval_t val) +static hashval_t +iterative_hash_expr_1 (const_tree t, hashval_t val, unsigned int flags) { int i; enum tree_code code; @@ -6682,6 +6683,9 @@ iterative_hash_expr (const_tree t, hashv if (t == NULL_TREE) return iterative_hash_hashval_t (0, val); + if (TREE_TYPE (t) && (flags & OEP_SAME_TYPE)) + val = iterative_hash_hashval_t (TYPE_UID (TREE_TYPE (t)), val); + code = TREE_CODE (t); switch (code) @@ -6707,10 +6711,10 @@ iterative_hash_expr (const_tree t, hashv return iterative_hash (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t), val); case COMPLEX_CST: - val = iterative_hash_expr (TREE_REALPART (t), val); - return iterative_hash_expr (TREE_IMAGPART (t), val); + val = iterative_hash_expr_1 (TREE_REALPART (t), val, flags); + return iterative_hash_expr_1 (TREE_IMAGPART (t), val, flags); case VECTOR_CST: - return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val); + return iterative_hash_expr_1 (TREE_VECTOR_CST_ELTS (t), val, flags); case SSA_NAME: /* We can just compare by pointer. */ return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val); @@ -6721,7 +6725,7 @@ iterative_hash_expr (const_tree t, hashv /* A list of expressions, for a CALL_EXPR or as the elements of a VECTOR_CST. */ for (; t; t = TREE_CHAIN (t)) - val = iterative_hash_expr (TREE_VALUE (t), val); + val = iterative_hash_expr_1 (TREE_VALUE (t), val, flags); return val; case CONSTRUCTOR: { @@ -6729,8 +6733,8 @@ iterative_hash_expr (const_tree t, hashv tree field, value; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value) { - val = iterative_hash_expr (field, val); - val = iterative_hash_expr (value, val); + val = iterative_hash_expr_1 (field, val, flags); + val = iterative_hash_expr_1 (value, val, flags); } return val; } @@ -6769,7 +6773,7 @@ iterative_hash_expr (const_tree t, hashv { /* Make sure to include signness in the hash computation. */ val += TYPE_UNSIGNED (TREE_TYPE (t)); - val = iterative_hash_expr (TREE_OPERAND (t, 0), val); + val = iterative_hash_expr_1 (TREE_OPERAND (t, 0), val, flags); } else if (commutative_tree_code (code)) @@ -6778,8 +6782,10 @@ iterative_hash_expr (const_tree t, hashv however it appears. We do this by first hashing both operands and then rehashing based on the order of their independent hashes. */ - hashval_t one = iterative_hash_expr (TREE_OPERAND (t, 0), 0); - hashval_t two = iterative_hash_expr (TREE_OPERAND (t, 1), 0); + hashval_t one = iterative_hash_expr_1 (TREE_OPERAND (t, 0), + 0, flags); + hashval_t two = iterative_hash_expr_1 (TREE_OPERAND (t, 1), + 0, flags); hashval_t t; if (one > two) @@ -6790,13 +6796,30 @@ iterative_hash_expr (const_tree t, hashv } else for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) - val = iterative_hash_expr (TREE_OPERAND (t, i), val); + val = iterative_hash_expr_1 (TREE_OPERAND (t, i), val, flags); } return val; break; } } +/* Wrapper for iterative_hash_expr_1, expected to be + inlined/specialized with flags == 0. */ + +hashval_t +iterative_hash_expr (const_tree t, hashval_t val) +{ + return iterative_hash_expr_1 (t, val, 0); +} + +/* Publicly-visible wrapper for iterative_hash_expr_1. */ + +hashval_t +iterative_hash_expr_flags (const_tree t, hashval_t val, unsigned int flags) +{ + return iterative_hash_expr_1 (t, val, flags); +} + /* Generate a hash value for a pair of expressions. This can be used iteratively by passing a previous result as the VAL argument. Index: gcc/tree.h =================================================================== --- gcc/tree.h.orig 2010-09-04 05:55:51.868554928 -0300 +++ gcc/tree.h 2010-09-04 05:56:07.000000000 -0300 @@ -4952,7 +4952,8 @@ extern bool fold_deferring_overflow_warn enum operand_equal_flag { OEP_ONLY_CONST = 1, - OEP_PURE_SAME = 2 + OEP_PURE_SAME = 2, + OEP_SAME_TYPE = 4 }; extern int operand_equal_p (const_tree, const_tree, unsigned int); @@ -5085,6 +5086,8 @@ extern int tree_log2 (const_tree); extern int tree_floor_log2 (const_tree); extern int simple_cst_equal (const_tree, const_tree); extern hashval_t iterative_hash_expr (const_tree, hashval_t); +extern hashval_t iterative_hash_expr_flags (const_tree, hashval_t, + unsigned int); extern hashval_t iterative_hash_exprs_commutative (const_tree, const_tree, hashval_t); extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);