From patchwork Fri Feb 17 16:51:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 1744366 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=8.43.85.97; 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=HM+78b+K; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (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 4PJHsQ0tnWz23r4 for ; Sat, 18 Feb 2023 03:51:52 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 034353860740 for ; Fri, 17 Feb 2023 16:51:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 034353860740 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1676652710; bh=MQjv0Cdbiwpk95Btqhfs5IQAuo2anogQQQijkp5SHg8=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=HM+78b+KR3Qs2OK0V7HfRl+HB+l+VfaZ9fMi0QNoP3iAZU+KkjjUiTctbiEefeu5W ZIQuGHeip7hr3ZvhJwHxHhIoOwrtxk1wZ1WrcaE908Pm4B690OixGz0p1M1snQxgB5 LN+1eHI4pSC6O1/xzf4V2ALYbtzpl3640rOWhMRU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) by sourceware.org (Postfix) with ESMTPS id 1862B385781F for ; Fri, 17 Feb 2023 16:51:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1862B385781F Received: by mail-yb1-xb35.google.com with SMTP id d196so1818516ybh.12 for ; Fri, 17 Feb 2023 08:51:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=MQjv0Cdbiwpk95Btqhfs5IQAuo2anogQQQijkp5SHg8=; b=aXNQcig69R7VYjYfByWUdobqFDvT2qWyO8afUQZTwiZTdOGxlOSGkmFpbrGup3GwhE 1PUEcRkmKL0vZzSH81ApP8TWLRRl18bkgxjLhJOPeWfgFmM99jd25pRL1X3SSnejFhr6 7yqE9cNwMlv4UhRzgh83CAxOSR12PmNvxPlpamTbdcCK3FRal7qxoER7J2lw19pQJ06B g56lK2VvzyRMr/w6Ym7FTS/8QoWacsU2LD0zfa53ObaXeVLHDL1riNMFnMDW6dI1H1Qy UolY91P2UBtbTuKIFoke+ils7Swknk3nUVpLpO+aOCb+3uy1Hhjo3haCwSJyDWfwPFOB 9fxw== X-Gm-Message-State: AO0yUKU+v6Tb3MM0bS+FlwDQxgfvR8Z2Mlp6Y1KzA/EhcC3oyLfMiTlw XFSvcw+F6OidzHET1HyZU3AyrtAHG3C+W5iQOLULeDFWat0KWg== X-Google-Smtp-Source: AK7set9FF6Rr0ko4n8iPnQjW1q2Bejo+kzT6l2Q+juqxnSotM13pLUEhXSstcHYAjPIIL8eGnWSFFgMS06Q/gyIR7X0= X-Received: by 2002:a5b:749:0:b0:8a9:b677:52a7 with SMTP id s9-20020a5b0749000000b008a9b67752a7mr173769ybq.30.1676652686048; Fri, 17 Feb 2023 08:51:26 -0800 (PST) MIME-Version: 1.0 Date: Fri, 17 Feb 2023 17:51:14 +0100 Message-ID: Subject: [PATCH] i386: Generate QImode binary ops with high-part input register [PR108831] To: "gcc-patches@gcc.gnu.org" X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, 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: Uros Bizjak via Gcc-patches From: Uros Bizjak Reply-To: Uros Bizjak Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Following testcase: --cut here-- struct S { unsigned char pad1; unsigned char val; unsigned short pad2; }; unsigned char test_add (unsigned char a, struct S b) { a += b.val; return a; } --cut here-- should be compiled to something like: addb %dh, %al but is currently compiled to: movzbl %dh, %edx addl %edx, %eax The patch implements insn patterns that model QImode binary ops with high-part QImode input register. These ops can not be encoded with REX prefix, so only Q registers and constant memory output operands are allowed on x86_64 targets. 2023-02-17 Uroš Bizjak gcc/ChangeLog: PR target/108831 * config/i386/predicates.md (nonimm_x64constmem_operand): New predicate. * config/i386/i386.md (*addqi_ext_0): New insn pattern. (*subqi_ext_0): Ditto. (*andqi_ext_0): Ditto. (*qi_ext_0): Ditto. gcc/testsuite/ChangeLog: PR target/108831 * gcc.target/i386/pr108831-1.c: New test. * gcc.target/i386/pr108831-2.c: Ditto. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Pushed to master. Uros. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 198f06e0769..55042e7ae15 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6641,6 +6641,22 @@ (define_insn "*add_5" (const_string "*"))) (set_attr "mode" "")]) +(define_insn "*addqi_ext_0" + [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m") + (plus:QI + (subreg:QI + (zero_extract:SWI248 + (match_operand 2 "int248_register_operand" "Q,Q") + (const_int 8) + (const_int 8)) 0) + (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0"))) + (clobber (reg:CC FLAGS_REG))] + "" + "add{b}\t{%h2, %0|%0, %h2}" + [(set_attr "isa" "*,nox64") + (set_attr "type" "alu") + (set_attr "mode" "QI")]) + (define_expand "addqi_ext_1" [(parallel [(set (zero_extract:HI (match_operand:HI 0 "register_operand") @@ -7265,6 +7281,22 @@ (define_insn "*subsi_2_zext" [(set_attr "type" "alu") (set_attr "mode" "SI")]) +(define_insn "*subqi_ext_0" + [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m") + (minus:QI + (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0") + (subreg:QI + (zero_extract:SWI248 + (match_operand 2 "int248_register_operand" "Q,Q") + (const_int 8) + (const_int 8)) 0))) + (clobber (reg:CC FLAGS_REG))] + "" + "sub{b}\t{%h2, %0|%0, %h2}" + [(set_attr "isa" "*,nox64") + (set_attr "type" "alu") + (set_attr "mode" "QI")]) + (define_insn "*subqi_ext_2" [(set (zero_extract:SWI248 (match_operand 0 "int248_register_operand" "+Q") @@ -10528,6 +10560,22 @@ (define_insn "*and_2" [(set_attr "type" "alu") (set_attr "mode" "")]) +(define_insn "*andqi_ext_0" + [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m") + (and:QI + (subreg:QI + (zero_extract:SWI248 + (match_operand 2 "int248_register_operand" "Q,Q") + (const_int 8) + (const_int 8)) 0) + (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0"))) + (clobber (reg:CC FLAGS_REG))] + "" + "and{b}\t{%h2, %0|%0, %h2}" + [(set_attr "isa" "*,nox64") + (set_attr "type" "alu") + (set_attr "mode" "QI")]) + (define_expand "andqi_ext_1" [(parallel [(set (zero_extract:HI (match_operand:HI 0 "register_operand") @@ -11269,6 +11317,22 @@ (define_insn "*_3" [(set_attr "type" "alu") (set_attr "mode" "")]) +(define_insn "*qi_ext_0" + [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m") + (any_or:QI + (subreg:QI + (zero_extract:SWI248 + (match_operand 2 "int248_register_operand" "Q,Q") + (const_int 8) + (const_int 8)) 0) + (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0"))) + (clobber (reg:CC FLAGS_REG))] + "" + "{b}\t{%h2, %0|%0, %h2}" + [(set_attr "isa" "*,nox64") + (set_attr "type" "alu") + (set_attr "mode" "QI")]) + (define_insn "*qi_ext_1" [(set (zero_extract:SWI248 (match_operand 0 "int248_register_operand" "+Q,Q") diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 2f079a6fad8..7b3db0cc851 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -109,6 +109,13 @@ (define_special_predicate "int_nonimmediate_operand" (match_test "GET_MODE (op) == HImode") (match_test "GET_MODE (op) == QImode")))) +;; Match nonimmediate operand, but exclude non-constant addresses for x86_64. +(define_predicate "nonimm_x64constmem_operand" + (ior (match_operand 0 "register_operand") + (and (match_operand 0 "memory_operand") + (ior (not (match_test "TARGET_64BIT")) + (match_test "constant_address_p (XEXP (op, 0))"))))) + ;; Match register operands, but include memory operands for TARGET_SSE_MATH. (define_predicate "register_ssemem_operand" (if_then_else diff --git a/gcc/testsuite/gcc.target/i386/pr108831-1.c b/gcc/testsuite/gcc.target/i386/pr108831-1.c new file mode 100644 index 00000000000..3499b187cbe --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr108831-1.c @@ -0,0 +1,63 @@ +/* PR target/108831 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzbl" } } */ +/* { dg-final { scan-assembler-not "movb" } } */ + +struct S +{ + unsigned char pad1; + unsigned char val; + unsigned short pad2; +}; + +unsigned char +test_and (unsigned char a, struct S b) +{ + a &= b.val; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +unsigned char +test_or (unsigned char a, struct S b) +{ + a |= b.val; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +unsigned char +test_xor (unsigned char a, struct S b) +{ + a ^= b.val; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +unsigned char +test_add (unsigned char a, struct S b) +{ + a += b.val; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +unsigned char +test_sub (unsigned char a, struct S b) +{ + a -= b.val; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr108831-2.c b/gcc/testsuite/gcc.target/i386/pr108831-2.c new file mode 100644 index 00000000000..a415391f69d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr108831-2.c @@ -0,0 +1,55 @@ +/* PR target/108831 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzbl" } } */ +/* { dg-final { scan-assembler-not "movb" } } */ + +struct S +{ + unsigned char pad1; + unsigned char val; + unsigned short pad2; +}; + +unsigned char a; + +void +test_and (struct S b) +{ + a &= b.val; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +void +test_or (struct S b) +{ + a |= b.val; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +void +test_xor (struct S b) +{ + a ^= b.val; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +void +test_add (struct S b) +{ + a += b.val; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +void +test_sub (struct S b) +{ + a -= b.val; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */