From patchwork Mon May 30 17:50:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Sayle X-Patchwork-Id: 54536 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6C4E8383E823 for ; Mon, 30 May 2022 17:52:07 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from server.nextmovesoftware.com (server.nextmovesoftware.com [162.254.253.69]) by sourceware.org (Postfix) with ESMTPS id 6FE2638515CD for ; Mon, 30 May 2022 17:50:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6FE2638515CD Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=nextmovesoftware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nextmovesoftware.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nextmovesoftware.com; s=default; h=Content-Type:MIME-Version:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Hfwx+MMFog4JBXWm3om9v6Y7CJKVLV5WxoEetMP8tVM=; b=B5rLbIRl7Opa9Dh/SR5Eu0NoQV mzYC+ODeW86V31d2P37h6Fuxm51lQxwNA4tHQDbqzf6xyrmLay1SCF6fyIdxX0Cq4wRAdpRpJ8gsj CeLf5H0Y+i84Dt+RdEOed5OPmtrfej64sW7rVg8hQmlotQT6WZCihmJkPee0Wyos7IVOeDfwFqKeF RkzJg9FSj3Bn1PqhYBIzvPnWv1fhh9O+3csgR4Skf0s0bDL5tagiZvOhn8rZGuBeYQ38fIA2xW2mH 9Fa0H3MY2chJONnUFV4sBOjjras9dArZGGY2rBh+teEGl+ggbb4UAyHopi3RzGyzQOXolphmZdzPF FE+RRIMQ==; Received: from [185.62.158.67] (port=55013 helo=Dell) by server.nextmovesoftware.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1nvjXX-0001gb-5j; Mon, 30 May 2022 13:50:51 -0400 From: "Roger Sayle" To: "'GCC Patches'" Subject: [x86 PATCH] PR rtl-optimization/101617: Use neg/sbb in ix86_expand_int_movcc. Date: Mon, 30 May 2022 18:50:49 +0100 Message-ID: <001d01d8744d$cd3a8d60$67afa820$@nextmovesoftware.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: Adh0TQhpewwLd2YjSBu7ceqgeSMlKg== Content-Language: en-gb X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server.nextmovesoftware.com X-AntiAbuse: Original Domain - gcc.gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - nextmovesoftware.com X-Get-Message-Sender-Via: server.nextmovesoftware.com: authenticated_id: roger@nextmovesoftware.com X-Authenticated-Sender: server.nextmovesoftware.com: roger@nextmovesoftware.com X-Source: X-Source-Args: X-Source-Dir: X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch resolves PR rtl-optimization/101617 where we should generate the exact same code for (X ? -1 : 1) as we do for ((X ? -1 : 0) | 1). The cause of the current difference on x86_64 is actually in ix86_expand_int_movcc that doesn't know that negl;sbbl can be used to create a -1/0 result depending on whether the input is zero/nonzero. So for Andrew Pinski's test case: int f1(int i) { return i ? -1 : 1; } GCC currently generates: f1: cmpl $1, %edi sbbl %eax, %eax // x ? 0 : -1 andl $2, %eax // x ? 0 : 2 subl $1, %eax // x ? -1 : 1 ret but with the attached patch, now generates: f1: negl %edi sbbl %eax, %eax // x ? -1 : 0 orl $1, %eax // x ? -1 : 1 ret To implement this I needed to add two expanders to i386.md to generate the required instructions (in both SImode and DImode) matching the pre-existing define_insns of the same name. This patch has been tested on x86_64-pc-linux-gnu with make bootstrap and make -k check, both with and without --target_board=unix{-m32}, with no new failures. Ok for mainline? 2022-05-30 Roger Sayle gcc/ChangeLog PR rtl-optimization/101617 * config/i386/i386-expand.cc (ix86_expand_int_movcc): Add a special case (indicated by negate_cc_compare_p) to generate a -1/0 mask using neg;sbb. * config/i386/i386.md (x86_neg_ccc): New define_expand to generate an *x86_neg_ccc instruction. (x86_movcc_0_m1_neg): Likewise, a new define_expand to generate a *x86_movcc_0_m1_neg instruction. gcc/testsuite/ChangeLog PR rtl-optimization/101617 * gcc.target/i386/pr101617.c: New test case. Thanks in advance, Roger diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 5cd7b99..36f4698 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -3142,6 +3142,7 @@ ix86_expand_int_movcc (rtx operands[]) rtx compare_op; machine_mode mode = GET_MODE (operands[0]); bool sign_bit_compare_p = false; + bool negate_cc_compare_p = false; rtx op0 = XEXP (operands[1], 0); rtx op1 = XEXP (operands[1], 1); rtx op2 = operands[2]; @@ -3188,16 +3189,48 @@ ix86_expand_int_movcc (rtx operands[]) HOST_WIDE_INT cf = INTVAL (op3); HOST_WIDE_INT diff; + if ((mode == SImode + || (TARGET_64BIT && mode == DImode)) + && (GET_MODE (op0) == SImode + || (TARGET_64BIT && GET_MODE (op0) == DImode))) + { + /* Special case x != 0 ? -1 : y. */ + if (code == NE && op1 == const0_rtx && ct == -1) + { + negate_cc_compare_p = true; + std::swap (ct, cf); + code = EQ; + } + else if (code == EQ && op1 == const0_rtx && cf == -1) + negate_cc_compare_p = true; + } + diff = ct - cf; /* Sign bit compares are better done using shifts than we do by using sbb. */ if (sign_bit_compare_p + || negate_cc_compare_p || ix86_expand_carry_flag_compare (code, op0, op1, &compare_op)) { /* Detect overlap between destination and compare sources. */ rtx tmp = out; - if (!sign_bit_compare_p) + if (negate_cc_compare_p) + { + if (GET_MODE (op0) == DImode) + emit_insn (gen_x86_negdi_ccc (gen_reg_rtx (DImode), op0)); + else + emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode), + gen_lowpart (SImode, op0))); + + tmp = gen_reg_rtx (mode); + if (mode == DImode) + emit_insn (gen_x86_movdicc_0_m1_neg (tmp)); + else + emit_insn (gen_x86_movsicc_0_m1_neg (gen_lowpart (SImode, + tmp))); + } + else if (!sign_bit_compare_p) { rtx flags; bool fpcmp = false; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 602dfa7..370df74 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -11189,6 +11189,14 @@ [(set_attr "type" "negnot") (set_attr "mode" "")]) +(define_expand "x86_neg_ccc" + [(parallel + [(set (reg:CCC FLAGS_REG) + (ne:CCC (match_operand:SWI48 1 "register_operand") + (const_int 0))) + (set (match_operand:SWI48 0 "register_operand") + (neg:SWI48 (match_dup 1)))])]) + (define_insn "*negqi_ext_2" [(set (zero_extract:SWI248 (match_operand:SWI248 0 "register_operand" "+Q") @@ -20700,6 +20708,12 @@ (set_attr "mode" "") (set_attr "length_immediate" "0")]) +(define_expand "x86_movcc_0_m1_neg" + [(parallel + [(set (match_operand:SWI48 0 "register_operand") + (neg:SWI48 (ltu:SWI48 (reg:CCC FLAGS_REG) (const_int 0)))) + (clobber (reg:CC FLAGS_REG))])]) + (define_split [(set (match_operand:SWI48 0 "register_operand") (neg:SWI48 diff --git a/gcc/testsuite/gcc.target/i386/pr101617.c b/gcc/testsuite/gcc.target/i386/pr101617.c new file mode 100644 index 0000000..503bf11 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101617.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +int f(int i) +{ + int t = i ? -1 : 0; + return t | 1; +} + +int f1(int i) +{ + int t = i ? -1 : 1; + return t; +} + +/* { dg-final { scan-assembler-times "negl" 2 } } */ +/* { dg-final { scan-assembler-times "sbbl" 2 } } */ +/* { dg-final { scan-assembler-times "orl" 2 } } */ +/* { dg-final { scan-assembler-not "cmpl" } } */ +