From patchwork Thu Jul 18 17:23:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 1133781 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-505294-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="EpiI45K8"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NsfUnXxx"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45qLZd1r2Xz9s3l for ; Fri, 19 Jul 2019 03:23:36 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=rD70qRp8zcr85Eia59mB7zL6xZnolBHJjX/czqA7BOxSpc gkP1vXdJmBcK8+fzPb4DgGPj/SCM0gYjKt6r2EIfbHPwJlcQvk0msZd4tw5YjY6c ex3JLpTsTHtqlzyDUL6oV505eaLgSkO/pDdCAnFddYFEFLo/ObBhL+ASBOmbI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=DIwF1NdFwd44mp8G7RSWO/HY/64=; b=EpiI45K8W13k5aybnSwR YxV/wBzGpZT0C5LwyWCwtUATLhRXRtOhx9tb4SJMqDjbNXxsr75NLMMpWMlr3ilW 7XwzCae/SwpRqhjwzrFiAJx2iSH7LSFn4IrWK6i/0J/WJiGrXB4Kws7N6Bk0aRzv GlHKcTcpyLc9nlFx/mpUYgM= Received: (qmail 25878 invoked by alias); 18 Jul 2019 17:23:29 -0000 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 Received: (qmail 25870 invoked by uid 89); 18 Jul 2019 17:23:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=unmatched, destructive, att X-HELO: mail-io1-f41.google.com Received: from mail-io1-f41.google.com (HELO mail-io1-f41.google.com) (209.85.166.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 18 Jul 2019 17:23:26 +0000 Received: by mail-io1-f41.google.com with SMTP id e20so22342898iob.9 for ; Thu, 18 Jul 2019 10:23:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=1kSgt/Kz7OjPy9sO87UNidd9cYTOYlXgUnuNoHOE/Gw=; b=NsfUnXxxjNj7JLnABBxNox6TFr2zZedDKrHRfaiKOjdaGWm8OyVJg1XkP2co9eZKOV 97s9IWKer2a0Z41Pf3ehHtSg+5WO+Sc8stfXtqNjjbic3qttqkE7zHzdZ/lC3fZglYTy Dt9iTXAFhs3i8jcBAWFY1/Aq1XfuoJ8MkcFE0tRH2SuxU4//iUiZ4kSU0gk3cyTyDDUu fHvYYMpjNdFPlTj/3ESO27MqjCCNgBL/ESsxCiezD2hdz9Tu862OZ2+vY3kbOi+ZsMCw 6Eg3rQtaaEV9BGBuMZzXjQijtVW2ne9vurPJ7DYu45VzxJJGz4N9kHMSg/HuyqB8wYa9 J5kA== MIME-Version: 1.0 From: Uros Bizjak Date: Thu, 18 Jul 2019 19:23:11 +0200 Message-ID: Subject: [PATCH, i386]: Fix PR 91188, strict_low_part operations do not work To: "gcc-patches@gcc.gnu.org" Attached patch fixes several strict_low_part insn patterns to operate only on register outputs. Also, the patch paves the was for patterns to handle unmatched registers (once PR82524) is fixed, and allows patterns to operate on HImode operands. 2019-07-18 Uroš Bizjak PR target/91188 * config/i386/i386.md (*addqi_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that either input operand matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*and_1_slp): Ditto. (*qi_1_slp): Ditto. (*sub_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that operand 1 matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*ashl3_1_slp): Ditto. (*3_1_slp): Ditto. (*3_1_slp): Ditto. testsuite/ChangeLog: 2019-07-18 Uroš Bizjak PR target/91188 * gcc.target/i386/pr91188-1a.c: New test. * gcc.target/i386/pr91188-1b.c: Ditto. * gcc.target/i386/pr91188-1c.c: Ditto. * gcc.target/i386/pr91188-2a.c: Ditto. * gcc.target/i386/pr91188-2b.c: Ditto. * gcc.target/i386/pr91188-2c.c: Ditto. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros. Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 273573) +++ config/i386/i386.md (working copy) @@ -5583,41 +5583,39 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*addqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*add_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (plus:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[1] == const1_rtx) - return "inc{b}\t%0"; + if (operands[2] == const1_rtx) + return "inc{}\t%0"; else { - gcc_assert (operands[1] == constm1_rtx); - return "dec{b}\t%0"; + gcc_assert (operands[2] == constm1_rtx); + return "dec{}\t%0"; } default: - if (x86_maybe_negate_const_int (&operands[1], QImode)) - return "sub{b}\t{%1, %0|%0, %1}"; + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "sub{}\t{%2, %0|%0, %2}"; - return "add{b}\t{%1, %0|%0, %1}"; + return "add{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:QI 1 "incdec_operand") + (if_then_else (match_operand:QI 2 "incdec_operand") (const_string "incdec") - (const_string "alu1"))) - (set (attr "memory") - (if_then_else (match_operand 1 "memory_operand") - (const_string "load") - (const_string "none"))) - (set_attr "mode" "QI")]) + (const_string "alu"))) + (set_attr "mode" "")]) ;; Split non destructive adds if we cannot use lea. (define_split @@ -6345,16 +6343,17 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*sub_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (minus:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "sub{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" + "sub{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_insn "*sub_2" [(set (reg FLAGS_REG) @@ -8548,16 +8547,18 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*andqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (and:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*and_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (and:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "and{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" + "and{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_split [(set (match_operand:SWI248 0 "register_operand") @@ -9098,16 +9099,18 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*qi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (any_or:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_or:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" + "{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_insn "*_2" [(set (reg FLAGS_REG) @@ -9162,7 +9165,7 @@ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && ix86_match_ccmode (insn, CCNOmode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "{b}\t{%1, %0|%0, %1}" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -10318,48 +10321,45 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*ashlqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (ashift:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*ashl3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (ashift:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[1] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { switch (get_attr_type (insn)) { - case TYPE_ALU1: - gcc_assert (operands[1] == const1_rtx); - return "add{b}\t%0, %0"; + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{}\t%0, %0"; default: - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; + return "sal{}\t%0"; else - return "sal{b}\t{%1, %0|%0, %1}"; + return "sal{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (cond [(and (and (match_test "TARGET_DOUBLE_WITH_ADD") - (match_operand 0 "register_operand")) - (match_operand 1 "const1_operand")) - (const_string "alu1") + (cond [(and (match_test "TARGET_DOUBLE_WITH_ADD") + (match_operand 2 "const1_operand")) + (const_string "alu") ] - (const_string "ishift1"))) + (const_string "ishift"))) (set (attr "length_immediate") (if_then_else - (ior (eq_attr "type" "alu1") - (and (eq_attr "type" "ishift1") - (and (match_operand 1 "const1_operand") + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) ;; Convert ashift to the lea pattern to avoid flags dependency. (define_split @@ -10937,31 +10937,30 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "*qi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (any_shiftrt:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_shiftrt:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_REG_STALL - || (operands[1] == const1_rtx - && TARGET_SHIFT1))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "{b}\t%0"; + return "{}\t%0"; else - return "{b}\t{%1, %0|%0, %1}"; + return "{}\t{%2, %0|%0, %2}"; } - [(set_attr "type" "ishift1") + [(set_attr "type" "ishift") (set (attr "length_immediate") (if_then_else - (and (match_operand 1 "const1_operand") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -11366,31 +11365,30 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "*qi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (any_rotate:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_rotate:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_REG_STALL - || (operands[1] == const1_rtx - && TARGET_SHIFT1))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "{b}\t%0"; + return "{}\t%0"; else - return "{b}\t{%1, %0|%0, %1}"; + return "{}\t{%2, %0|%0, %2}"; } - [(set_attr "type" "rotate1") + [(set_attr "type" "rotate") (set (attr "length_immediate") (if_then_else - (and (match_operand 1 "const1_operand") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) (define_split [(set (match_operand:HI 0 "QIreg_operand") Index: testsuite/gcc.target/i386/pr91188-1a.c =================================================================== --- testsuite/gcc.target/i386/pr91188-1a.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-1a.c (working copy) @@ -0,0 +1,63 @@ +/* PR target/91188 */ +/* { 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 val; + unsigned char pad1; + unsigned short pad2; +}; + +struct S +test_and (struct S a, unsigned char b) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a, unsigned char b) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a, unsigned char b) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_add (struct S a, unsigned char b) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a, unsigned char b) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ Index: testsuite/gcc.target/i386/pr91188-1b.c =================================================================== --- testsuite/gcc.target/i386/pr91188-1b.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-1b.c (working copy) @@ -0,0 +1,65 @@ +/* PR target/91188 */ +/* { 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 val; + unsigned char pad1; + unsigned short pad2; +}; + +unsigned char b; + +struct S +test_and (struct S a) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_add (struct S a) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ Index: testsuite/gcc.target/i386/pr91188-1c.c =================================================================== --- testsuite/gcc.target/i386/pr91188-1c.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-1c.c (working copy) @@ -0,0 +1,113 @@ +/* PR target/91188 */ +/* { 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 val; + unsigned char pad1; + unsigned short pad2; +}; + +struct S +test_and (struct S a) +{ + a.val &= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a) +{ + a.val |= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_sal (struct S a) +{ + a.val <<= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]salb" } } */ + +struct S +test_shr (struct S a) +{ + a.val >>= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]shrb" } } */ + +struct S +test_sar (struct S a) +{ + a.val = (signed char) a.val >> 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]sarb" } } */ + +struct S +test_rol (struct S a) +{ + a.val = (a.val << 3 | a.val >> 5) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rolb" } } */ + +struct S +test_ror (struct S a) +{ + a.val = (a.val >> 3 | a.val << 5) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rorb" } } */ + +struct S +test_add (struct S a) +{ + a.val += 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ Index: testsuite/gcc.target/i386/pr91188-2a.c =================================================================== --- testsuite/gcc.target/i386/pr91188-2a.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-2a.c (working copy) @@ -0,0 +1,62 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +struct S +test_and (struct S a, unsigned short b) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a, unsigned short b) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a, unsigned short b) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_add (struct S a, unsigned short b) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a, unsigned short b) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */ Index: testsuite/gcc.target/i386/pr91188-2b.c =================================================================== --- testsuite/gcc.target/i386/pr91188-2b.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-2b.c (working copy) @@ -0,0 +1,64 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +unsigned short b; + +struct S +test_and (struct S a) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_add (struct S a) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */ Index: testsuite/gcc.target/i386/pr91188-2c.c =================================================================== --- testsuite/gcc.target/i386/pr91188-2c.c (nonexistent) +++ testsuite/gcc.target/i386/pr91188-2c.c (working copy) @@ -0,0 +1,112 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +struct S +test_and (struct S a) +{ + a.val &= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a) +{ + a.val |= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_sal (struct S a) +{ + a.val <<= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]salw" } } */ + +struct S +test_shr (struct S a) +{ + a.val >>= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]shrw" } } */ + +struct S +test_sar (struct S a) +{ + a.val = (signed short) a.val >> 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]sarw" } } */ + +struct S +test_rol (struct S a) +{ + a.val = (a.val << 3 | a.val >> 13) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rolw" } } */ + +struct S +test_ror (struct S a) +{ + a.val = (a.val >> 3 | a.val << 13) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rorw" } } */ + +struct S +test_add (struct S a) +{ + a.val += 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */