re PR target/59874 (Missing builtin (__builtin_clzs) when compiling with g++)
authorUros Bizjak <ubizjak@gmail.com>
Wed, 14 Dec 2016 20:27:06 +0000 (21:27 +0100)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 14 Dec 2016 20:27:06 +0000 (21:27 +0100)
PR target/59874
* config/i386/i386-builtin.def: Add __builtin_clzs and __builtin_ctzs.
(ix86_fold_builtin): Handle IX86_BUILTIN_CTZS and IX86_BUILTIN_CLZS.
* config/i386/i386.md (*ctzhi2): New insn_and_split pattern.
(*clzhi2): Ditto.

testsuite/ChangeLog

PR target/59874
* gcc.target/i386/pr59874-1.c: New test.
* gcc.target/i386/pr59874-2.c: Ditto.

From-SVN: r243668

gcc/ChangeLog
gcc/config/i386/i386-builtin.def
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr59874-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr59874-2.c [new file with mode: 0644]

index 259389ee69ea48bc3db33073bf0cd73415dff741..1fbc8727a52e8ac6ad03a3fe9299e3018bedc6ae 100644 (file)
@@ -1,3 +1,11 @@
+2016-12-14  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/59874
+       * config/i386/i386-builtin.def: Add __builtin_clzs and __builtin_ctzs.
+       (ix86_fold_builtin): Handle IX86_BUILTIN_CTZS and IX86_BUILTIN_CLZS.
+       * config/i386/i386.md (*ctzhi2): New insn_and_split pattern.
+       (*clzhi2): Ditto.
+
 2016-12-14  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/77844
index 83a508909babb641329b0fa838fcf29d515d7177..498207a9a537d2cefceb09b9330e2c0c396836fe 100644 (file)
@@ -1188,6 +1188,8 @@ BDESC (OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshrvv4si, "__builtin_ia32_psrlv4si",
 
 /* LZCNT */
 BDESC (OPTION_MASK_ISA_LZCNT, CODE_FOR_lzcnt_hi, "__builtin_ia32_lzcnt_u16", IX86_BUILTIN_LZCNT16, UNKNOWN, (int) UINT16_FTYPE_UINT16)
+/* Same as above, for backward compatibility.  */
+BDESC (OPTION_MASK_ISA_LZCNT, CODE_FOR_lzcnt_hi, "__builtin_clzs", IX86_BUILTIN_CLZS, UNKNOWN, (int) UINT16_FTYPE_UINT16)
 BDESC (OPTION_MASK_ISA_LZCNT, CODE_FOR_lzcnt_si, "__builtin_ia32_lzcnt_u32", IX86_BUILTIN_LZCNT32, UNKNOWN, (int) UINT_FTYPE_UINT)
 BDESC (OPTION_MASK_ISA_LZCNT | OPTION_MASK_ISA_64BIT, CODE_FOR_lzcnt_di, "__builtin_ia32_lzcnt_u64", IX86_BUILTIN_LZCNT64, UNKNOWN, (int) UINT64_FTYPE_UINT64)
 
@@ -1196,6 +1198,8 @@ BDESC (OPTION_MASK_ISA_BMI, CODE_FOR_bmi_bextr_si, "__builtin_ia32_bextr_u32", I
 BDESC (OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_64BIT, CODE_FOR_bmi_bextr_di, "__builtin_ia32_bextr_u64", IX86_BUILTIN_BEXTR64, UNKNOWN, (int) UINT64_FTYPE_UINT64_UINT64)
 
 BDESC (OPTION_MASK_ISA_BMI, CODE_FOR_bmi_tzcnt_hi, "__builtin_ia32_tzcnt_u16", IX86_BUILTIN_TZCNT16, UNKNOWN, (int) UINT16_FTYPE_UINT16)
+/* Same as above, for backward compatibility.  */
+BDESC (OPTION_MASK_ISA_BMI, CODE_FOR_bmi_tzcnt_hi, "__builtin_ctzs", IX86_BUILTIN_CTZS, UNKNOWN, (int) UINT16_FTYPE_UINT16)
 BDESC (OPTION_MASK_ISA_BMI, CODE_FOR_bmi_tzcnt_si, "__builtin_ia32_tzcnt_u32", IX86_BUILTIN_TZCNT32, UNKNOWN, (int) UINT_FTYPE_UINT)
 BDESC (OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_64BIT, CODE_FOR_bmi_tzcnt_di, "__builtin_ia32_tzcnt_u64", IX86_BUILTIN_TZCNT64, UNKNOWN, (int) UINT64_FTYPE_UINT64)
 
index 8fca3692a311f78446cdcae382a5f02c82ce7052..3d9d485ad19e2b242dba8959350fbd581adf6016 100644 (file)
@@ -33573,6 +33573,7 @@ ix86_fold_builtin (tree fndecl, int n_args,
          }
 
        case IX86_BUILTIN_TZCNT16:
+       case IX86_BUILTIN_CTZS:
        case IX86_BUILTIN_TZCNT32:
        case IX86_BUILTIN_TZCNT64:
          gcc_assert (n_args == 1);
@@ -33580,7 +33581,8 @@ ix86_fold_builtin (tree fndecl, int n_args,
            {
              tree type = TREE_TYPE (TREE_TYPE (fndecl));
              tree arg = args[0];
-             if (fn_code == IX86_BUILTIN_TZCNT16)
+             if (fn_code == IX86_BUILTIN_TZCNT16
+                 || fn_code == IX86_BUILTIN_CTZS)
                arg = fold_convert (short_unsigned_type_node, arg);
              if (integer_zerop (arg))
                return build_int_cst (type, TYPE_PRECISION (TREE_TYPE (arg)));
@@ -33590,6 +33592,7 @@ ix86_fold_builtin (tree fndecl, int n_args,
          break;
 
        case IX86_BUILTIN_LZCNT16:
+       case IX86_BUILTIN_CLZS:
        case IX86_BUILTIN_LZCNT32:
        case IX86_BUILTIN_LZCNT64:
          gcc_assert (n_args == 1);
@@ -33597,7 +33600,8 @@ ix86_fold_builtin (tree fndecl, int n_args,
            {
              tree type = TREE_TYPE (TREE_TYPE (fndecl));
              tree arg = args[0];
-             if (fn_code == IX86_BUILTIN_LZCNT16)
+             if (fn_code == IX86_BUILTIN_LZCNT16
+                 || fn_code == IX86_BUILTIN_CLZS)
                arg = fold_convert (short_unsigned_type_node, arg);
              if (integer_zerop (arg))
                return build_int_cst (type, TYPE_PRECISION (TREE_TYPE (arg)));
index f2248a5da952c7b4754a4d3be4af4213a3ba11a5..30d049544111275fd0f7f11a308cb7e4725c4067 100644 (file)
            (match_operand:SWI48 1 "nonimmediate_operand")))
      (clobber (reg:CC FLAGS_REG))])])
 
+(define_insn_and_split "*ctzhi2"
+  [(set (match_operand:SI 0 "register_operand")
+       (ctz:SI
+         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_BMI
+   && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(const_int 0)]
+{
+  rtx tmp = gen_reg_rtx (HImode);
+
+  emit_insn (gen_bmi_tzcnt_hi (tmp, operands[1]));
+  emit_insn (gen_zero_extendhisi2 (operands[0], tmp));
+  DONE;
+})
+
 ; False dependency happens when destination is only updated by tzcnt,
 ; lzcnt or popcnt.  There is no false dependency when destination is
 ; also used in source.
      (clobber (reg:CC FLAGS_REG))])]
   "TARGET_LZCNT")
 
+(define_insn_and_split "*clzhi2"
+  [(set (match_operand:SI 0 "register_operand")
+       (clz:SI
+         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_LZCNT
+   && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(const_int 0)]
+{
+  rtx tmp = gen_reg_rtx (HImode);
+
+  emit_insn (gen_lzcnt_hi (tmp, operands[1]));
+  emit_insn (gen_zero_extendhisi2 (operands[0], tmp));
+  DONE;
+})
+
+; False dependency happens when destination is only updated by tzcnt,
+; lzcnt or popcnt.  There is no false dependency when destination is
+; also used in source.
 (define_insn_and_split "*clz<mode>2_lzcnt_falsedep_1"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
        (clz:SWI48
index c754831e75af78caf6386d81bda96908e7278822..7875060bcb76f403cde020b781096225c21fae4a 100644 (file)
@@ -1,3 +1,9 @@
+2016-12-14  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/59874
+       * gcc.target/i386/pr59874-1.c: New test.
+       * gcc.target/i386/pr59874-2.c: Ditto.
+
 2016-12-14  David Edelsohn  <dje.gcc@gmail.com>
 
        * gcc.dg/torture/pr78515.c: Add -Wno-psabi for AIX.
diff --git a/gcc/testsuite/gcc.target/i386/pr59874-1.c b/gcc/testsuite/gcc.target/i386/pr59874-1.c
new file mode 100644 (file)
index 0000000..e6a8a06
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR target/59874 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -masm=att" } */
+/* { dg-final { scan-assembler "tzcntw" } } */
+
+unsigned int
+foo (unsigned short x)
+{
+  return x ? __builtin_ctz (x) : 16U;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59874-2.c b/gcc/testsuite/gcc.target/i386/pr59874-2.c
new file mode 100644 (file)
index 0000000..710aa7a
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR target/59874 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlzcnt -masm=att" } */
+/* { dg-final { scan-assembler "lzcntw" } } */
+
+unsigned int
+foo (unsigned short x)
+{
+  return x ? __builtin_clz (x) : 16U;
+}