From patchwork Fri Mar 17 03:27:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiufu Guo X-Patchwork-Id: 1758061 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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=) Authentication-Results: legolas.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=aMAqZQ3s; 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 ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Pd8hv0V1rz1yWs for ; Fri, 17 Mar 2023 14:27:56 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 35B043857803 for ; Fri, 17 Mar 2023 03:27:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 35B043857803 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1679023674; bh=RB44livwtikXKvT9krPA6f/maIbC0uUSWNTZ9wCKi9o=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=aMAqZQ3sz/KvFCaiXWuVTZwQQrgRhGkhh8ahuwe2mO57ney/plXtmvPj+McSSnxhG NnO15l6tChEIrk+MvBHLLlUcXT6d4fZpLSzgzzrPIvgew/Ases4KU8aS8J6wSHEPvd w87uFqXsiiMDXDGff6tz5nx6g155XfjiIPjxc45U= 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 8378D3858423; Fri, 17 Mar 2023 03:27:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8378D3858423 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 32H3COa4018041; Fri, 17 Mar 2023 03:27:31 GMT Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3pcg3b88t8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 17 Mar 2023 03:27:31 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 32H3LIAq014770; Fri, 17 Mar 2023 03:27:30 GMT Received: from ppma01fra.de.ibm.com (46.49.7a9f.ip4.static.sl-reverse.com [159.122.73.70]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3pcg3b88sm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 17 Mar 2023 03:27:30 +0000 Received: from pps.filterd (ppma01fra.de.ibm.com [127.0.0.1]) by ppma01fra.de.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 32H1Y4Yw008119; Fri, 17 Mar 2023 03:27:28 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma01fra.de.ibm.com (PPS) with ESMTPS id 3pbsmrh9dk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 17 Mar 2023 03:27:28 +0000 Received: from smtpav06.fra02v.mail.ibm.com (smtpav06.fra02v.mail.ibm.com [10.20.54.105]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 32H3ROnQ19530422 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Mar 2023 03:27:24 GMT Received: from smtpav06.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5AB1820049; Fri, 17 Mar 2023 03:27:24 +0000 (GMT) Received: from smtpav06.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E33E720043; Fri, 17 Mar 2023 03:27:22 +0000 (GMT) Received: from ltcden2-lp1.aus.stglabs.ibm.com (unknown [9.3.90.43]) by smtpav06.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 17 Mar 2023 03:27:22 +0000 (GMT) To: gcc-patches@gcc.gnu.org Cc: rguenther@suse.de, jeffreyalaw@gmail.com, segher@kernel.crashing.org, dje.gcc@gmail.com, linkw@gcc.gnu.org, guojiufu@linux.ibm.com, meissner@linux.ibm.com Subject: [PATCH V3] extract DF/SF/SI/HI/QI subreg from parameter word on stack Date: Fri, 17 Mar 2023 11:27:22 +0800 Message-Id: <20230317032722.1548833-1-guojiufu@linux.ibm.com> X-Mailer: git-send-email 2.31.1 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: lB05OOBBselJb7d8yZJjFsvfryfyEz2X X-Proofpoint-ORIG-GUID: 5w678jezFeXJxIz3D0Haq5NF1yZjb7GC X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-03-16_16,2023-03-16_02,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 priorityscore=1501 mlxlogscore=999 clxscore=1011 impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxscore=0 suspectscore=0 adultscore=0 phishscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2303150002 definitions=main-2303170016 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP 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: Jiufu Guo via Gcc-patches From: Jiufu Guo Reply-To: Jiufu Guo Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch is fixing an issue about parameter accessing if the parameter is struct type and passed through integer registers, and there is floating member is accessed. Like below code: typedef struct DF {double a[4]; long l; } DF; double foo_df (DF arg){return arg.a[3];} On ppc64le, with trunk gcc, "std 6,-24(1) ; lfd 1,-24(1)" is generated. While instruction "mtvsrd 1, 6" would be enough for this case. This patch updates the behavior when loading floating members of a parameter: if that floating member is stored via integer register, then loading it as integer mode first, and converting it to floating mode. Compare with previous patch: https://gcc.gnu.org/pipermail/gcc-patches/2023-January/609396.html This version supports the non-zero stack offset for parameter argument. I also tried to enhance CSE/DSE for this issue. But because the limitations (e.g. CSE does not like new pseudo, DSE is not good at cross-blocks), some cases (as this patch) can not be handled. Bootstrap and regtest passes on ppc64{,le}. Is this ok for trunk? Thanks for comments! BR, Jeff (Jiufu) PR target/108073 gcc/ChangeLog: * expr.cc (extract_subreg_from_loading_word): New function. (expand_expr_real_1): Call extract_subreg_from_loading_word. gcc/testsuite/ChangeLog: * g++.target/powerpc/pr102024.C: Updated. * gcc.target/powerpc/pr108073.c: New test. --- gcc/expr.cc | 85 +++++++++++++++++++++ gcc/testsuite/g++.target/powerpc/pr102024.C | 2 +- gcc/testsuite/gcc.target/powerpc/pr108073.c | 29 +++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108073.c diff --git a/gcc/expr.cc b/gcc/expr.cc index 3917fc24c8c..57bc29c5678 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -10711,6 +10711,77 @@ stmt_is_replaceable_p (gimple *stmt) return false; } +/* Return the content of the memory slot SOURCE as MODE. + SOURCE is based on BASE. BASE is a memory block that is stored via words. + + To get the content from SOURCE: + first load the word from the memory which covers the SOURCE slot first; + next return the word's subreg which offsets to SOURCE slot; + then convert to MODE as necessary. */ + +static rtx +extract_subreg_from_loading_word (machine_mode mode, rtx source, rtx base, poly_uint64 bytepos) +{ + rtx src_base = XEXP (source, 0); + poly_uint64 offset = MEM_OFFSET (source); + + if (GET_CODE (src_base) == PLUS && CONSTANT_P (XEXP (src_base, 1))) + { + offset += INTVAL (XEXP (src_base, 1)); + src_base = XEXP (src_base, 0); + } + + base = XEXP (base, 0); + if (GET_CODE (base) == PLUS && CONSTANT_P (XEXP (base, 1))) + { + poly_uint64 offset_on_base = INTVAL (XEXP (base, 1)); + base = XEXP (base, 0); + offset -= offset_on_base; + } + + if (!rtx_equal_p (base, src_base) || !known_ge (offset, bytepos)) + return NULL_RTX; + + /* Subreg(DI,n) -> DF/SF/SI/HI/QI */ + poly_uint64 word_size = GET_MODE_SIZE (word_mode); + poly_uint64 mode_size = GET_MODE_SIZE (mode); + poly_uint64 byte_off; + unsigned int start; + machine_mode int_mode; + if (known_ge (word_size, mode_size) && multiple_p (word_size, mode_size) + && int_mode_for_mode (mode).exists (&int_mode) + && can_div_trunc_p (offset, word_size, &start, &byte_off) + && multiple_p (byte_off, mode_size)) + { + rtx word_mem = copy_rtx (source); + PUT_MODE (word_mem, word_mode); + word_mem = adjust_address (word_mem, word_mode, -byte_off); + + rtx word_reg = gen_reg_rtx (word_mode); + emit_move_insn (word_reg, word_mem); + + poly_uint64 low_off = subreg_lowpart_offset (int_mode, word_mode); + if (!known_eq (byte_off, low_off)) + { + poly_uint64 shift_bytes = known_gt (byte_off, low_off) + ? byte_off - low_off + : low_off - byte_off; + word_reg = expand_shift (RSHIFT_EXPR, word_mode, word_reg, + shift_bytes * BITS_PER_UNIT, word_reg, 0); + } + + rtx int_subreg = gen_lowpart (int_mode, word_reg); + if (mode == int_mode) + return int_subreg; + + rtx int_mode_reg = gen_reg_rtx (int_mode); + emit_move_insn (int_mode_reg, int_subreg); + return gen_lowpart (mode, int_mode_reg); + } + + return NULL_RTX; +} + rtx expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, enum expand_modifier modifier, rtx *alt_rtl, @@ -11892,6 +11963,20 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && modifier != EXPAND_WRITE) op0 = flip_storage_order (mode1, op0); + /* Accessing sub-field of struct parameter which passed via integer + registers. */ + if (mode == mode1 && TREE_CODE (tem) == PARM_DECL + && DECL_INCOMING_RTL (tem) && REG_P (DECL_INCOMING_RTL (tem)) + && GET_MODE (DECL_INCOMING_RTL (tem)) == BLKmode && MEM_P (op0) + && MEM_OFFSET_KNOWN_P (op0)) + { + rtx subreg + = extract_subreg_from_loading_word (mode, op0, DECL_RTL (tem), + bytepos); + if (subreg) + op0 = subreg; + } + if (mode == mode1 || mode1 == BLKmode || mode1 == tmode || modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER) diff --git a/gcc/testsuite/g++.target/powerpc/pr102024.C b/gcc/testsuite/g++.target/powerpc/pr102024.C index 769585052b5..c8995cae707 100644 --- a/gcc/testsuite/g++.target/powerpc/pr102024.C +++ b/gcc/testsuite/g++.target/powerpc/pr102024.C @@ -5,7 +5,7 @@ // Test that a zero-width bit field in an otherwise homogeneous aggregate // generates a psabi warning and passes arguments in GPRs. -// { dg-final { scan-assembler-times {\mstd\M} 4 } } +// { dg-final { scan-assembler-times {\mmtvsrd\M} 4 } } struct a_thing { diff --git a/gcc/testsuite/gcc.target/powerpc/pr108073.c b/gcc/testsuite/gcc.target/powerpc/pr108073.c new file mode 100644 index 00000000000..7dd1a4a326a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr108073.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -save-temps" } */ + +typedef struct DF {double a[4]; short s1; short s2; short s3; short s4; } DF; +typedef struct SF {float a[4]; int i1; int i2; } SF; + +/* { dg-final { scan-assembler-times {\mmtvsrd\M} 3 {target { has_arch_ppc64 && has_arch_pwr8 } } } } */ +/* { dg-final { scan-assembler-not {\mlwz\M} {target { has_arch_ppc64 && has_arch_pwr8 } } } } */ +/* { dg-final { scan-assembler-not {\mlhz\M} {target { has_arch_ppc64 && has_arch_pwr8 } } } } */ +short __attribute__ ((noipa)) foo_hi (DF a, int flag){if (flag == 2)return a.s2+a.s3;return 0;} +int __attribute__ ((noipa)) foo_si (SF a, int flag){if (flag == 2)return a.i2+a.i1;return 0;} +double __attribute__ ((noipa)) foo_df (DF arg, int flag){if (flag == 2)return arg.a[3];else return 0.0;} +float __attribute__ ((noipa)) foo_sf (SF arg, int flag){if (flag == 2)return arg.a[2]; return 0;} +float __attribute__ ((noipa)) foo_sf1 (SF arg, int flag){if (flag == 2)return arg.a[1];return 0;} + +DF gdf = {{1.0,2.0,3.0,4.0}, 1, 2, 3, 4}; +SF gsf = {{1.0f,2.0f,3.0f,4.0f}, 1, 2}; + +int main() +{ + if (!(foo_hi (gdf, 2) == 5 && foo_si (gsf, 2) == 3 && foo_df (gdf, 2) == 4.0 + && foo_sf (gsf, 2) == 3.0 && foo_sf1 (gsf, 2) == 2.0)) + __builtin_abort (); + if (!(foo_hi (gdf, 1) == 0 && foo_si (gsf, 1) == 0 && foo_df (gdf, 1) == 0 + && foo_sf (gsf, 1) == 0 && foo_sf1 (gsf, 1) == 0)) + __builtin_abort (); + return 0; +} +