From 5fcafa6051863dbabf1d9798ec45b83df942509d Mon Sep 17 00:00:00 2001 From: Kirill Yukhin Date: Mon, 1 Aug 2011 13:47:31 +0000 Subject: [PATCH] Add -mlzcnt. gcc/ 2011-08-01 Kirill Yukhin PR target/49547 * config.gcc (i[34567]86-*-*): Replace abmintrin.h with lzcntintrin.h. (x86_64-*-*): Likewise. * config/i386/i386.opt (mlzcnt): New. * config/i386/abmintrin.h: File removed. (__lzcnt_u16, __lzcnt, __lzcnt_u64): Moved to ... * config/i386/lzcntintrin.h: ... here. New file. (__lzcnt): Rename to ... (__lzcnt32): ... this. * config/i386/bmiintrin.h (head): Update copyright year. (__lzcnt_u16): Removed. (__lzcnt_u32): Likewise. (__lzcnt_u64): Likewise. * config/i386/x86intrin.h: Include lzcntintrin.h when __LZCNT__ is defined, remove abmintrin.h. * config/i386/cpuid.h (bit_LZCNT): New. * config/i386/driver-i386.c (host_detect_local_cpu): Detect LZCNT feature. * config/i386/i386-c.c (ix86_target_macros_internal): Define __LZCNT__ if needed. * config/i386/i386.c (ix86_target_string): New option -mlzcnt. (ix86_option_override_internal): Handle LZCNT option. (ix86_valid_target_attribute_inner_p): Likewise. (struct builtin_description bdesc_args) : Update. * config/i386/i386.h (TARGET_LZCNT): New. (CLZ_DEFINED_VALUE_AT_ZERO): Update. * config/i386/i386.md (clz2): Update insn constraint. (clz2_lzcnt): Likewise. * doc/invoke.texi: Mention -mlzcnt option. * doc/extend.texi: Likewise. gcc/testsuite/ 2011-08-01 Kirill Yukhin * gcc.target/i386/i386.exp (check_effective_target_lzcnt): New. * gcc.target/i386/lzcnt-1.c: New test. * gcc.target/i386/lzcnt-2.c: Likewise. * gcc.target/i386/lzcnt-2a.c: Likewise. * gcc.target/i386/lzcnt-3.c: Likewise. * gcc.target/i386/lzcnt-4.c: Likewise. * gcc.target/i386/lzcnt-4a.c: Likewise. * gcc.target/i386/lzcnt-5.c: Likewise. * gcc.target/i386/lzcnt-6.c: Likewise. * gcc.target/i386/lzcnt-6a.c: Likewise. * gcc.target/i386/lzcnt-check.h: Likewise. * gcc.target/i386/sse-12.c (dg-compile): Add -mlzcnt. * gcc.target/i386/sse-13.c: Likewise. * gcc.target/i386/sse-14.c: Likewise. * g++.dg/other/i386-2.C: Likewise. * g++.dg/other/i386-3.C: Likewise. From-SVN: r177034 --- gcc/ChangeLog | 34 +++++++++++++++++ gcc/config.gcc | 4 +- gcc/config/i386/bmiintrin.h | 20 +--------- gcc/config/i386/cpuid.h | 1 + gcc/config/i386/driver-i386.c | 6 ++- gcc/config/i386/i386-c.c | 2 + gcc/config/i386/i386.c | 14 ++++++- gcc/config/i386/i386.h | 3 +- gcc/config/i386/i386.md | 8 ++-- gcc/config/i386/i386.opt | 4 ++ .../i386/{abmintrin.h => lzcntintrin.h} | 16 ++++---- gcc/config/i386/x86intrin.h | 8 ++-- gcc/doc/extend.texi | 5 +++ gcc/doc/invoke.texi | 8 ++-- gcc/testsuite/ChangeLog | 20 ++++++++++ gcc/testsuite/g++.dg/other/i386-2.C | 2 +- gcc/testsuite/g++.dg/other/i386-3.C | 2 +- gcc/testsuite/gcc.target/i386/i386.exp | 10 +++++ gcc/testsuite/gcc.target/i386/lzcnt-1.c | 11 ++++++ gcc/testsuite/gcc.target/i386/lzcnt-2.c | 35 ++++++++++++++++++ gcc/testsuite/gcc.target/i386/lzcnt-2a.c | 6 +++ gcc/testsuite/gcc.target/i386/lzcnt-3.c | 11 ++++++ gcc/testsuite/gcc.target/i386/lzcnt-4.c | 35 ++++++++++++++++++ gcc/testsuite/gcc.target/i386/lzcnt-4a.c | 6 +++ gcc/testsuite/gcc.target/i386/lzcnt-5.c | 11 ++++++ gcc/testsuite/gcc.target/i386/lzcnt-6.c | 35 ++++++++++++++++++ gcc/testsuite/gcc.target/i386/lzcnt-6a.c | 6 +++ gcc/testsuite/gcc.target/i386/lzcnt-check.h | 37 +++++++++++++++++++ gcc/testsuite/gcc.target/i386/sse-12.c | 2 +- gcc/testsuite/gcc.target/i386/sse-13.c | 2 +- gcc/testsuite/gcc.target/i386/sse-14.c | 2 +- 31 files changed, 316 insertions(+), 50 deletions(-) rename gcc/config/i386/{abmintrin.h => lzcntintrin.h} (83%) create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-1.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-2.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-3.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-4.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-4a.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-5.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-6.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-6a.c create mode 100644 gcc/testsuite/gcc.target/i386/lzcnt-check.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3880f963224..b516175b567 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2011-08-01 Kirill Yukhin + + PR target/49547 + * config.gcc (i[34567]86-*-*): Replace abmintrin.h with + lzcntintrin.h. + (x86_64-*-*): Likewise. + * config/i386/i386.opt (mlzcnt): New. + * config/i386/abmintrin.h: File removed. + (__lzcnt_u16, __lzcnt, __lzcnt_u64): Moved to ... + * config/i386/lzcntintrin.h: ... here. New file. + (__lzcnt): Rename to ... + (__lzcnt32): ... this. + * config/i386/bmiintrin.h (head): Update copyright year. + (__lzcnt_u16): Removed. + (__lzcnt_u32): Likewise. + (__lzcnt_u64): Likewise. + * config/i386/x86intrin.h: Include lzcntintrin.h when __LZCNT__ + is defined, remove abmintrin.h. + * config/i386/cpuid.h (bit_LZCNT): New. + * config/i386/driver-i386.c (host_detect_local_cpu): Detect + LZCNT feature. + * config/i386/i386-c.c (ix86_target_macros_internal): Define + __LZCNT__ if needed. + * config/i386/i386.c (ix86_target_string): New option -mlzcnt. + (ix86_option_override_internal): Handle LZCNT option. + (ix86_valid_target_attribute_inner_p): Likewise. + (struct builtin_description bdesc_args) : Update. + * config/i386/i386.h (TARGET_LZCNT): New. + (CLZ_DEFINED_VALUE_AT_ZERO): Update. + * config/i386/i386.md (clz2): Update insn constraint. + (clz2_lzcnt): Likewise. + * doc/invoke.texi: Mention -mlzcnt option. + * doc/extend.texi: Likewise. + 2011-08-01 Julian Brown * configure.ac (fixed-point): Add ARM support. diff --git a/gcc/config.gcc b/gcc/config.gcc index 02cc556ccca..94f15d8706d 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -352,7 +352,7 @@ i[34567]86-*-*) nmmintrin.h bmmintrin.h fma4intrin.h wmmintrin.h immintrin.h x86intrin.h avxintrin.h xopintrin.h ia32intrin.h cross-stdarg.h lwpintrin.h popcntintrin.h - abmintrin.h bmiintrin.h tbmintrin.h" + lzcntintrin.h bmiintrin.h tbmintrin.h" ;; x86_64-*-*) cpu_type=i386 @@ -364,7 +364,7 @@ x86_64-*-*) nmmintrin.h bmmintrin.h fma4intrin.h wmmintrin.h immintrin.h x86intrin.h avxintrin.h xopintrin.h ia32intrin.h cross-stdarg.h lwpintrin.h popcntintrin.h - abmintrin.h bmiintrin.h tbmintrin.h" + lzcntintrin.h bmiintrin.h tbmintrin.h" need_64bit_hwint=yes ;; ia64-*-*) diff --git a/gcc/config/i386/bmiintrin.h b/gcc/config/i386/bmiintrin.h index 225f2ecbe23..1699c61d24e 100644 --- a/gcc/config/i386/bmiintrin.h +++ b/gcc/config/i386/bmiintrin.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Free Software Foundation, Inc. +/* Copyright (C) 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -32,12 +32,6 @@ #ifndef _BMIINTRIN_H_INCLUDED #define _BMIINTRIN_H_INCLUDED -extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -__lzcnt_u16 (unsigned short __X) -{ - return __builtin_clzs (__X); -} - extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __tzcnt_u16 (unsigned short __X) { @@ -79,12 +73,6 @@ __blsr_u32 (unsigned int __X) return tmp; } -extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -__lzcnt_u32 (unsigned int __X) -{ - return __builtin_clz (__X); -} - extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __tzcnt_u32 (unsigned int __X) @@ -128,12 +116,6 @@ __blsr_u64 (unsigned long long __X) return tmp; } -extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -__lzcnt_u64 (unsigned long long __X) -{ - return __builtin_clzll (__X); -} - extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __tzcnt_u64 (unsigned long long __X) { diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h index 3c3f47b0030..8826c2829ff 100644 --- a/gcc/config/i386/cpuid.h +++ b/gcc/config/i386/cpuid.h @@ -24,6 +24,7 @@ /* %ecx */ #define bit_SSE3 (1 << 0) #define bit_PCLMUL (1 << 1) +#define bit_LZCNT (1 << 5) #define bit_SSSE3 (1 << 9) #define bit_FMA (1 << 12) #define bit_CMPXCHG16B (1 << 13) diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c index ecd8958df23..5823987863f 100644 --- a/gcc/config/i386/driver-i386.c +++ b/gcc/config/i386/driver-i386.c @@ -396,7 +396,7 @@ const char *host_detect_local_cpu (int argc, const char **argv) unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0; unsigned int has_pclmul = 0, has_abm = 0, has_lwp = 0; unsigned int has_fma = 0, has_fma4 = 0, has_xop = 0; - unsigned int has_bmi = 0, has_tbm = 0; + unsigned int has_bmi = 0, has_tbm = 0, has_lzcnt = 0; bool arch; @@ -465,6 +465,7 @@ const char *host_detect_local_cpu (int argc, const char **argv) has_fma4 = ecx & bit_FMA4; has_xop = ecx & bit_XOP; has_tbm = ecx & bit_TBM; + has_lzcnt = ecx & bit_LZCNT; has_longmode = edx & bit_LM; has_3dnowp = edx & bit_3DNOWP; @@ -717,10 +718,11 @@ const char *host_detect_local_cpu (int argc, const char **argv) const char *avx = has_avx ? " -mavx" : " -mno-avx"; const char *sse4_2 = has_sse4_2 ? " -msse4.2" : " -mno-sse4.2"; const char *sse4_1 = has_sse4_1 ? " -msse4.1" : " -mno-sse4.1"; + const char *lzcnt = has_lzcnt ? " -mlzcnt" : " -mnolzcnt"; options = concat (options, cx16, sahf, movbe, ase, pclmul, popcnt, abm, lwp, fma, fma4, xop, bmi, tbm, - avx, sse4_2, sse4_1, NULL); + avx, sse4_2, sse4_1, lzcnt, NULL); } done: diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index 5cbcfd51c68..1fc333c7e17 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -271,6 +271,8 @@ ix86_target_macros_internal (int isa_flag, def_or_undef (parse_in, "__ABM__"); if (isa_flag & OPTION_MASK_ISA_BMI) def_or_undef (parse_in, "__BMI__"); + if (isa_flag & OPTION_MASK_ISA_LZCNT) + def_or_undef (parse_in, "__LZCNT__"); if (isa_flag & OPTION_MASK_ISA_TBM) def_or_undef (parse_in, "__TBM__"); if (isa_flag & OPTION_MASK_ISA_POPCNT) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ebb6f250d57..c8ea48f7cd8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2663,6 +2663,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune, { "-mmmx", OPTION_MASK_ISA_MMX }, { "-mabm", OPTION_MASK_ISA_ABM }, { "-mbmi", OPTION_MASK_ISA_BMI }, + { "-mlzcnt", OPTION_MASK_ISA_LZCNT }, { "-mtbm", OPTION_MASK_ISA_TBM }, { "-mpopcnt", OPTION_MASK_ISA_POPCNT }, { "-mmovbe", OPTION_MASK_ISA_MOVBE }, @@ -2917,7 +2918,8 @@ ix86_option_override_internal (bool main_args_p) PTA_RDRND = 1 << 25, PTA_F16C = 1 << 26, PTA_BMI = 1 << 27, - PTA_TBM = 1 << 28 + PTA_TBM = 1 << 28, + PTA_LZCNT = 1 << 29 /* if this reaches 32, need to widen struct pta flags below */ }; @@ -3278,6 +3280,9 @@ ix86_option_override_internal (bool main_args_p) if (processor_alias_table[i].flags & PTA_BMI && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI)) ix86_isa_flags |= OPTION_MASK_ISA_BMI; + if (processor_alias_table[i].flags & (PTA_LZCNT | PTA_ABM) + && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LZCNT)) + ix86_isa_flags |= OPTION_MASK_ISA_LZCNT; if (processor_alias_table[i].flags & PTA_TBM && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM)) ix86_isa_flags |= OPTION_MASK_ISA_TBM; @@ -3525,6 +3530,10 @@ ix86_option_override_internal (bool main_args_p) if (TARGET_SSE4_2 || TARGET_ABM) ix86_isa_flags |= OPTION_MASK_ISA_POPCNT & ~ix86_isa_flags_explicit; + /* Turn on lzcnt instruction for -mabm. */ + if (TARGET_ABM) + ix86_isa_flags |= OPTION_MASK_ISA_LZCNT & ~ix86_isa_flags_explicit; + /* Validate -mpreferred-stack-boundary= value or default it to PREFERRED_STACK_BOUNDARY_DEFAULT. */ ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT; @@ -4030,6 +4039,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[], IX86_ATTR_ISA ("3dnow", OPT_m3dnow), IX86_ATTR_ISA ("abm", OPT_mabm), IX86_ATTR_ISA ("bmi", OPT_mbmi), + IX86_ATTR_ISA ("lzcnt", OPT_mlzcnt), IX86_ATTR_ISA ("tbm", OPT_mtbm), IX86_ATTR_ISA ("aes", OPT_maes), IX86_ATTR_ISA ("avx", OPT_mavx), @@ -24935,7 +24945,7 @@ static const struct builtin_description bdesc_args[] = { OPTION_MASK_ISA_AVX, CODE_FOR_copysignv8sf3, "__builtin_ia32_copysignps256", IX86_BUILTIN_CPYSGNPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF }, { OPTION_MASK_ISA_AVX, CODE_FOR_copysignv4df3, "__builtin_ia32_copysignpd256", IX86_BUILTIN_CPYSGNPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF }, - { OPTION_MASK_ISA_ABM, CODE_FOR_clzhi2_abm, "__builtin_clzs", IX86_BUILTIN_CLZS, UNKNOWN, (int) UINT16_FTYPE_UINT16 }, + { OPTION_MASK_ISA_LZCNT, CODE_FOR_clzhi2_lzcnt, "__builtin_clzs", IX86_BUILTIN_CLZS, UNKNOWN, (int) UINT16_FTYPE_UINT16 }, /* BMI */ { OPTION_MASK_ISA_BMI, CODE_FOR_bmi_bextr_si, "__builtin_ia32_bextr_u32", IX86_BUILTIN_BEXTR32, UNKNOWN, (int) UINT_FTYPE_UINT_UINT }, diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 20c9a8fba9a..f43586d012b 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -61,6 +61,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_ROUND OPTION_ISA_ROUND #define TARGET_ABM OPTION_ISA_ABM #define TARGET_BMI OPTION_ISA_BMI +#define TARGET_LZCNT OPTION_ISA_LZCNT #define TARGET_TBM OPTION_ISA_TBM #define TARGET_POPCNT OPTION_ISA_POPCNT #define TARGET_SAHF OPTION_ISA_SAHF @@ -2288,7 +2289,7 @@ extern void debug_dispatch_window (int); #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \ ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI) #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \ - ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI) + ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_LZCNT) /* Flags returned by ix86_get_callcvt (). */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 5dfa43ee427..0c78f92ef3a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -11801,19 +11801,19 @@ (clobber (reg:CC FLAGS_REG))])] "" { - if (TARGET_ABM) + if (TARGET_LZCNT) { - emit_insn (gen_clz2_abm (operands[0], operands[1])); + emit_insn (gen_clz2_lzcnt (operands[0], operands[1])); DONE; } operands[2] = GEN_INT (GET_MODE_BITSIZE (mode)-1); }) -(define_insn "clz2_abm" +(define_insn "clz2_lzcnt" [(set (match_operand:SWI248 0 "register_operand" "=r") (clz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_ABM || TARGET_BMI" + "TARGET_LZCNT" "lzcnt{}\t{%1, %0|%0, %1}" [(set_attr "prefix_rep" "1") (set_attr "type" "bitmanip") diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 5e6b5df4c74..f197dd8506f 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -489,6 +489,10 @@ mbmi Target Report Mask(ISA_BMI) Var(ix86_isa_flags) Save Support BMI built-in functions and code generation +mlzcnt +Target Report Mask(ISA_LZCNT) Var(ix86_isa_flags) Save +Support LZCNT built-in function and code generation + mtbm Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save Support TBM built-in functions and code generation diff --git a/gcc/config/i386/abmintrin.h b/gcc/config/i386/lzcntintrin.h similarity index 83% rename from gcc/config/i386/abmintrin.h rename to gcc/config/i386/lzcntintrin.h index 9d87f574586..43008111576 100644 --- a/gcc/config/i386/abmintrin.h +++ b/gcc/config/i386/lzcntintrin.h @@ -22,15 +22,15 @@ . */ #ifndef _X86INTRIN_H_INCLUDED -# error "Never use directly; include instead." +# error "Never use directly; include instead." #endif -#ifndef __ABM__ -# error "ABM instruction set not enabled" -#endif /* __ABM__ */ +#ifndef __LZCNT__ +# error "LZCNT instruction is not enabled" +#endif /* __LZCNT__ */ -#ifndef _ABMINTRIN_H_INCLUDED -#define _ABMINTRIN_H_INCLUDED +#ifndef _LZCNTINTRIN_H_INCLUDED +#define _LZCNTINTRIN_H_INCLUDED extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __lzcnt16 (unsigned short __X) @@ -39,7 +39,7 @@ __lzcnt16 (unsigned short __X) } extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) -__lzcnt (unsigned int __X) +__lzcnt32 (unsigned int __X) { return __builtin_clz (__X); } @@ -52,4 +52,4 @@ __lzcnt64 (unsigned long __X) } #endif -#endif /* _ABMINTRIN_H_INCLUDED */ +#endif /* _LZCNTINTRIN_H_INCLUDED */ diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h index 36b43df8760..88456f9e9ef 100644 --- a/gcc/config/i386/x86intrin.h +++ b/gcc/config/i386/x86intrin.h @@ -77,10 +77,6 @@ #include #endif -#ifdef __ABM__ -#include -#endif - #ifdef __BMI__ #include #endif @@ -89,6 +85,10 @@ #include #endif +#ifdef __LZCNT__ +#include +#endif + #ifdef __POPCNT__ #include #endif diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 0c95a795861..480a8b0288e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9676,6 +9676,11 @@ All of them generate the machine instruction that is part of the name. @smallexample unsigned int __builtin_ia32_bextr_u32(unsigned int, unsigned int); unsigned long long __builtin_ia32_bextr_u64 (unsigned long long, unsigned long long); +@end smallexample + +The following built-in functions are available when @option{-mlzcnt} is used. +All of them generate the machine instruction that is part of the name. +@smallexample unsigned short __builtin_ia32_lzcnt_16(unsigned short); unsigned int __builtin_ia32_lzcnt_u32(unsigned int); unsigned long long __builtin_ia32_lzcnt_u64 (unsigned long long); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index db9a5da5051..264d1b0f350 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -606,8 +606,8 @@ Objective-C and Objective-C++ Dialects}. -mcld -mcx16 -msahf -mmovbe -mcrc32 -mrecip -mvzeroupper @gol -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol --msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlwp @gol --mthreads -mno-align-stringops -minline-all-stringops @gol +-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol +-mlwp -mthreads -mno-align-stringops -minline-all-stringops @gol -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol -mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol -m96bit-long-double -mregparm=@var{num} -msseregparm @gol @@ -12692,6 +12692,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -mno-abm @itemx -mbmi @itemx -mno-bmi +@itemx -mlzcnt +@itemx -mno-lzcnt @itemx -mtbm @itemx -mno-tbm @opindex mmmx @@ -12702,7 +12704,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @opindex mno-3dnow These switches enable or disable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, -SSE4A, FMA4, XOP, LWP, ABM, BMI, or 3DNow!@: extended instruction sets. +SSE4A, FMA4, XOP, LWP, ABM, BMI, LZCNT or 3DNow!@: extended instruction sets. These extensions are also available as built-in functions: see @ref{X86 Built-in Functions}, for details of the functions enabled and disabled by these switches. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f5685bfc518..480eea6ac1c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2011-08-01 Kirill Yukhin + + * gcc.target/i386/i386.exp (check_effective_target_lzcnt): New. + * gcc.target/i386/lzcnt-1.c: New test. + * gcc.target/i386/lzcnt-2.c: Likewise. + * gcc.target/i386/lzcnt-2a.c: Likewise. + * gcc.target/i386/lzcnt-3.c: Likewise. + * gcc.target/i386/lzcnt-4.c: Likewise. + * gcc.target/i386/lzcnt-4a.c: Likewise. + * gcc.target/i386/lzcnt-5.c: Likewise. + * gcc.target/i386/lzcnt-6.c: Likewise. + * gcc.target/i386/lzcnt-6a.c: Likewise. + * gcc.target/i386/lzcnt-check.h: Likewise. + + * gcc.target/i386/sse-12.c (dg-compile): Add -mlzcnt. + * gcc.target/i386/sse-13.c: Likewise. + * gcc.target/i386/sse-14.c: Likewise. + * g++.dg/other/i386-2.C: Likewise. + * g++.dg/other/i386-3.C: Likewise. + 2011-08-01 Julian Brown * gcc.target/arm/fixed-point-exec.c: New test. diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C index 1a445f1b52e..ed183c7633d 100644 --- a/gcc/testsuite/g++.dg/other/i386-2.C +++ b/gcc/testsuite/g++.dg/other/i386-2.C @@ -1,5 +1,5 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ -/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ +/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h, diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C index 66eec1422ae..626f972463a 100644 --- a/gcc/testsuite/g++.dg/other/i386-3.C +++ b/gcc/testsuite/g++.dg/other/i386-3.C @@ -1,5 +1,5 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ -/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ +/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h, diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp index 13d8cffca4f..167b79b5d2a 100644 --- a/gcc/testsuite/gcc.target/i386/i386.exp +++ b/gcc/testsuite/gcc.target/i386/i386.exp @@ -186,6 +186,16 @@ proc check_effective_target_xop { } { } "-O2 -mxop" ] } +# Return 1 if lzcnt instruction can be compiled. +proc check_effective_target_lzcnt { } { + return [check_no_compiler_messages lzcnt object { + unsigned short _lzcnt (unsigned short __X) + { + return __builtin_clzs (__X); + } + } "-mlzcnt" ] +} + # Return 1 if bmi instructions can be compiled. proc check_effective_target_bmi { } { return [check_no_compiler_messages bmi object { diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-1.c b/gcc/testsuite/gcc.target/i386/lzcnt-1.c new file mode 100644 index 00000000000..f6240d1ba78 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlzcnt " } */ +/* { dg-final { scan-assembler "lzcntw\[^\\n]*(%|)ax" } } */ + +#include + +unsigned int +func_lzcnt16 (unsigned int X) +{ + return __lzcnt16(X); +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-2.c b/gcc/testsuite/gcc.target/i386/lzcnt-2.c new file mode 100644 index 00000000000..329a11f9753 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-2.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { lzcnt } } } */ +/* { dg-options "-O2 -mlzcnt -fno-inline" } */ + +#include + +#include "lzcnt-check.h" + +short calc_lzcnt_u16 (short src) +{ + int i; + short res = 0; + + while ((res < 16) && (((src >> (15 - res)) & 1) == 0)) + ++res; + + return res; +} + +static void +lzcnt_test () +{ + unsigned i; + short src = 0x7ace; + short res, res_ref; + + for (i=0; i<5; ++i) { + src = src >> i; + + res_ref = calc_lzcnt_u16 (src); + res = __lzcnt16 (src); + + if (res != res_ref) + abort(); + } +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-2a.c b/gcc/testsuite/gcc.target/i386/lzcnt-2a.c new file mode 100644 index 00000000000..fe1069feea4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-2a.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlzcnt" } */ + +#include "lzcnt-2.c" + +/* { dg-final { scan-assembler "lzcntw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-3.c b/gcc/testsuite/gcc.target/i386/lzcnt-3.c new file mode 100644 index 00000000000..1477951174a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -mlzcnt " } */ +/* { dg-final { scan-assembler "lzcntl\[^\\n]*(%|)eax" } } */ + +#include + +unsigned int +func_lzcnt32 (unsigned int X) +{ + return __lzcnt32(X); +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-4.c b/gcc/testsuite/gcc.target/i386/lzcnt-4.c new file mode 100644 index 00000000000..20653265bf4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-4.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { lzcnt } } } */ +/* { dg-options "-O2 -mlzcnt -fno-inline" } */ + +#include + +#include "lzcnt-check.h" + +int calc_lzcnt_u32 (int src) +{ + int i; + int res = 0; + + while ((res < 32) && (((src >> (31 - res)) & 1) == 0)) + ++res; + + return res; +} + +static void +lzcnt_test () +{ + unsigned i; + int src = 0xce7ace0; + int res, res_ref; + + for (i=0; i<5; ++i) { + src = src >> i; + + res_ref = calc_lzcnt_u32 (src); + res = __lzcnt32 (src); + + if (res != res_ref) + abort(); + } +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-4a.c b/gcc/testsuite/gcc.target/i386/lzcnt-4a.c new file mode 100644 index 00000000000..6bba6a97df3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-4a.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlzcnt" } */ + +#include "lzcnt-4.c" + +/* { dg-final { scan-assembler "lzcntl" } } */ diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-5.c b/gcc/testsuite/gcc.target/i386/lzcnt-5.c new file mode 100644 index 00000000000..a4b9aafcd3d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mlzcnt" } */ +/* { dg-final { scan-assembler "lzcntq\[^\\n]*(%|)rax" } } */ + +#include + +unsigned int +func_lzcnt64 (unsigned long long X) +{ + return __lzcnt64(X); +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-6.c b/gcc/testsuite/gcc.target/i386/lzcnt-6.c new file mode 100644 index 00000000000..f0bf5dab044 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-6.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { lzcnt && { ! ia32 } } } } */ +/* { dg-options "-O2 -mlzcnt -fno-inline" } */ + +#include + +#include "lzcnt-check.h" + +long long calc_lzcnt_u64 (long long src) +{ + int i; + int res = 0; + + while ((res < 64) && (((src >> (63 - res)) & 1) == 0)) + ++res; + + return res; +} + +static void +lzcnt_test () +{ + unsigned i; + long long src = 0xce7ace0ce7ace0; + long long res, res_ref; + + for (i=0; i<5; ++i) { + src = src >> i; + + res_ref = calc_lzcnt_u64 (src); + res = __lzcnt64 (src); + + if (res != res_ref) + abort(); + } +} diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-6a.c b/gcc/testsuite/gcc.target/i386/lzcnt-6a.c new file mode 100644 index 00000000000..209009344b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-6a.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mlzcnt" } */ + +#include "lzcnt-6.c" + +/* { dg-final { scan-assembler "lzcntq" } } */ diff --git a/gcc/testsuite/gcc.target/i386/lzcnt-check.h b/gcc/testsuite/gcc.target/i386/lzcnt-check.h new file mode 100644 index 00000000000..8aad834d6af --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/lzcnt-check.h @@ -0,0 +1,37 @@ +#include +#include + +#include "cpuid.h" + +static void lzcnt_test (void); + +static void +__attribute__ ((noinline)) +do_test (void) +{ + lzcnt_test (); +} + +int +main () +{ + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (0x80000001, &eax, &ebx, &ecx, &edx)) + return 0; + + /* Run LZCNT test only if host has LZCNT support. */ + if (ecx & bit_LZCNT) + { + do_test (); +#ifdef DEBUG + printf ("PASSED\n"); +#endif + } +#ifdef DEBUG + else + printf ("SKIPPED\n"); +#endif + + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c index 4f8aaec6d3a..59e659ebec1 100644 --- a/gcc/testsuite/gcc.target/i386/sse-12.c +++ b/gcc/testsuite/gcc.target/i386/sse-12.c @@ -3,7 +3,7 @@ popcntintrin.h and mm_malloc.h are usable with -O -std=c89 -pedantic-errors. */ /* { dg-do compile } */ -/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ +/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ #include diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c index 188b2e6dc08..836272d7e62 100644 --- a/gcc/testsuite/gcc.target/i386/sse-13.c +++ b/gcc/testsuite/gcc.target/i386/sse-13.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ +/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ #include diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c index 22ea61f68b4..af42781e2a2 100644 --- a/gcc/testsuite/gcc.target/i386/sse-14.c +++ b/gcc/testsuite/gcc.target/i386/sse-14.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ +/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */ #include