From patchwork Tue Aug 9 05:33:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kewen.Lin" X-Patchwork-Id: 1664756 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=EWsCDEsE; dkim-atps=neutral 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+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) 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 (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4M21vs4jxKz9sFs for ; Tue, 9 Aug 2022 15:33:59 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7E70C3858428 for ; Tue, 9 Aug 2022 05:33:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7E70C3858428 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1660023236; bh=ZjuMnKuKYmqWjYtmLdiroQMJ0N4JR0yJGb9Ps0YpyRs=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=EWsCDEsE1wJLESiLJ1vizStYhs11NjhFrmQ3841ZQS8wk9wlBWWWIMBwRoR51v0eW ndjnaTK5YGN9+IJFgAM3sy8+O6RL9N4adiHLxRr+T4D18LZzlQhksNGdEB1hTwc6Oo 3DiGXFt4ELlOgev9ai/c8xxbCBs54tCaFT8UmxE0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 0DDF03858C54 for ; Tue, 9 Aug 2022 05:33:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0DDF03858C54 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2794TkqQ022023; Tue, 9 Aug 2022 05:33:33 GMT Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3hugkw1hr8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 09 Aug 2022 05:33:33 +0000 Received: from m0098399.ppops.net (m0098399.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 2795GKdP025540; Tue, 9 Aug 2022 05:33:32 GMT Received: from ppma03ams.nl.ibm.com (62.31.33a9.ip4.static.sl-reverse.com [169.51.49.98]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3hugkw1hq9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 09 Aug 2022 05:33:32 +0000 Received: from pps.filterd (ppma03ams.nl.ibm.com [127.0.0.1]) by ppma03ams.nl.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 2795M84M030078; Tue, 9 Aug 2022 05:33:30 GMT Received: from b06avi18878370.portsmouth.uk.ibm.com (b06avi18878370.portsmouth.uk.ibm.com [9.149.26.194]) by ppma03ams.nl.ibm.com with ESMTP id 3hsfx8u1mb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 09 Aug 2022 05:33:29 +0000 Received: from d06av24.portsmouth.uk.ibm.com (d06av24.portsmouth.uk.ibm.com [9.149.105.60]) by b06avi18878370.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 2795XieL34079048 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 9 Aug 2022 05:33:44 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B47DC4203F; Tue, 9 Aug 2022 05:33:27 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D884242041; Tue, 9 Aug 2022 05:33:25 +0000 (GMT) Received: from [9.197.252.244] (unknown [9.197.252.244]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Tue, 9 Aug 2022 05:33:25 +0000 (GMT) Message-ID: Date: Tue, 9 Aug 2022 13:33:24 +0800 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.6.1 Content-Language: en-US To: GCC Patches Subject: [PATCH] rs6000: Rework ELFv2 support for -fpatchable-function-entry* [PR99888] X-TM-AS-GCONF: 00 X-Proofpoint-GUID: V3d1RlxblSVbUJfuBb_PHbN7_1Vm2sJk X-Proofpoint-ORIG-GUID: hwIqapBSZ9kp13T63xCmo7mTUChCsKXt X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-09_03,2022-08-09_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 suspectscore=0 adultscore=0 priorityscore=1501 spamscore=0 mlxscore=0 impostorscore=0 phishscore=0 lowpriorityscore=0 bulkscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2206140000 definitions=main-2208090023 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: "Kewen.Lin via Gcc-patches" From: "Kewen.Lin" Reply-To: "Kewen.Lin" Cc: David Edelsohn , Segher Boessenkool , amodra@gmail.com Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, As PR99888 and its related show, the current support for -fpatchable-function-entry on powerpc ELFv2 doesn't work well with global entry existence. For example, with one command line option -fpatchable-function-entry=3,2, it got below w/o this patch: .LPFE1: nop nop .type foo, @function foo: nop .LFB0: .cfi_startproc .LCF0: 0: addis 2,12,.TOC.-.LCF0@ha addi 2,2,.TOC.-.LCF0@l .localentry foo,.-foo , the assembly is unexpected since the patched NOPs have no effects when being entered from local entry. This patch is to update the NOPs patched before and after local entry, it looks like: .type foo, @function foo: .LFB0: .cfi_startproc .LCF0: 0: addis 2,12,.TOC.-.LCF0@ha addi 2,2,.TOC.-.LCF0@l nop nop .localentry foo,.-foo nop Bootstrapped and regtested on powerpc64-linux-gnu P7 & P8, and powerpc64le-linux-gnu P9 & P10. Is it ok for trunk? BR, Kewen ----- PR target/99888 PR target/105649 gcc/ChangeLog: * config/rs6000/rs6000-internal.h (rs6000_print_patchable_function_entry): New function declaration. * config/rs6000/rs6000-logue.cc (rs6000_output_function_prologue): Support patchable-function-entry by emitting NOPs before and after local entry for the function that needs global entry. * config/rs6000/rs6000.cc (rs6000_print_patchable_function_entry): Skip the function that needs global entry till global entry has been emitted. * config/rs6000/rs6000.h (struct machine_function): New bool member global_entry_emitted. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr99888-1.c: New test. * gcc.target/powerpc/pr99888-2.c: New test. * gcc.target/powerpc/pr99888-3.c: New test. * gcc.target/powerpc/pr99888-4.c: New test. * gcc.target/powerpc/pr99888-5.c: New test. * gcc.target/powerpc/pr99888-6.c: New test. * c-c++-common/patchable_function_entry-default.c: Adjust for powerpc_elfv2 to avoid compilation error. --- gcc/config/rs6000/rs6000-internal.h | 5 ++ gcc/config/rs6000/rs6000-logue.cc | 29 ++++++++++++ gcc/config/rs6000/rs6000.cc | 10 +++- gcc/config/rs6000/rs6000.h | 4 ++ .../patchable_function_entry-default.c | 1 + gcc/testsuite/gcc.target/powerpc/pr99888-1.c | 47 +++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr99888-2.c | 47 +++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr99888-3.c | 13 +++++ gcc/testsuite/gcc.target/powerpc/pr99888-4.c | 13 +++++ gcc/testsuite/gcc.target/powerpc/pr99888-5.c | 13 +++++ gcc/testsuite/gcc.target/powerpc/pr99888-6.c | 14 ++++++ 11 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-3.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-4.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-5.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr99888-6.c -- 2.27.0 diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index b9e82c0468d..da809d1ac8b 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -182,10 +182,15 @@ extern tree rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, tree *args ATTRIBUTE_UNUSED, bool ignore ATTRIBUTE_UNUSED); +extern void rs6000_print_patchable_function_entry (FILE *, + unsigned HOST_WIDE_INT, + bool); + extern bool rs6000_passes_float; extern bool rs6000_passes_long_double; extern bool rs6000_passes_vector; extern bool rs6000_returns_struct; extern bool cpu_builtin_p; #endif diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index 59fe1c8cb8b..ca0a6c1c64a 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4013,11 +4013,40 @@ rs6000_output_function_prologue (FILE *file) fprintf (file, "\tadd 2,2,12\n"); } + unsigned short patch_area_size = crtl->patch_area_size; + unsigned short patch_area_entry = crtl->patch_area_entry; + /* Need to emit the patching area. */ + if (patch_area_size > 0) + { + cfun->machine->global_entry_emitted = true; + /* As ELFv2 ABI shows, the allowable bytes past the global entry + point are 0, 4, 8, 16, 32 and 64. Considering there are two + non-prefixed instructions for global entry (8 bytes), the count + for patchable NOPs before local entry would be 2, 6 and 14. */ + if (patch_area_entry > 0) + { + if (patch_area_entry != 2 + && patch_area_entry != 6 + && patch_area_entry != 14) + error ("for %<-fpatchable-function-entry=%u,%u%>, patching " + "%u NOP(s) before function entry is invalid, it can " + "cause assembler error", + patch_area_size, patch_area_entry, patch_area_entry); + rs6000_print_patchable_function_entry (file, patch_area_entry, + true); + patch_area_size -= patch_area_entry; + } + } + fputs ("\t.localentry\t", file); assemble_name (file, name); fputs (",.-", file); assemble_name (file, name); fputs ("\n", file); + /* Emit the NOPs after local entry. */ + if (patch_area_size > 0) + rs6000_print_patchable_function_entry (file, patch_area_size, + patch_area_entry == 0); } else if (rs6000_pcrel_p ()) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 777a06599c3..c79a0ee7a49 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -14898,8 +14898,14 @@ rs6000_print_patchable_function_entry (FILE *file, if (!(TARGET_64BIT && DEFAULT_ABI != ABI_ELFv2) && HAVE_GAS_SECTION_LINK_ORDER) flags |= SECTION_LINK_ORDER; - default_print_patchable_function_entry_1 (file, patch_area_size, record_p, - flags); + bool global_entry_needed_p = rs6000_global_entry_point_prologue_needed_p (); + /* For a function which needs global entry point, we will emit the + patchable area before and after local entry point under the control of + cfun->machine->global_entry_emitted, see the handling in function + rs6000_output_function_prologue. */ + if (!global_entry_needed_p || cfun->machine->global_entry_emitted) + default_print_patchable_function_entry_1 (file, patch_area_size, record_p, + flags); } enum rtx_code diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index ad9bf0f7358..c352421e87c 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2439,6 +2439,10 @@ typedef struct GTY(()) machine_function bool lr_is_wrapped_separately; bool toc_is_wrapped_separately; bool mma_return_type_error; + /* Indicate global entry is emitted, only useful when the function requires + global entry. It helps to control the patchable area before and after + local entry. */ + bool global_entry_emitted; } machine_function; #endif diff --git a/gcc/testsuite/c-c++-common/patchable_function_entry-default.c b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c index 7036f7bfbea..fc9ab9ac8cd 100644 --- a/gcc/testsuite/c-c++-common/patchable_function_entry-default.c +++ b/gcc/testsuite/c-c++-common/patchable_function_entry-default.c @@ -1,6 +1,7 @@ /* { dg-do compile { target { ! { nvptx*-*-* visium-*-* } } } } */ /* { dg-options "-O2 -fpatchable-function-entry=3,1" } */ /* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */ +/* { dg-additional-options "-fpatchable-function-entry=3,2" { target powerpc_elfv2 } } */ /* { dg-final { scan-assembler-times "nop|NOP|SWYM" 3 { target { ! { alpha*-*-* } } } } } */ /* { dg-final { scan-assembler-times "bis" 3 { target alpha*-*-* } } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-1.c b/gcc/testsuite/gcc.target/powerpc/pr99888-1.c new file mode 100644 index 00000000000..b9d8acdca5d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-1.c @@ -0,0 +1,47 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9" } */ + +/* Verify no errors for different NOPs after local entry. */ + +extern int a; + +__attribute__ ((noipa, patchable_function_entry (1, 0))) +int test1 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (2, 0))) +int test2 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (3, 0))) +int test3 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (4, 0))) +int test4 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (5, 0))) +int test5 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (6, 0))) +int test6 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (7, 0))) +int test7 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (8, 0))) +int test8 (int b) { + return a + b; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-2.c b/gcc/testsuite/gcc.target/powerpc/pr99888-2.c new file mode 100644 index 00000000000..eee66752ee6 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-2.c @@ -0,0 +1,47 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9" } */ + +/* Verify no errors for 2, 6 and 14 NOPs before local entry. */ + +extern int a; + +__attribute__ ((noipa, patchable_function_entry (2, 2))) +int test1 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (4, 2))) +int test2 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (6, 6))) +int test3 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (8, 6))) +int test4 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (16, 6))) +int test5 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (14, 14))) +int test6 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (28, 14))) +int test7 (int b) { + return a + b; +} + +__attribute__ ((noipa, patchable_function_entry (64, 14))) +int test8 (int b) { + return a + b; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-3.c b/gcc/testsuite/gcc.target/powerpc/pr99888-3.c new file mode 100644 index 00000000000..ab86791d259 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-3.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9 -fpatchable-function-entry=1" } */ + +/* Verify no errors, using command line option instead of function + attribute. */ + +extern int a; + +int test (int b) { + return a + b; +} + diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-4.c b/gcc/testsuite/gcc.target/powerpc/pr99888-4.c new file mode 100644 index 00000000000..f17d2335a76 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-4.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9 -fpatchable-function-entry=1,1" } */ + +/* Verify one error emitted for unexpected 1 NOP before local + entry. */ + +extern int a; + +int test (int b) { + return a + b; +} +/* { dg-error "for '-fpatchable-function-entry=1,1', patching 1 NOP\\(s\\) before function entry is invalid, it can cause assembler error" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-5.c b/gcc/testsuite/gcc.target/powerpc/pr99888-5.c new file mode 100644 index 00000000000..66087db7629 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-5.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9 -fpatchable-function-entry=7,3" } */ + +/* Verify one error emitted for unexpected 3 NOP before local + entry. */ + +extern int a; + +int test (int b) { + return a + b; +} +/* { dg-error "for '-fpatchable-function-entry=7,3', patching 3 NOP\\(s\\) before function entry is invalid, it can cause assembler error" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr99888-6.c b/gcc/testsuite/gcc.target/powerpc/pr99888-6.c new file mode 100644 index 00000000000..5c116a49d50 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr99888-6.c @@ -0,0 +1,14 @@ +/* { dg-require-effective-target powerpc_elfv2 } */ +/* Specify -mcpu=power9 to ensure global entry is needed. */ +/* { dg-options "-mdejagnu-cpu=power9" } */ + +/* Verify one error emitted for unexpected 4 NOP before local + entry. */ + +extern int a; + +__attribute__ ((noipa, patchable_function_entry (20, 4))) +int test (int b) { + return a + b; +} +/* { dg-error "for '-fpatchable-function-entry=20,4', patching 4 NOP\\(s\\) before function entry is invalid, it can cause assembler error" "" { target *-*-* } .-1 } */