From cc99421ec4b3b94aa328175635782f6f5c36f9e9 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 14 Dec 2016 21:27:06 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 8 +++++ gcc/config/i386/i386-builtin.def | 4 +++ gcc/config/i386/i386.c | 8 +++-- gcc/config/i386/i386.md | 39 +++++++++++++++++++++++ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.target/i386/pr59874-1.c | 10 ++++++ gcc/testsuite/gcc.target/i386/pr59874-2.c | 10 ++++++ 7 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr59874-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr59874-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 259389ee69e..1fbc8727a52 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-12-14 Uros Bizjak + + 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 PR debug/77844 diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index 83a508909ba..498207a9a53 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 8fca3692a31..3d9d485ad19 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 f2248a5da95..30d04954411 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 "*clz2_lzcnt_falsedep_1" [(set (match_operand:SWI48 0 "register_operand" "=r") (clz:SWI48 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c754831e75a..7875060bcb7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-12-14 Uros Bizjak + + PR target/59874 + * gcc.target/i386/pr59874-1.c: New test. + * gcc.target/i386/pr59874-2.c: Ditto. + 2016-12-14 David Edelsohn * 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 00000000000..e6a8a06dd52 --- /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 00000000000..710aa7a482c --- /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; +} -- 2.30.2