From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 100894 invoked by alias); 22 May 2015 14:42:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 100878 invoked by uid 89); 22 May 2015 14:42:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.0 required=5.0 tests=AWL,BAYES_50,KAM_LAZY_DOMAIN_SECURITY,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 22 May 2015 14:42:37 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id A1A77542D8D; Fri, 22 May 2015 16:42:33 +0200 (CEST) Date: Fri, 22 May 2015 14:59:00 -0000 From: Jan Hubicka To: Jan Hubicka Cc: Richard Biener , gcc-patches@gcc.gnu.org, mliska@suse.cz Subject: Re: Add few cases to operand_equal_p Message-ID: <20150522144232.GG75713@kam.mff.cuni.cz> References: <20150522123341.GD91616@kam.mff.cuni.cz> <20150522135025.GE75713@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150522135025.GE75713@kam.mff.cuni.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-SW-Source: 2015-05/txt/msg02132.txt.bz2 > > > + case OBJ_TYPE_REF: > > > + { > > > + if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0), > > > + OBJ_TYPE_REF_EXPR (arg1), flags)) > > > + return false; > > > + if (flag_devirtualize && virtual_method_call_p (arg0)) > > > + { > > > + if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0)) > > > + != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1))) > > > + return false; > > > + if (!types_same_for_odr (obj_type_ref_class (arg0), > > > + obj_type_ref_class (arg1))) > > > + return false; > > > > devirt machinery in operand_equal_p? please not. not more places! > > OBJ_TYPE_REF explicitly says what is the type of class whose virtual method is > called. It is GIMPLE operand expression like other, so I think we need to handle > it. > > Actually I think I can just drop the flag_devirtualize check because with > !flag_devirtualize we should simply avoid having OBJ_TYPE_REF around. That > would make it looking less devirt specific. We can also test types for > equivalence of main variant, but that would just introduce false positives when > LTO did not merged two identical ODR types. It would be correct though. After more tought, I indeed like the idea of having gimple specific matching code better (I managed to talk myself into the idea of unifying the code rather than duplicating everything, but handling generic is a pain) If we go this path, I think I can just withdraw OBJ_TYPE_REF change here. operand_equal_p conservatively consders every pair of two OBJ_TYPE_REFs different that is safe. Concerning the rest of the patch, I leave it up to your decision if we want to handle these in operand_equal_p or only at gimple level. thanks, Honza > > > > > + /* OBJ_TYPE_REF_OBJECT is used to track the instance of > > > + object THIS pointer points to. Checking that both > > > + addresses equal is safe approximation of the fact > > > + that dynamic types are equal. > > > + Do not care about the other flags, because this expression > > > + does not attribute to actual value of OBJ_TYPE_REF */ > > > + if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0), > > > + OBJ_TYPE_REF_OBJECT (arg1), > > > + OEP_ADDRESS_OF)) > > > + return false; > > > + } > > > + > > > + return true; > > > + } > > > + > > > default: > > > return 0; > > > } > > > @@ -3097,6 +3152,21 @@ operand_equal_p (const_tree arg0, const_ > > > } > > > > > > case tcc_declaration: > > > + /* At LTO time the FIELD_DECL may exist in multiple copies. > > > + We only care about offsets and bit offsets for operands. */ > > > > Err? Even at LTO time FIELD_DECLs should only appear once. > > So - testcase? > > FIELD_DECL has TREE_TYPE and TREE_TYPE may not get merged by LTO. So if the > two expressions originate from two different units, we may have two > semantically equivalent FIELD_DECLs (of compatible types and same offsets) that > occupy different memory locations because their merging was prevented by > something upstream (like complete wrt incmplete pointer in the type) > > > + /* In GIMPLE empty constructors are allowed in initializers of > > > + vector types. */ > > > > Why this comment about GIMPLE? This is about comparing GENERIC > > trees which of course can have CONSTRUCTORs of various sorts. > > > > > + if (TREE_CODE (arg0) == CONSTRUCTOR) > > > + { > > > + unsigned length1 = vec_safe_length (CONSTRUCTOR_ELTS (arg0)); > > > + unsigned length2 = vec_safe_length (CONSTRUCTOR_ELTS (arg1)); > > > + > > > + if (length1 != length2) > > > + return false; > > > + > > > + flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); > > > + > > > + for (unsigned i = 0; i < length1; i++) > > > + if (!operand_equal_p (CONSTRUCTOR_ELT (arg0, i)->value, > > > + CONSTRUCTOR_ELT (arg1, i)->value, flags)) > > > > You need to compare ->index as well here. I'm not sure constructor > > values are sorted always so you might get very many false negatives. > > many false negatives is better than all false negatices :) > > You are right, either I should punt on non-empty constructors or compare > the indexes, will do the second. > > > > + case FIELD_DECL: > > > + /* At LTO time the FIELD_DECL may exist in multiple copies. > > > + We only care about offsets and bit offsets for operands. */ > > > > So explain that this is the reason we don't want to hash by > > DECL_UID. I still think this is bogus. > > Will do if we agree on having this. > > I know you would like ipa-icf to keep original bodies and use them for inlining > declaring alias sets to be function local. This is wrong plan. Consder: > > void t(int *ptr) > { > *ptr=1; > } > > int a(int *ptr1, int *ptr2) > { > int a = *ptr1; > t(ptr2) > return a+*ptr1; > } > > long b(long *ptr1, int *ptr2) > { > int a = *ptr1; > t(ptr2) > return a+*ptr1; > } > > here aliasing leads to the two options to be optimizer differently: > a: > .LFB1: > .cfi_startproc > movl 4(%esp), %edx > movl 8(%esp), %ecx > movl (%edx), %eax > movl $1, (%ecx) > addl (%edx), %eax > ret > .cfi_endproc > b: > .LFB2: > .cfi_startproc > movl 4(%esp), %eax > movl 8(%esp), %edx > movl (%eax), %eax > movl $1, (%edx) > addl %eax, %eax > ret > .cfi_endproc > > however with -fno-early-inlining the functions look identical (modulo alias > sets) at ipa-icf time. If we merged a/b, we could get wrong code for a > even though no inlining of a or b happens. > > So either we match the alias sets or we need to verify that the alias sets > permit precisely the same set of optimizations with taking possible inlining > into account. > > I also do not believe that TBAA should be function local. I believe it is > useful to propagate stuff interprocedurally, like ipa-prop could be able to > propagate this: > > long *ptr1; > int *ptr2; > t(int *ptr) > { > return *ptr; > } > wrap(int *ptr) > { > *ptr1=1; > } > call() > { > return wrap (*ptr2); > } > > and we could have ipa-reference style pass that collect alias sets read/written by a function > and uses it during local optimization to figure out if there is a true dependence > between function call and memory store. > > Honza