public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Roger Sayle <sayle@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-792] Pre-reload splitter to transform and; cmp into not; test on x86. Date: Fri, 27 May 2022 07:53:46 +0000 (GMT) [thread overview] Message-ID: <20220527075346.2B022385737C@sourceware.org> (raw) https://gcc.gnu.org/g:29ae455901ac711470c4aa4f42d51f62e0b3753a commit r13-792-g29ae455901ac711470c4aa4f42d51f62e0b3753a Author: Roger Sayle <roger@nextmovesoftware.com> Date: Fri May 27 08:52:03 2022 +0100 Pre-reload splitter to transform and;cmp into not;test on x86. A common idiom for testing if a specific set of bits is set in a value is to use "(X & Y) == Y", which on x86 results in an AND followed by a CMP. A slightly improved implementation is to instead use (~X & Y)==0, that uses a NOT and a TEST (or ANDN where available); still two "fast" instructions, but typically shorter especially if Y is an immediate constant. Because the above transformation would require more gimple statements in SSA, and may only be a win on targets with flags registers, it isn't performed by the middle-end, instead leaving this choice to the backend. As an example, here's the change in code generation for pr91400-1.c [which now requires a tweak to its dg-final clauses]. Before: movl __cpu_model+12(%rip), %eax andl $68, %eax // 3 bytes cmpl $68, %eax // 3 bytes sete %al ret After: movl __cpu_model+12(%rip), %eax notl %eax // 2 bytes testb $68, %al // 2 bytes sete %al ret 2022-05-27 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * config/i386/i386.md (*test<mode>_not): New define_insn_and_split to split a combined "and;cmp" sequence into "not;test". gcc/testsuite/ChangeLog * gcc.target/i386/pr91400-1.c: Update for improved code generation. * gcc.target/i386/pr91400-2.c: Likewise. * gcc.target/i386/testnot-1.c: New test case. * gcc.target/i386/testnot-2.c: Likewise. Diff: --- gcc/config/i386/i386.md | 21 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr91400-1.c | 4 ++-- gcc/testsuite/gcc.target/i386/pr91400-2.c | 4 ++-- gcc/testsuite/gcc.target/i386/testnot-1.c | 24 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/testnot-2.c | 24 ++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b9b8f78dc89..602dfa799bf 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -9716,6 +9716,27 @@ operands[2] = gen_rtx_AND (mode, val, immed_wide_int_const (mask, mode)); }) +;; Split and;cmp (as optimized by combine) into not;test +;; Except when TARGET_BMI provides andn (*andn_<mode>_ccno). +(define_insn_and_split "*test<mode>_not" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ + (and:SWI + (not:SWI (match_operand:SWI 0 "register_operand")) + (match_operand:SWI 1 "<nonmemory_szext_operand>")) + (const_int 0)))] + "ix86_pre_reload_split () + && (!TARGET_BMI || !REG_P (operands[1]))" + "#" + "&& 1" + [(set (match_dup 2) (not:SWI (match_dup 0))) + (set (reg:CCZ FLAGS_REG) + (compare:CCZ (and:SWI (match_dup 2) (match_dup 1)) + (const_int 0)))] +{ + operands[2] = gen_reg_rtx (<MODE>mode); +}) + ;; Convert HImode/SImode test instructions with immediate to QImode ones. ;; i386 does not allow to encode test with 8bit sign extended immediate, so ;; this is relatively important trick. diff --git a/gcc/testsuite/gcc.target/i386/pr91400-1.c b/gcc/testsuite/gcc.target/i386/pr91400-1.c index 6124058dc1e..751dc6c824e 100644 --- a/gcc/testsuite/gcc.target/i386/pr91400-1.c +++ b/gcc/testsuite/gcc.target/i386/pr91400-1.c @@ -1,8 +1,8 @@ /* PR target/91400 */ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-final { scan-assembler-times "andl" 1 } } */ -/* { dg-final { scan-assembler-times "cmpl" 1 } } */ +/* { dg-final { scan-assembler-times "notl" 1 } } */ +/* { dg-final { scan-assembler-times "testb" 1 } } */ /* { dg-final { scan-assembler-times "sete" 1 } } */ /* { dg-final { scan-assembler-not "cmove" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91400-2.c b/gcc/testsuite/gcc.target/i386/pr91400-2.c index 1af5a2f41cd..914acd7812f 100644 --- a/gcc/testsuite/gcc.target/i386/pr91400-2.c +++ b/gcc/testsuite/gcc.target/i386/pr91400-2.c @@ -1,8 +1,8 @@ /* PR target/91400 */ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-final { scan-assembler-times "andl" 1 } } */ -/* { dg-final { scan-assembler-times "cmpl" 1 } } */ +/* { dg-final { scan-assembler-times "notl" 1 } } */ +/* { dg-final { scan-assembler-times "testb" 1 } } */ /* { dg-final { scan-assembler-times "sete" 1 } } */ /* { dg-final { scan-assembler-not "cmove" } } */ diff --git a/gcc/testsuite/gcc.target/i386/testnot-1.c b/gcc/testsuite/gcc.target/i386/testnot-1.c new file mode 100644 index 00000000000..9ebcb5c7e99 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/testnot-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int foo(int x) +{ + return (x & 1234) == 1234; +} + +int foos(short x) +{ + return (x & 1234) == 1234; +} + +int fooc(char x) +{ + return (x & 123) == 123; +} + +int fool(long long x) +{ + return (x & 1234) == 1234; +} + +/* { dg-final { scan-assembler-not "cmp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/testnot-2.c b/gcc/testsuite/gcc.target/i386/testnot-2.c new file mode 100644 index 00000000000..52fdaf361df --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/testnot-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +int foo(int x, int y) +{ + return (x & y) == y; +} + +int foos(short x, short y) +{ + return (x & y) == y; +} + +int fooc(char x, char y) +{ + return (x & y) == y; +} + +int fool(long long x, long long y) +{ + return (x & y) == y; +} + +/* { dg-final { scan-assembler-not "cmp" } } */
reply other threads:[~2022-05-27 7:53 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220527075346.2B022385737C@sourceware.org \ --to=sayle@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).