On Thu, Jan 07, 2021 at 10:14:33AM +0100, Uros Bizjak wrote:
> I wonder if we should also add _cc variant where scratch is used:

So like this then if it passes bootstrap/regtest?

I think both variants are useful, e.g. one could compare the result but
store it in one of the branches etc.

2021-01-07  Jakub Jelinek  <ja...@redhat.com>

        PR target/98567
        * config/i386/i386.md (*bmi_blsi_<mode>_cmp, *bmi_blsi_<mode>_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.jj  2021-01-07 09:57:03.711083006 +0100
+++ gcc/config/i386/i386.md     2021-01-07 10:41:12.763159199 +0100
@@ -14568,6 +14568,35 @@ (define_insn "*bmi_blsi_<mode>"
    (set_attr "btver2_decode" "double")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "*bmi_blsi_<mode>_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" "<MODE>")])
+
+(define_insn "*bmi_blsi_<mode>_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" "<MODE>")])
+
 (define_insn "*bmi_blsmsk_<mode>"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
         (xor:SWI48
--- gcc/testsuite/gcc.target/i386/pr98567-1.c.jj        2021-01-07 
10:35:01.123354599 +0100
+++ gcc/testsuite/gcc.target/i386/pr98567-1.c   2021-01-07 10:35:01.123354599 
+0100
@@ -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);
+}
--- gcc/testsuite/gcc.target/i386/pr98567-2.c.jj        2021-01-07 
10:35:01.124354588 +0100
+++ gcc/testsuite/gcc.target/i386/pr98567-2.c   2021-01-07 10:35:01.124354588 
+0100
@@ -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);
+}


        Jakub

Reply via email to