From 6bca2ebf10654b8beb5c5737c8652e8262901294 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 7 Jan 2021 17:18:58 +0100 Subject: [PATCH] i386: Optimize blsi followed by comparison [PR98567] The BLSI instruction sets SF and ZF based on the result and clears OF. CF is set to something unrelated. The following patch optimizes BLSI followed by comparison, so we don't need to emit a TEST insn in between. 2021-01-07 Jakub Jelinek PR target/98567 * config/i386/i386.md (*bmi_blsi__cmp, *bmi_blsi__ccno): New define_insn patterns. * gcc.target/i386/pr98567-1.c: New test. * gcc.target/i386/pr98567-2.c: New test. --- gcc/config/i386/i386.md | 29 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr98567-1.c | 31 +++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr98567-2.c | 31 +++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr98567-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr98567-2.c diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 6f6af8c3cbf..c1023123d5c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -14563,6 +14563,35 @@ (set_attr "btver2_decode" "double") (set_attr "mode" "")]) +(define_insn "*bmi_blsi__cmp" + [(set (reg FLAGS_REG) + (compare + (and:SWI48 + (neg:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")) + (match_dup 1)) + (const_int 0))) + (set (match_operand:SWI48 0 "register_operand" "=r") + (and:SWI48 (neg:SWI48 (match_dup 1)) (match_dup 1)))] + "TARGET_BMI && ix86_match_ccmode (insn, CCNOmode)" + "blsi\t{%1, %0|%0, %1}" + [(set_attr "type" "bitmanip") + (set_attr "btver2_decode" "double") + (set_attr "mode" "")]) + +(define_insn "*bmi_blsi__ccno" + [(set (reg FLAGS_REG) + (compare + (and:SWI48 + (neg:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")) + (match_dup 1)) + (const_int 0))) + (clobber (match_scratch:SWI48 0 "=r"))] + "TARGET_BMI && ix86_match_ccmode (insn, CCNOmode)" + "blsi\t{%1, %0|%0, %1}" + [(set_attr "type" "bitmanip") + (set_attr "btver2_decode" "double") + (set_attr "mode" "")]) + (define_insn "*bmi_blsmsk_" [(set (match_operand:SWI48 0 "register_operand" "=r") (xor:SWI48 diff --git a/gcc/testsuite/gcc.target/i386/pr98567-1.c b/gcc/testsuite/gcc.target/i386/pr98567-1.c new file mode 100644 index 00000000000..ef53ec72a91 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98567-1.c @@ -0,0 +1,31 @@ +/* PR target/98567 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mbmi -fno-stack-protector" } */ +/* { dg-final { scan-assembler-times "\tblsi" 4 } } */ +/* { dg-final { scan-assembler-times "\tsetne\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tsete\t" 2 } } */ +/* { dg-final { scan-assembler-not "\ttest\[ld]" } } */ + +int +foo (unsigned long x) +{ + return (-x & x) == 0; +} + +int +bar (unsigned int x) +{ + return (-x & x) == 0; +} + +int +baz (unsigned long x) +{ + return (x & -x) != 0; +} + +int +qux (unsigned int x) +{ + return 0 != (x & -x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr98567-2.c b/gcc/testsuite/gcc.target/i386/pr98567-2.c new file mode 100644 index 00000000000..dccb24f7127 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98567-2.c @@ -0,0 +1,31 @@ +/* PR target/98567 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mbmi -fno-stack-protector" } */ +/* { dg-final { scan-assembler-times "\tblsi" 4 } } */ +/* { dg-final { scan-assembler-times "\tsetle\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tsetg\t" 2 } } */ +/* { dg-final { scan-assembler-not "\ttest\[ld]" } } */ + +int +foo (unsigned long x) +{ + return 0 >= (int) (-x & x); +} + +int +bar (unsigned int x) +{ + return (int) (-x & x) <= 0; +} + +int +baz (unsigned long x) +{ + return (int) (x & -x) > 0; +} + +int +qux (unsigned int x) +{ + return 0 < (int) (x & -x); +} -- 2.30.2