From patchwork Tue Nov 13 01:11:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sriraman Tallam X-Patchwork-Id: 198517 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 C995F2C0081 for ; Tue, 13 Nov 2012 12:12:10 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1353373931; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:In-Reply-To:References:Date: Message-ID:Subject:From:To:Cc:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=48EJIB+Anpm3RPoUZbUmYCJnxDU=; b=DERIHrdpT40ZH9hQrO36B5ItnKiXKrovAhiooWMXv0tGzsUb/YqllmZqqSaS5s W3VOwf842JxVrJkwYRitzGDp6cizXPzkEHZKoRbYftt3vybLOAsvGooCY/XpaJZ3 xVGRkkrLmUhCZrTzAeNVTAn5dWMU0BX1ddA9ZkwI+vZf0= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:MIME-Version:Received:Received:In-Reply-To:References:Date:Message-ID:Subject:From:To:Cc:Content-Type:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=H/JyeDqs42mrEJUiWW0fZPFnIi2yXDR25zUj4gk3GA3+YXKD+tIBIiAvqNgoX1 O76/MljDDWBMUgJ9hDZOuQG8pF10OTHv+Gk0an72zWcJPOY/fnHSkFmSSRmYvwYr nSqjSGLwHe4NwY8DDn34ZTKGy8HedKE6awLZWgititsQc=; Received: (qmail 10713 invoked by alias); 13 Nov 2012 01:11:53 -0000 Received: (qmail 10702 invoked by uid 22791); 13 Nov 2012 01:11:52 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, TW_VF X-Spam-Check-By: sourceware.org Received: from mail-ob0-f175.google.com (HELO mail-ob0-f175.google.com) (209.85.214.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 13 Nov 2012 01:11:12 +0000 Received: by mail-ob0-f175.google.com with SMTP id vb8so5373338obc.20 for ; Mon, 12 Nov 2012 17:11:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:x-gm-message-state; bh=gcjaZF/Z3YCIEQnZfIaebU9YF0Qd5dzH1grMLqhzR8w=; b=Yi3NYfjme5fTfnvQvsPWjwKzWBV5rAhwQQNGgfEu/v/gRHL2qp4BuEmTbgrRFigs7I w2jwx/v3xoF6zgF+i/q/XzqTZiK+0TXUl1XipMxB5zl5c7qdBtu5WOAXEITAJEjmjRH/ t5wFToovnHrOAiiLTtUIoBgzFotTIOUDU7Wd3ElIbF12v9wM7UT6ISFx03ywQMtY+vw+ VCBkXBZ8m9y38iTQFfMmeqLO0plfTdUPSsqrMgZVTa/elSYxL6LYvLmMPQpFYOpVMGwd qUWK9OtSURSvZjt3o6aGAYSV1fRq+e/niKXN06osI+EMbgJIfxtexyuZd+W/vFrGRKsM Gl8w== MIME-Version: 1.0 Received: by 10.60.30.100 with SMTP id r4mr16412673oeh.121.1352769071939; Mon, 12 Nov 2012 17:11:11 -0800 (PST) Received: by 10.182.176.106 with HTTP; Mon, 12 Nov 2012 17:11:11 -0800 (PST) In-Reply-To: <50A08349.4070101@redhat.com> References: <506F27AF.3070805@redhat.com> <50816D63.3020908@google.com> <20121026155447.GA4348@atrey.karlin.mff.cuni.cz> <50902624.3020705@redhat.com> <50912F66.3030707@redhat.com> <50993222.3010609@redhat.com> <50A08349.4070101@redhat.com> Date: Mon, 12 Nov 2012 17:11:11 -0800 Message-ID: Subject: Re: User directed Function Multiversioning via Function Overloading (issue5752064) From: Sriraman Tallam To: Jason Merrill Cc: David Li , "H.J. Lu" , gcc-patches List , Jan Hubicka , Diego Novillo X-Gm-Message-State: ALoCoQncRfotWa8yzj5xIcp5Mhbe2BcZj/RSKSxt6wgERUeFdtNDH7YOwzrbfdDDNdNEZbNWptDuw06NcgNLMxGHZSG9hxSvWw14BxPtMOv8EFben3zhy4LYGkt0NXOxf6VCdEI2N7OLXkFo1bJe0ZkNvTJXe2wStOlF4p/+4EHjap7YSL10zbfxiABWanr19wrwVbzbvrm9 X-IsSubscribed: yes 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 Hi Jason, Made the changes. Also fixed one more segfault bug when ifunc is not supported. Thanks, -Sri. On Sun, Nov 11, 2012 at 9:04 PM, Jason Merrill wrote: > On 11/09/2012 08:33 PM, Sriraman Tallam wrote: >> >> + /* Skip calling decls_match for versioned functions. */ >> + if (DECL_FUNCTION_VERSIONED (fn) >> + && DECL_FUNCTION_VERSIONED (TREE_PURPOSE (match))) >> + continue; >> + if (!decls_match (fn, TREE_PURPOSE (match))) >> + break; > > > This seems like it would allow multiple versioned functions from different > namespaces; I want to allow mismatches only if they are versions of the same > function. I was thinking > > > for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN > (match)) > if (!decls_match (fn, TREE_PURPOSE (match)) > && !targetm.target_option.function_versions (fn, > TREE_PURPOSE (match))) > break; > >> + error_at (input_location, "Call/Pointer to multiversioned function" >> + " without a default cannot be dispatched"); > > > Let's just say "use of multiversioned function without a default". > > Jason > * cgraph.c (insert_new_cgraph_node_version): Use cgraph_get_node instead of cgraph_get_create_node. * cp/class.c (mark_versions_used): Remove. (resolve_address_of_overloaded_function): Do not call decls_match for versioned functions. Call get_function_versions_dispatcher. * cp/decl.c (duplicate_decls): Add comments. * cp/call.c (get_function_version_dispatcher): Expose function. (mark_versions_used): Expose function. * cp/cp-tree.h (mark_versions_used): New declaration. (get_function_version_dispatcher): Ditto. * config/i386/i386.c (ix86_get_function_versions_dispatcher): Move ifunc not supported code to the end. * testsuite/g++.dg/mv4.C: Add require ifunc. Change error message. * testsuite/g++.dg/mv5.C: Add require ifunc. * testsuite/g++.dg/mv6.C: Add require ifunc. Index: cgraph.c =================================================================== --- cgraph.c (revision 193452) +++ cgraph.c (working copy) @@ -206,7 +206,7 @@ insert_new_cgraph_node_version (struct cgraph_node void delete_function_version (tree decl) { - struct cgraph_node *decl_node = cgraph_get_create_node (decl); + struct cgraph_node *decl_node = cgraph_get_node (decl); struct cgraph_function_version_info *decl_v = NULL; if (decl_node == NULL) Index: testsuite/g++.dg/mv4.C =================================================================== --- testsuite/g++.dg/mv4.C (revision 193452) +++ testsuite/g++.dg/mv4.C (working copy) @@ -3,6 +3,7 @@ and its pointer is taken. */ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-ifunc "" } */ /* { dg-options "-O2 -mno-sse -mno-popcnt" } */ int __attribute__ ((target ("sse"))) @@ -18,6 +19,6 @@ foo () int main () { - int (*p)() = &foo; /* { dg-error "Pointer to a multiversioned function without a default is not allowed" {} } */ + int (*p)() = &foo; /* { dg-error "Use of multiversioned function without a default" {} } */ return (*p)(); } Index: testsuite/g++.dg/mv6.C =================================================================== --- testsuite/g++.dg/mv6.C (revision 193452) +++ testsuite/g++.dg/mv6.C (working copy) @@ -1,6 +1,7 @@ /* Test to check if member version multiversioning works correctly. */ /* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-ifunc "" } */ class Foo { Index: testsuite/g++.dg/mv5.C =================================================================== --- testsuite/g++.dg/mv5.C (revision 193452) +++ testsuite/g++.dg/mv5.C (working copy) @@ -2,6 +2,7 @@ marked comdat with inline keyword. */ /* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-ifunc "" } */ /* { dg-options "-O2 -mno-popcnt" } */ Index: cp/class.c =================================================================== --- cp/class.c (revision 193452) +++ cp/class.c (working copy) @@ -7068,38 +7068,6 @@ pop_lang_context (void) { current_lang_name = VEC_pop (tree, current_lang_base); } - -/* fn is a function version dispatcher that is marked used. Mark all the - semantically identical function versions it will dispatch as used. */ - -static void -mark_versions_used (tree fn) -{ - struct cgraph_node *node; - struct cgraph_function_version_info *node_v; - struct cgraph_function_version_info *it_v; - - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); - - node = cgraph_get_node (fn); - if (node == NULL) - return; - - gcc_assert (node->dispatcher_function); - - node_v = get_cgraph_node_version (node); - if (node_v == NULL) - return; - - /* All semantically identical versions are chained. Traverse and mark each - one of them as used. */ - it_v = node_v->next; - while (it_v != NULL) - { - mark_used (it_v->this_node->symbol.decl); - it_v = it_v->next; - } -} /* Type instantiation routines. */ @@ -7315,22 +7283,13 @@ resolve_address_of_overloaded_function (tree targe fn = TREE_PURPOSE (matches); - /* For multi-versioned functions, more than one match is just fine. - Call decls_match to make sure they are different because they are - versioned. */ - if (DECL_FUNCTION_VERSIONED (fn)) - { - for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match)) - if (!DECL_FUNCTION_VERSIONED (TREE_PURPOSE (match)) - || decls_match (fn, TREE_PURPOSE (match))) - break; - } - else - { - for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match)) - if (!decls_match (fn, TREE_PURPOSE (match))) - break; - } + /* For multi-versioned functions, more than one match is just fine and + decls_match will return false as they are different. */ + for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match)) + if (!decls_match (fn, TREE_PURPOSE (match)) + && !targetm.target_option.function_versions (fn, + TREE_PURPOSE (match))) + break; if (match) { @@ -7377,17 +7336,9 @@ resolve_address_of_overloaded_function (tree targe function version at run-time. */ if (DECL_FUNCTION_VERSIONED (fn)) { - tree dispatcher_decl = NULL; - gcc_assert (targetm.get_function_versions_dispatcher); - dispatcher_decl = targetm.get_function_versions_dispatcher (fn); - if (!dispatcher_decl) - { - error_at (input_location, "Pointer to a multiversioned function" - " without a default is not allowed"); - return error_mark_node; - } - retrofit_lang_decl (dispatcher_decl); - fn = dispatcher_decl; + fn = get_function_version_dispatcher (fn); + if (fn == NULL) + return error_mark_node; /* Mark all the versions corresponding to the dispatcher as used. */ if (!(flags & tf_conv)) mark_versions_used (fn); Index: cp/decl.c =================================================================== --- cp/decl.c (revision 193452) +++ cp/decl.c (working copy) @@ -2307,12 +2307,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool else if (DECL_PRESERVE_P (newdecl)) DECL_PRESERVE_P (olddecl) = 1; - /* If the olddecl is a version, so is the newdecl. */ + /* Merge the DECL_FUNCTION_VERSIONED information. newdecl will be copied + to olddecl and deleted. */ if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_FUNCTION_VERSIONED (olddecl)) { + /* Set the flag for newdecl so that it gets copied to olddecl. */ DECL_FUNCTION_VERSIONED (newdecl) = 1; - /* newdecl will be purged and is no longer a version. */ + /* newdecl will be purged after copying to olddecl and is no longer + a version. */ delete_function_version (newdecl); } Index: cp/call.c =================================================================== --- cp/call.c (revision 193452) +++ cp/call.c (working copy) @@ -6517,7 +6517,7 @@ magic_varargs_p (tree fn) /* Returns the decl of the dispatcher function if FN is a function version. */ -static tree +tree get_function_version_dispatcher (tree fn) { tree dispatcher_decl = NULL; @@ -6530,8 +6530,8 @@ get_function_version_dispatcher (tree fn) if (dispatcher_decl == NULL) { - error_at (input_location, "Call to multiversioned function" - " without a default is not allowed"); + error_at (input_location, "Use of multiversioned function " + "without a default"); return NULL; } @@ -6543,7 +6543,7 @@ get_function_version_dispatcher (tree fn) /* fn is a function version dispatcher that is marked used. Mark all the semantically identical function versions it will dispatch as used. */ -static void +void mark_versions_used (tree fn) { struct cgraph_node *node; Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 193452) +++ cp/cp-tree.h (working copy) @@ -4971,6 +4971,8 @@ extern bool is_list_ctor (tree); #ifdef ENABLE_CHECKING extern void validate_conversion_obstack (void); #endif /* ENABLE_CHECKING */ +extern void mark_versions_used (tree); +extern tree get_function_version_dispatcher (tree); /* in class.c */ extern tree build_vfield_ref (tree, tree); Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 193452) +++ config/i386/i386.c (working copy) @@ -28926,11 +28926,6 @@ ix86_get_function_versions_dispatcher (void *decl) #if defined (ASM_OUTPUT_TYPE_DIRECTIVE) && HAVE_GNU_INDIRECT_FUNCTION /* Right now, the dispatching is done via ifunc. */ dispatch_decl = make_dispatcher_decl (default_node->symbol.decl); -#else - error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl), - "Multiversioning needs ifunc which is not supported " - "in this configuration"); -#endif dispatcher_node = cgraph_get_create_node (dispatch_decl); gcc_assert (dispatcher_node != NULL); @@ -28947,7 +28942,11 @@ ix86_get_function_versions_dispatcher (void *decl) it_v->dispatcher_resolver = dispatch_decl; it_v = it_v->next; } - +#else + error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl), + "Multiversioning needs ifunc which is not supported " + "in this configuration"); +#endif return dispatch_decl; }