aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2016-12-14 21:27:06 +0100
committerUros Bizjak <uros@gcc.gnu.org>2016-12-14 21:27:06 +0100
commitcc99421ec4b3b94aa328175635782f6f5c36f9e9 (patch)
tree9040d890f5c23059afba6984baea15264e0c7ee0 /gcc
parentd3cab14ab383a8b52fec55c8fd4621865205c693 (diff)
downloadgcc-cc99421ec4b3b94aa328175635782f6f5c36f9e9.zip
gcc-cc99421ec4b3b94aa328175635782f6f5c36f9e9.tar.gz
gcc-cc99421ec4b3b94aa328175635782f6f5c36f9e9.tar.bz2
re PR target/59874 (Missing builtin (__builtin_clzs) when compiling with g++)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386-builtin.def4
-rw-r--r--gcc/config/i386/i386.c8
-rw-r--r--gcc/config/i386/i386.md39
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59874-1.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59874-2.c10
7 files changed, 83 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 259389e..1fbc872 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 83a5089..498207a 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -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)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8fca369..3d9d485 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)));
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index f2248a5d..30d0495 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12606,6 +12606,24 @@
(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.
@@ -12768,6 +12786,27 @@
(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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c754831..7875060 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..e6a8a06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59874-1.c
@@ -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
index 0000000..710aa7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59874-2.c
@@ -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;
+}