summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/bmiintrin.h145
-rw-r--r--gcc/config/i386/cpuid.h1
-rw-r--r--gcc/config/i386/driver-i386.c7
-rw-r--r--gcc/config/i386/i386-c.c2
-rw-r--r--gcc/config/i386/i386.c35
-rw-r--r--gcc/config/i386/i386.h9
-rw-r--r--gcc/config/i386/i386.md79
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/x86intrin.h4
9 files changed, 281 insertions, 5 deletions
diff --git a/gcc/config/i386/bmiintrin.h b/gcc/config/i386/bmiintrin.h
new file mode 100644
index 00000000000..d3b3bbdf4b5
--- /dev/null
+++ b/gcc/config/i386/bmiintrin.h
@@ -0,0 +1,145 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _X86INTRIN_H_INCLUDED
+# error "Never use <bmiintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __BMI__
+# error "BMI instruction set not enabled"
+#endif /* __BMI__ */
+
+#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_ia32_lzcnt_u16 (__X);
+}
+
+extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__tzcnt_u16 (unsigned short __X)
+{
+ return __builtin_ctzs(__X);
+}
+
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__andn_u32 (unsigned int __X, unsigned int __Y)
+{
+ unsigned int tmp = ~(__X) & (__Y);
+ return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__bextr_u32 (unsigned int __X, unsigned int __Y)
+{
+ return __builtin_ia32_bextr_u32 (__X, __Y);
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsi_u32 (unsigned int __X)
+{
+ unsigned int tmp = (__X) & (-(__X));
+ return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsmsk_u32 (unsigned int __X)
+{
+ unsigned int tmp = (__X) ^ (__X - 1);
+ return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsr_u32 (unsigned int __X)
+{
+ unsigned int tmp = (__X) & (__X - 1);
+ return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lzcnt_u32 (unsigned int __X)
+{
+ return __builtin_ia32_lzcnt_u32 (__X);
+}
+
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__tzcnt_u32 (unsigned int __X)
+{
+ return __builtin_ctz(__X);
+}
+
+
+#ifdef __x86_64__
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__andn_u64 (unsigned long long __X, unsigned long long __Y)
+{
+ unsigned long long tmp = ~(__X) & (__Y);
+ return tmp;
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__bextr_u64 (unsigned long long __X, unsigned long long __Y)
+{
+ return __builtin_ia32_bextr_u64 (__X, __Y);
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsi_u64 (unsigned long long __X)
+{
+ unsigned long long tmp = (__X) & (-(__X));
+ return tmp;
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsmsk_u64 (unsigned long long __X)
+{
+ unsigned long long tmp = (__X) ^ (__X - 1);
+ return tmp;
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsr_u64 (unsigned long long __X)
+{
+ unsigned long long tmp = (__X) & (__X - 1);
+ return tmp;
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__lzcnt_u64 (unsigned long long __X)
+{
+ return __builtin_ia32_lzcnt_u64 (__X);
+}
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__tzcnt_u64 (unsigned long long __X)
+{
+ return __builtin_ctzll(__X);
+}
+
+#endif /* __x86_64__ */
+
+#endif /* _BMIINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 11c2f1e2662..0f1af7f8d0d 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -62,6 +62,7 @@
/* Extended Features (%eax == 7) */
#define bit_FSGSBASE (1 << 0)
+#define bit_BMI (1 << 3)
#if defined(__i386__) && defined(__PIC__)
/* %ebx may be the PIC register. */
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 998214b0bda..6319a14b78a 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -397,6 +397,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_fma4 = 0, has_xop = 0;
+ unsigned int has_bmi = 0;
bool arch;
@@ -467,6 +468,10 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_longmode = edx & bit_LM;
has_3dnowp = edx & bit_3DNOWP;
has_3dnow = edx & bit_3DNOW;
+
+ __cpuid (0x7, eax, ebx, ecx, edx);
+
+ has_bmi = ebx & bit_BMI;
}
if (!arch)
@@ -686,6 +691,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
options = concat (options, " -mfma4", NULL);
if (has_xop)
options = concat (options, " -mxop", NULL);
+ if (has_bmi)
+ options = concat (options, " -mbmi", NULL);
if (has_avx)
options = concat (options, " -mavx", NULL);
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 3b4409e889a..51c0c135ad2 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -253,6 +253,8 @@ ix86_target_macros_internal (int isa_flag,
def_or_undef (parse_in, "__LWP__");
if (isa_flag & OPTION_MASK_ISA_ABM)
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_POPCNT)
def_or_undef (parse_in, "__POPCNT__");
if (isa_flag & OPTION_MASK_ISA_FSGSBASE)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 138fb3fa3e4..3c7dc8c827e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2325,6 +2325,8 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_ABM_SET \
(OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT)
+#define OPTION_MASK_ISA_BMI_SET OPTION_MASK_ISA_BMI
+
#define OPTION_MASK_ISA_POPCNT_SET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_SET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_SET OPTION_MASK_ISA_SAHF
@@ -2379,6 +2381,7 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_AES_UNSET OPTION_MASK_ISA_AES
#define OPTION_MASK_ISA_PCLMUL_UNSET OPTION_MASK_ISA_PCLMUL
#define OPTION_MASK_ISA_ABM_UNSET OPTION_MASK_ISA_ABM
+#define OPTION_MASK_ISA_BMI_UNSET OPTION_MASK_ISA_BMI
#define OPTION_MASK_ISA_POPCNT_UNSET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_UNSET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_UNSET OPTION_MASK_ISA_SAHF
@@ -2681,6 +2684,19 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
}
return true;
+ case OPT_mbmi:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_BMI_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_BMI_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_UNSET;
+ }
+ return true;
+
case OPT_mpopcnt:
if (value)
{
@@ -2849,6 +2865,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
{ "-m3dnowa", OPTION_MASK_ISA_3DNOW_A },
{ "-mmmx", OPTION_MASK_ISA_MMX },
{ "-mabm", OPTION_MASK_ISA_ABM },
+ { "-mbmi", OPTION_MASK_ISA_BMI },
{ "-mpopcnt", OPTION_MASK_ISA_POPCNT },
{ "-mmovbe", OPTION_MASK_ISA_MOVBE },
{ "-mcrc32", OPTION_MASK_ISA_CRC32 },
@@ -3104,7 +3121,9 @@ ix86_option_override_internal (bool main_args_p)
PTA_LWP = 1 << 23,
PTA_FSGSBASE = 1 << 24,
PTA_RDRND = 1 << 25,
- PTA_F16C = 1 << 26
+ PTA_F16C = 1 << 26,
+ PTA_BMI = 1 << 27
+ /* if this reaches 32, need to widen struct pta flags below */
};
static struct pta
@@ -3439,6 +3458,9 @@ ix86_option_override_internal (bool main_args_p)
if (processor_alias_table[i].flags & PTA_ABM
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM))
ix86_isa_flags |= OPTION_MASK_ISA_ABM;
+ 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_CX16
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16))
ix86_isa_flags |= OPTION_MASK_ISA_CX16;
@@ -4276,6 +4298,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
/* isa options */
IX86_ATTR_ISA ("3dnow", OPT_m3dnow),
IX86_ATTR_ISA ("abm", OPT_mabm),
+ IX86_ATTR_ISA ("bmi", OPT_mbmi),
IX86_ATTR_ISA ("aes", OPT_maes),
IX86_ATTR_ISA ("avx", OPT_mavx),
IX86_ATTR_ISA ("mmx", OPT_mmmx),
@@ -24016,6 +24039,11 @@ enum ix86_builtins
IX86_BUILTIN_CLZS,
+ /* BMI instructions. */
+ IX86_BUILTIN_BEXTR32,
+ IX86_BUILTIN_BEXTR64,
+ IX86_BUILTIN_CTZS,
+
/* FSGSBASE instructions. */
IX86_BUILTIN_RDFSBASE32,
IX86_BUILTIN_RDFSBASE64,
@@ -24955,6 +24983,11 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_ABM, CODE_FOR_clzhi2_abm, "__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 },
+ { OPTION_MASK_ISA_BMI, CODE_FOR_bmi_bextr_di, "__builtin_ia32_bextr_u64", IX86_BUILTIN_BEXTR64, UNKNOWN, (int) UINT64_FTYPE_UINT64_UINT64 },
+ { OPTION_MASK_ISA_BMI, CODE_FOR_ctzhi2, "__builtin_ctzs", IX86_BUILTIN_CTZS, UNKNOWN, (int) UINT16_FTYPE_UINT16 },
+
/* F16C */
{ OPTION_MASK_ISA_F16C, CODE_FOR_vcvtph2ps, "__builtin_ia32_vcvtph2ps", IX86_BUILTIN_CVTPH2PS, UNKNOWN, (int) V4SF_FTYPE_V8HI },
{ OPTION_MASK_ISA_F16C, CODE_FOR_vcvtph2ps256, "__builtin_ia32_vcvtph2ps256", IX86_BUILTIN_CVTPH2PS256, UNKNOWN, (int) V8SF_FTYPE_V8HI },
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 0257dbbe4e9..d854797be82 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -59,6 +59,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_LWP OPTION_ISA_LWP
#define TARGET_ROUND OPTION_ISA_ROUND
#define TARGET_ABM OPTION_ISA_ABM
+#define TARGET_BMI OPTION_ISA_BMI
#define TARGET_POPCNT OPTION_ISA_POPCNT
#define TARGET_SAHF OPTION_ISA_SAHF
#define TARGET_MOVBE OPTION_ISA_MOVBE
@@ -2366,6 +2367,14 @@ struct GTY(()) machine_function {
extern void debug_ready_dispatch (void);
extern void debug_dispatch_window (int);
+/* The value at zero is only defined for the BMI instructions
+ LZCNT and TZCNT, not the BSR/BSF insns in the original isa. */
+#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)
+
+
/*
Local variables:
version-control: t
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index eff96a106d4..a4881f5e6fb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -229,6 +229,9 @@
UNSPEC_VTESTP
UNSPEC_VCVTPH2PS
UNSPEC_VCVTPS2PH
+
+ ;; For BMI support
+ UNSPEC_BEXTR
])
(define_c_enum "unspecv" [
@@ -11988,13 +11991,19 @@
(set_attr "mode" "<MODE>")])
(define_insn "ctz<mode>2"
- [(set (match_operand:SWI48 0 "register_operand" "=r")
- (ctz:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (ctz:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
""
- "bsf{<imodesuffix>}\t{%1, %0|%0, %1}"
+{
+ if (TARGET_BMI)
+ return "tzcnt{<imodesuffix>}\t{%1, %0|%0, %1}";
+ else
+ return "bsf{<imodesuffix>}\t{%1, %0|%0, %1}";
+}
[(set_attr "type" "alu1")
(set_attr "prefix_0f" "1")
+ (set (attr "prefix_rep") (symbol_ref "TARGET_BMI"))
(set_attr "mode" "<MODE>")])
(define_expand "clz<mode>2"
@@ -12021,12 +12030,74 @@
[(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_ABM || TARGET_BMI"
"lzcnt{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "prefix_rep" "1")
(set_attr "type" "bitmanip")
(set_attr "mode" "<MODE>")])
+;; BMI instructions.
+(define_insn "*bmi_andn_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (not:SWI48
+ (match_operand:SWI48 1 "register_operand" "r"))
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "andn\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "bmi_bextr_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (match_operand:SWI48 2 "register_operand" "r")]
+ UNSPEC_BEXTR))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "bextr\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsi_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (neg:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm"))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsmsk_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (xor:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsmsk\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*bmi_blsr_<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (and:SWI48
+ (plus:SWI48
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (const_int -1))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_BMI"
+ "blsr\t{%1, %0|%0, %1}"
+ [(set_attr "type" "bitmanip")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "bsr_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (const_int 63)
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 28a921f9131..f4c3c582a15 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -358,6 +358,10 @@ mpopcnt
Target Report Mask(ISA_POPCNT) Var(ix86_isa_flags) Save
Support code generation of popcnt instruction.
+mbmi
+Target Report Mask(ISA_BMI) Var(ix86_isa_flags) Save
+Support BMI built-in functions and code generation
+
mcx16
Target Report Mask(ISA_CX16) Var(ix86_isa_flags) Save
Support code generation of cmpxchg16b instruction.
diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h
index 29d44dc8706..9a7366b769c 100644
--- a/gcc/config/i386/x86intrin.h
+++ b/gcc/config/i386/x86intrin.h
@@ -81,6 +81,10 @@
#include <abmintrin.h>
#endif
+#ifdef __BMI__
+#include <bmiintrin.h>
+#endif
+
#ifdef __POPCNT__
#include <popcntintrin.h>
#endif