Patchwork [2/2] AMD bdver2 processors - TBM

login
register
mail settings
Submitter Quentin Neill
Date Nov. 4, 2010, 2:58 p.m.
Message ID <AANLkTinmzgspzmeeYQf8M9QHMNpbkBnPqKZ2ENi4x3eg@mail.gmail.com>
Download mbox | patch
Permalink /patch/70139/
State New
Headers show

Comments

Quentin Neill - Nov. 4, 2010, 2:58 p.m.
Also with fixes suggested by Richard.

Passes bootstrap and make -k check on x86-64.

Okay to commit?
--
Quentin
From 1fe243fb0dd49c8b6b154b7f5d689111c0da33ed Mon Sep 17 00:00:00 2001
From: Quentin Neill <quentin.neill.gnu@gmail.com>
Date: Tue, 26 Oct 2010 13:37:11 -0500
Subject: [PATCH 2/2] 2010-11-04 Quentin Neill  <quentin.neill.gnu@gmail.com>

gcc/
	* config.gcc (i[34567]86-*-*): Include tbmintrin.h.
    (x86_64-*-*): Likewise.
	* config/i386/cpuid.h: Define TBM bit.
	* config/i386/driver-i386.c (host_detect_local_cpu): Define
	and set has_tbm.
	* config/i386/i386-builtin-types.def (UINT_FTYPE_UINT_UCHAR_UCHAR): New.
	(UINT64_FTYPE_UINT64_UCHAR_UCHAR): New.
	* config/i386/i386-c.c (ix86_target_macros_internal): Check
	isa_flag for TBM.
	* config/i386/i386.c (OPTION_MASK_ISA_TBM_SET): New.
	(OPTION_MASK_ISA_TBM_UNSET): New.
	(ix86_handle_option): Handle -mtbm.
	(isa_opts): Add -mtbm.
	(enum pta_flags): Add PTA_TBM.
	(ix86_option_override_internal): Add TBM support.
	(ix86_valid_target_attribute_inner_p): Handle -mtbm.
	(IX86_BUILTIN_BEXTRI32): New for TBM intrinsic.
	(IX86_BUILTIN_BEXTRI64): Likewise.
	(bdesc_args): Add TBM intrinsics.
	(ix86_expand_builtin): Add TBM specific case.
	* config/i386/i386.h (TARGET_TBM): New for TBM.
	* config/i386/i386.md (UNSPEC_BEXTRI): New for TBM.
	(tbm_bextri_<mode>): Likewise.
	(*tbm_blcfill_<mode>): Likewise.
	(*tbm_blci_<mode>): Likewise.
	(*tbm_blcic_<mode>): Likewise.
	(*tbm_blcmsk_<mode>): Likewise.
	(*tbm_blcs_<mode>): Likewise.
	(*tbm_blsfill_<mode>): Likewise.
	(*tbm_blsic_<mode>): Likewise.
	(*tbm_t1mskc_<mode>): Likewise.
	(*tbm_tzmsk_<mode>): Likewise.
	* config/i386/i386.opt: Add -mtbm.
	* config/i386/tbmintrin.h (__bextri_u32): New.
	(__blcfill_u32): Likewise.
	(__blci_u32): Likewise.
	(__blcic_u32): Likewise.
	(__blcmsk_u32): Likewise.
	(__blcs_u32): Likewise.
	(__blsfill_u32): Likewise.
	(__blsic_u32): Likewise.
	(__t1mskc_u32): Likewise.
	(__tzmsk_u32): Likewise.
	(__bextri_u64): Likewise.
	(__blcfill_u64): Likewise.
	(__blci_u64): Likewise.
	(__blcic_u64): Likewise.
	(__blcmsk_u64): Likewise.
	(__blcs_u64): Likewise.
	(__blsfill_u64): Likewise.
	(__blsic_u64): Likewise.
	(__t1mskc_u64): Likewise.
	(__tzmsk_u64): Likewise.
	* config/i386/x86intrin.h: Add TBM check and tbmintrin.h.
	* doc/invoke.texi: Document -mtbm.
	* doc/extend.texi: Document TBM built-in functions.

gcc/testsuite/
	* g++.dg/other/i386-2.C: Add -mtbm.
	* g++.dg/other/i386-3.C: Likewise.
	* gcc.target/i386/funcspec-5.c: Add tbm and no-tbm targets.
	* gcc.target/i386/funcspec-6.c: Likewise.
	* gcc.target/i386/sse-12.c: Add -mtbm.
	* gcc.target/i386/sse-13.c: Add -mtbm and test immediate
	operand intrinsics.
	* gcc.target/i386/sse-14.c: Likewise.
	* gcc.target/i386/sse-22.c: Likewise.
	* gcc.target/i386/sse-23.c: Likewise.
	* gcc.target/i386/tbm-1.c: New file.
	* gcc.target/i386/tbm-2.c: Likewise.
---
 gcc/config.gcc                             |    4 +-
 gcc/config/i386/cpuid.h                    |    1 +
 gcc/config/i386/driver-i386.c              |    5 +-
 gcc/config/i386/i386-builtin-types.def     |    2 +
 gcc/config/i386/i386-c.c                   |    2 +
 gcc/config/i386/i386.c                     |   60 ++++++++-
 gcc/config/i386/i386.h                     |    1 +
 gcc/config/i386/i386.md                    |  145 ++++++++++++++++++++
 gcc/config/i386/i386.opt                   |    4 +
 gcc/config/i386/tbmintrin.h                |  197 ++++++++++++++++++++++++++++
 gcc/config/i386/x86intrin.h                |    4 +
 gcc/doc/extend.texi                        |    8 +
 gcc/doc/invoke.texi                        |    4 +-
 gcc/testsuite/g++.dg/other/i386-2.C        |    6 +-
 gcc/testsuite/g++.dg/other/i386-3.C        |    6 +-
 gcc/testsuite/gcc.target/i386/funcspec-5.c |    2 +
 gcc/testsuite/gcc.target/i386/funcspec-6.c |    2 +
 gcc/testsuite/gcc.target/i386/sse-12.c     |    4 +-
 gcc/testsuite/gcc.target/i386/sse-13.c     |   11 +-
 gcc/testsuite/gcc.target/i386/sse-14.c     |    8 +-
 gcc/testsuite/gcc.target/i386/sse-22.c     |   20 ++-
 gcc/testsuite/gcc.target/i386/sse-23.c     |   12 +-
 gcc/testsuite/gcc.target/i386/tbm-1.c      |   74 +++++++++++
 gcc/testsuite/gcc.target/i386/tbm-2.c      |   75 +++++++++++
 24 files changed, 630 insertions(+), 27 deletions(-)
 create mode 100644 gcc/config/i386/tbmintrin.h
 create mode 100644 gcc/testsuite/gcc.target/i386/tbm-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/tbm-2.c
Richard Henderson - Nov. 4, 2010, 4:19 p.m.
> +  ;; For TBM support
> +  UNSPEC_BEXTRI

Leftover.

> +(define_insn "*tbm_blci_<mode>"
> +  [(set (match_operand:SWI48 0 "register_operand" "=r")
> +        (ior:SWI48
> +		  (not:SWI48
> +            (plus:SWI48
> +              (match_operand:SWI48 1 "nonimmediate_operand" "rm")
> +              (const_int 1)))
> +          (match_dup 1)))

Alignment.

> +  [(set_attr "type" "bitmanip")
> +   (set_attr "mode" "<MODE>")])
> +
> +
> +

Watch the extra vertical whitespace.

> +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
> +__bextri_u32 (unsigned int __X, const unsigned int __I)
> +{
> +	unsigned char length    = ((__I >> 8) & 0xFF);
> +	unsigned char lsb_index = (__I & 0xFF);
> +	return __builtin_ia32_bextri_u32 (__X, length, lsb_index);

If you hadn't created the bextri builtin with three arguments,
you wouldn't have to play the tricks you're doing here to make
sure that the final arguments are constants.

Unless you want to expose both constants to the user intrinsic
(which isn't a horrible idea if you are not already constrained
by external documentation of these), there's no reason you can't
pull apart the two bytes of the immediate inside the builtin
expander instead.

> +@smallexample
> +unsigned int __builtin_ia32_bextri_u32 (unsigned int, const unsigned int);
> +unsigned long long __builtin_ia32_bextri_u64 (unsigned long long, const unsigned long long);
> +@end smallexample

... and you documentation wasn't updated to match.  Though if you
are going to change it back...


r~
Quentin Neill - Nov. 4, 2010, 4:43 p.m.
Hi Richard,

On Thu, Nov 4, 2010 at 11:19 AM, Richard Henderson <rth@redhat.com> wrote:
>> +  [(set_attr "type" "bitmanip")
>> +   (set_attr "mode" "<MODE>")])
>> +
>> +
>> +
> Watch the extra vertical whitespace.

So should I have two lines (to separate list of ';TBM instructions')
or just one?


>> +extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
>> +__bextri_u32 (unsigned int __X, const unsigned int __I)
>> +{
>> +     unsigned char length    = ((__I >> 8) & 0xFF);
>> +     unsigned char lsb_index = (__I & 0xFF);
>> +     return __builtin_ia32_bextri_u32 (__X, length, lsb_index);
>
> If you hadn't created the bextri builtin with three arguments,
> you wouldn't have to play the tricks you're doing here to make
> sure that the final arguments are constants.
>
> Unless you want to expose both constants to the user intrinsic
> (which isn't a horrible idea if you are not already constrained
> by external documentation of these), there's no reason you can't
> pull apart the two bytes of the immediate inside the builtin
> expander instead.

I was a little uneasy with this little wart as well.  I was following
your feedback "the builtin function would need a bit of tweaking".

The builtin signature follows the signature of the BEXTR insn (and an
internal standard set for other compilers).

So pulling the two bytes out in the builtin expander - should that be
done with a *new* define_expand?  Or is there a set of RTX operations
(shift, mask) I should use in the define_insn as written?

Any hints appreciated :)

And good catch on all the others, thanks.
Richard Henderson - Nov. 4, 2010, 5:36 p.m.
On 11/04/2010 09:43 AM, Quentin Neill wrote:
>> Watch the extra vertical whitespace.
> 
> So should I have two lines (to separate list of ';TBM instructions')
> or just one?

Just one.

> So pulling the two bytes out in the builtin expander - should that be
> done with a *new* define_expand?  Or is there a set of RTX operations
> (shift, mask) I should use in the define_insn as written?

There's a set of C operators you may use.  ;-)

This is an *immediate*.  It's value is INTVAL (op1).
You can pull bits out from that and use GEN_INT to
pass the new rtl on to the define_insn.


r~

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index f3c8ae3..a110a27 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -316,7 +316,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"
+		       abmintrin.h bmiintrin.h tbmintrin.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -327,7 +327,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"
+		       abmintrin.h bmiintrin.h tbmintrin.h"
 	need_64bit_hwint=yes
 	;;
 ia64-*-*)
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 0f1af7f..e9d0fab 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -54,6 +54,7 @@ 
 #define bit_XOP         (1 << 11)
 #define bit_LWP 	(1 << 15)
 #define bit_FMA4        (1 << 16)
+#define bit_TBM         (1 << 21)
 
 /* %edx */
 #define bit_LM		(1 << 29)
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 6319a14..288d507 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -397,7 +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;
+  unsigned int has_bmi = 0, has_tbm = 0;
 
   bool arch;
 
@@ -464,6 +464,7 @@  const char *host_detect_local_cpu (int argc, const char **argv)
       has_lwp = ecx & bit_LWP;
       has_fma4 = ecx & bit_FMA4;
       has_xop = ecx & bit_XOP;
+      has_tbm = ecx & bit_TBM;
 
       has_longmode = edx & bit_LM;
       has_3dnowp = edx & bit_3DNOWP;
@@ -693,6 +694,8 @@  const char *host_detect_local_cpu (int argc, const char **argv)
 	options = concat (options, " -mxop", NULL);
       if (has_bmi)
 	options = concat (options, " -mbmi", NULL);
+      if (has_tbm)
+	options = concat (options, " -mtbm", NULL);
 
       if (has_avx)
 	options = concat (options, " -mavx", NULL);
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 110b81d..6e6335d 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -223,9 +223,11 @@  DEF_FUNCTION_TYPE (QI, V8QI, INT)
 DEF_FUNCTION_TYPE (SI, V2SI, INT)
 DEF_FUNCTION_TYPE (SI, V4SI, INT)
 DEF_FUNCTION_TYPE (UINT, UINT, UCHAR)
+DEF_FUNCTION_TYPE (UINT, UINT, UCHAR, UCHAR)
 DEF_FUNCTION_TYPE (UINT, UINT, UINT)
 DEF_FUNCTION_TYPE (UINT, UINT, USHORT)
 DEF_FUNCTION_TYPE (UINT16, UINT16, INT)
+DEF_FUNCTION_TYPE (UINT64, UINT64, UCHAR, UCHAR)
 DEF_FUNCTION_TYPE (UINT64, UINT64, UINT64)
 DEF_FUNCTION_TYPE (UINT8, UINT8, INT)
 DEF_FUNCTION_TYPE (V16QI, V16QI, SI)
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 51c0c13..ca35177 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -255,6 +255,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_TBM)
+    def_or_undef (parse_in, "__TBM__");
   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 d23c267..4382237 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2326,7 +2326,7 @@  static int ix86_isa_flags_explicit;
   (OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT)
 
 #define OPTION_MASK_ISA_BMI_SET OPTION_MASK_ISA_BMI
-
+#define OPTION_MASK_ISA_TBM_SET OPTION_MASK_ISA_TBM
 #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
@@ -2382,6 +2382,7 @@  static int ix86_isa_flags_explicit;
 #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_TBM_UNSET OPTION_MASK_ISA_TBM
 #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
@@ -2697,6 +2698,19 @@  ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
 	}
       return true;
 
+    case OPT_mtbm:
+      if (value)
+	{
+	  ix86_isa_flags |= OPTION_MASK_ISA_TBM_SET;
+	  ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_SET;
+	}
+      else
+	{
+	  ix86_isa_flags &= ~OPTION_MASK_ISA_TBM_UNSET;
+	  ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_UNSET;
+	}
+      return true;
+
     case OPT_mpopcnt:
       if (value)
 	{
@@ -2866,6 +2880,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 },
+    { "-mtbm",		OPTION_MASK_ISA_TBM },
     { "-mpopcnt",	OPTION_MASK_ISA_POPCNT },
     { "-mmovbe",	OPTION_MASK_ISA_MOVBE },
     { "-mcrc32",	OPTION_MASK_ISA_CRC32 },
@@ -3122,7 +3137,8 @@  ix86_option_override_internal (bool main_args_p)
       PTA_FSGSBASE = 1 << 24,
       PTA_RDRND = 1 << 25,
       PTA_F16C = 1 << 26,
-      PTA_BMI = 1 << 27
+      PTA_BMI = 1 << 27,
+      PTA_TBM = 1 << 28
       /* if this reaches 32, need to widen struct pta flags below */
     };
 
@@ -3461,6 +3477,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_TBM
+	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM))
+	  ix86_isa_flags |= OPTION_MASK_ISA_TBM;
 	if (processor_alias_table[i].flags & PTA_CX16
 	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16))
 	  ix86_isa_flags |= OPTION_MASK_ISA_CX16;
@@ -4299,6 +4318,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 ("tbm",	OPT_mtbm),
     IX86_ATTR_ISA ("aes",	OPT_maes),
     IX86_ATTR_ISA ("avx",	OPT_mavx),
     IX86_ATTR_ISA ("mmx",	OPT_mmmx),
@@ -23959,6 +23979,11 @@  enum ix86_builtins
   IX86_BUILTIN_BEXTR64,
   IX86_BUILTIN_CTZS,
 
+  /* TBM instructions.  */
+  IX86_BUILTIN_BEXTRI32,
+  IX86_BUILTIN_BEXTRI64,
+
+
   /* FSGSBASE instructions.  */
   IX86_BUILTIN_RDFSBASE32,
   IX86_BUILTIN_RDFSBASE64,
@@ -24903,6 +24928,10 @@  static const struct builtin_description bdesc_args[] =
   { 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 },
 
+  /* TBM */
+  { OPTION_MASK_ISA_TBM, CODE_FOR_tbm_bextri_si, "__builtin_ia32_bextri_u32", IX86_BUILTIN_BEXTRI32, UNKNOWN, (int) UINT_FTYPE_UINT_UCHAR_UCHAR },
+  { OPTION_MASK_ISA_TBM, CODE_FOR_tbm_bextri_di, "__builtin_ia32_bextri_u64", IX86_BUILTIN_BEXTRI64, UNKNOWN, (int) UINT64_FTYPE_UINT64_UCHAR_UCHAR },
+
   /* 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 },
@@ -27015,6 +27044,33 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       emit_insn (gen_lwp_slwpcb (target));
       return target;
 
+    case IX86_BUILTIN_BEXTRI32:
+    case IX86_BUILTIN_BEXTRI64:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      arg1 = CALL_EXPR_ARG (exp, 1);
+      arg2 = CALL_EXPR_ARG (exp, 1);
+      op0 = expand_normal (arg0);
+      op1 = expand_normal (arg1);
+      op2 = expand_normal (arg1);
+      icode = (fcode == IX86_BUILTIN_BEXTRI32
+	  ? CODE_FOR_tbm_bextri_si
+	  : CODE_FOR_tbm_bextri_di);
+      if (!CONST_INT_P (op1))
+      {
+        error ("next to last argument must be an immediate");
+        mode0 = insn_data[icode].operand[0].mode;
+        return gen_reg_rtx(mode0);
+      }
+      if (!CONST_INT_P (op2))
+      {
+        error ("last argument must be an immediate");
+        mode0 = insn_data[icode].operand[0].mode;
+        return gen_reg_rtx(mode0);
+      }
+      pat = GEN_FCN (icode) (target, op0, op1, op2);
+      if (pat) emit_insn (pat);
+      return target;
+
     default:
       break;
     }
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index d854797..8ef0d7b 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -60,6 +60,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_TBM	OPTION_ISA_TBM
 #define TARGET_POPCNT	OPTION_ISA_POPCNT
 #define TARGET_SAHF	OPTION_ISA_SAHF
 #define TARGET_MOVBE	OPTION_ISA_MOVBE
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 379d62b..ab9a102 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -232,6 +232,10 @@ 
   ;; For BMI support
   UNSPEC_BEXTR
   UNSPEC_TZCNT
+
+
+  ;; For TBM support
+  UNSPEC_BEXTRI
 ])
 
 (define_c_enum "unspecv" [
@@ -12098,6 +12102,147 @@ 
   [(set_attr "type" "bitmanip")
    (set_attr "mode" "<MODE>")])
 
+
+;; TBM instructions.
+(define_insn "tbm_bextri_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (zero_extract:SWI48
+          (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+          (match_operand:SWI48 2 "const_0_to_255_operand" "n")
+          (match_operand:SWI48 3 "const_0_to_255_operand" "n")))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) << 8 | INTVAL (operands[3]));
+  return "bextr\t{%2, %1, %0|%0, %1, %2}";
+}
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcfill_<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_TBM"
+   "blcfill\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blci_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (ior:SWI48
+		  (not:SWI48
+            (plus:SWI48
+              (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+              (const_int 1)))
+          (match_dup 1)))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "blci\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcic_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (and:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int 1))
+          (not:SWI48
+            (match_dup 1))))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "blcic\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcmsk_<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_TBM"
+   "blcmsk\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blcs_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (ior:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int 1))
+          (match_dup 1)))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "blcs\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blsfill_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (ior:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int -1))
+          (match_dup 1)))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "blsfill\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_blsic_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (ior:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int -1))
+          (not:SWI48
+            (match_dup 1))))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "blsic\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_t1mskc_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (ior:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int 1))
+          (not:SWI48
+            (match_dup 1))))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "t1mskc\t{%1, %0|%0, %1}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "*tbm_tzmsk_<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+        (and:SWI48
+          (plus:SWI48
+            (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+            (const_int -1))
+          (not:SWI48
+            (match_dup 1))))
+   (clobber (reg:CC FLAGS_REG))]
+   "TARGET_TBM"
+   "tzmsk\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 f4c3c58..aa1d615 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -362,6 +362,10 @@  mbmi
 Target Report Mask(ISA_BMI) Var(ix86_isa_flags) Save
 Support BMI built-in functions and code generation
 
+mtbm
+Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save
+Support TBM 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/tbmintrin.h b/gcc/config/i386/tbmintrin.h
new file mode 100644
index 0000000..759d81b
--- /dev/null
+++ b/gcc/config/i386/tbmintrin.h
@@ -0,0 +1,197 @@ 
+/* 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 <tbmintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef __TBM__
+# error "TBM instruction set not enabled"
+#endif /* __TBM__ */
+
+#ifndef _TBMINTRIN_H_INCLUDED
+#define _TBMINTRIN_H_INCLUDED
+
+#ifdef __OPTIMIZE__
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__bextri_u32 (unsigned int __X, const unsigned int __I)
+{
+	unsigned char length    = ((__I >> 8) & 0xFF);
+	unsigned char lsb_index = (__I & 0xFF);
+	return __builtin_ia32_bextri_u32 (__X, length, lsb_index);
+}
+#else
+#define __bextri_u32(X, I)                                                            \
+	((unsigned int)__builtin_ia32_bextri_u32 ((unsigned int)(X),                  \
+	                                          (unsigned char)(((I) >> 8) & 0xFF), \
+	                                          (unsigned char)((I) & 0xFF)))
+#endif /*__OPTIMIZE__ */
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blcfill_u32 (unsigned int __X)
+{
+	unsigned int tmp = (__X) & ((__X) + 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blci_u32 (unsigned int __X)
+{
+	unsigned int tmp = (__X) | (~((__X) + 1));
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blcic_u32 (unsigned int __X)
+{
+	unsigned int tmp = (~(__X)) & ((__X) + 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blcmsk_u32 (unsigned int __X)
+{
+	unsigned int tmp = (__X) ^ ((__X) + 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blcs_u32 (unsigned int __X)
+{
+	unsigned int tmp = (__X) | ((__X) + 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsfill_u32 (unsigned int __X)
+{
+	unsigned int tmp = (__X) | ((__X) - 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blsic_u32 (unsigned int __X)
+{
+	unsigned int tmp = (~(__X)) | ((__X) - 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__t1mskc_u32 (unsigned int __X)
+{
+	unsigned int tmp = (~(__X)) | ((__X) + 1);
+	return tmp;
+}
+
+extern __inline unsigned int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__tzmsk_u32 (unsigned int __X)
+{
+	unsigned int tmp = (~(__X)) & ((__X) - 1);
+	return tmp;
+}
+
+
+
+#ifdef __x86_64__
+#ifdef __OPTIMIZE__
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__bextri_u64 (unsigned long long __X, const unsigned int __I)
+{
+	unsigned char length    = ((__I >> 8) & 0xFF);
+	unsigned char lsb_index = (__I & 0xFF);
+	return __builtin_ia32_bextri_u64 (__X, length, lsb_index);
+}
+#else
+#define __bextri_u64(X, I)                                                                  \
+	((unsigned long long)__builtin_ia32_bextri_u64 ((unsigned long long)(X),            \
+	                                                (unsigned char)(((I) >> 8) & 0xFF), \
+	                                                (unsigned char)((I) & 0xFF)))
+#endif /*__OPTIMIZE__ */
+
+extern __inline unsigned long long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__blcfill_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__))
+__blci_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__))
+__blcic_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__))
+__blcmsk_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__))
+__blcs_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__))
+__blsfill_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__))
+__blsic_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__))
+__t1mskc_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__))
+__tzmsk_u64 (unsigned long long __X)
+{
+	unsigned long long tmp = (~(__X)) & ((__X) - 1);
+	return tmp;
+}
+
+
+#endif /* __x86_64__  */
+#endif /* _TBMINTRIN_H_INCLUDED */
+
diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h
index 9a7366b..72c4175 100644
--- a/gcc/config/i386/x86intrin.h
+++ b/gcc/config/i386/x86intrin.h
@@ -85,6 +85,10 @@ 
 #include <bmiintrin.h>
 #endif
 
+#ifdef __TBM__
+#include <tbmintrin.h>
+#endif
+
 #ifdef __POPCNT__
 #include <popcntintrin.h>
 #endif
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 6a969ed..2b9a5bb 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -9397,6 +9397,14 @@  unsigned int __builtin_ia32_tzcnt_u32(unsigned int);
 unsigned long long __builtin_ia32_tzcnt_u64 (unsigned long long);
 @end smallexample
 
+The following built-in functions are available when @option{-mtbm} is used.
+Both of them generate the immediate form of the bextr machine instruction.
+@smallexample
+unsigned int __builtin_ia32_bextri_u32 (unsigned int, const unsigned int);
+unsigned long long __builtin_ia32_bextri_u64 (unsigned long long, const unsigned long long);
+@end smallexample
+
+
 The following built-in functions are available when @option{-m3dnow} is used.
 All of them generate the machine instruction that is part of the name.
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b125b49..8c97022 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -598,7 +598,7 @@  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 -mfused-madd @gol
--msse4a -m3dnow -mpopcnt -mabm -mbmi -mfma4 -mxop -mlwp @gol
+-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlwp @gol
 -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
@@ -12435,6 +12435,8 @@  preferred alignment to @option{-mpreferred-stack-boundary=2}.
 @itemx -mno-abm
 @itemx -mbmi
 @itemx -mno-bmi
+@itemx -mtbm
+@itemx -mno-tbm
 @opindex mmmx
 @opindex mno-mmx
 @opindex msse
diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
index f0a382a..6f7ca84 100644
--- a/gcc/testsuite/g++.dg/other/i386-2.C
+++ b/gcc/testsuite/g++.dg/other/i386-2.C
@@ -1,9 +1,9 @@ 
 /* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -pedantic-errors -march=k8 -m3dnow -mavx -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mlwp -mfsgsbase -mrdrnd -mf16c" } */
+/* { dg-options "-O -pedantic-errors -march=k8 -m3dnow -mavx -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */
 
 /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, xopintrin.h, abmintrin.h,
-   bmiintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h are usable with
-   -O -pedantic-errors.  */
+   bmiintrin.h, tbmintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h
+   are usable with -O -pedantic-errors.  */
 
 #include <x86intrin.h>
 
diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C
index 4b27372..a8b2039 100644
--- a/gcc/testsuite/g++.dg/other/i386-3.C
+++ b/gcc/testsuite/g++.dg/other/i386-3.C
@@ -1,8 +1,8 @@ 
 /* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -fkeep-inline-functions -march=k8 -m3dnow -mavx -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mlwp -mfsgsbase -mrdrnd -mf16c" } */
+/* { dg-options "-O -fkeep-inline-functions -march=k8 -m3dnow -mavx -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */
 
 /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, xopintrin.h, abmintrin.h,
-   bmiintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h are usable with
-   -O -fkeep-inline-functions.  */
+   bmiintrin.h, tbmintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h
+   are usable with -O -fkeep-inline-functions.  */
 
 #include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-5.c b/gcc/testsuite/gcc.target/i386/funcspec-5.c
index 5e07d85..1e18dcf 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-5.c
+++ b/gcc/testsuite/gcc.target/i386/funcspec-5.c
@@ -19,6 +19,7 @@  extern void test_sse4_2 (void)			__attribute__((__target__("sse4.2")));
 extern void test_sse4a (void)			__attribute__((__target__("sse4a")));
 extern void test_fma4 (void)			__attribute__((__target__("fma4")));
 extern void test_ssse3 (void)			__attribute__((__target__("ssse3")));
+extern void test_tbm (void)			__attribute__((__target__("tbm")));
 
 extern void test_no_abm (void)			__attribute__((__target__("no-abm")));
 extern void test_no_aes (void)			__attribute__((__target__("no-aes")));
@@ -36,6 +37,7 @@  extern void test_no_sse4_2 (void)		__attribute__((__target__("no-sse4.2")));
 extern void test_no_sse4a (void)		__attribute__((__target__("no-sse4a")));
 extern void test_no_fma4 (void)			__attribute__((__target__("no-fma4")));
 extern void test_no_ssse3 (void)		__attribute__((__target__("no-ssse3")));
+extern void test_no_tbm (void)			__attribute__((__target__("no-tbm")));
 
 extern void test_arch_i386 (void)		__attribute__((__target__("arch=i386")));
 extern void test_arch_i486 (void)		__attribute__((__target__("arch=i486")));
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-6.c b/gcc/testsuite/gcc.target/i386/funcspec-6.c
index 81c831c..92a3cb5 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-6.c
+++ b/gcc/testsuite/gcc.target/i386/funcspec-6.c
@@ -19,6 +19,7 @@  extern void test_sse4_2 (void)			__attribute__((__target__("sse4.2")));
 extern void test_sse4a (void)			__attribute__((__target__("sse4a")));
 extern void test_fma4 (void)			__attribute__((__target__("fma4")));
 extern void test_ssse3 (void)			__attribute__((__target__("ssse3")));
+extern void test_tbm (void)			__attribute__((__target__("tbm")));
 
 extern void test_no_abm (void)			__attribute__((__target__("no-abm")));
 extern void test_no_aes (void)			__attribute__((__target__("no-aes")));
@@ -36,6 +37,7 @@  extern void test_no_sse4_2 (void)		__attribute__((__target__("no-sse4.2")));
 extern void test_no_sse4a (void)		__attribute__((__target__("no-sse4a")));
 extern void test_no_fma4 (void)			__attribute__((__target__("no-fma4")));
 extern void test_no_ssse3 (void)		__attribute__((__target__("no-ssse3")));
+extern void test_no_tbm (void)			__attribute__((__target__("no-tbm")));
 
 extern void test_arch_nocona (void)		__attribute__((__target__("arch=nocona")));
 extern void test_arch_core2 (void)		__attribute__((__target__("arch=core2")));
diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
index d59777b..fb53c3c 100644
--- a/gcc/testsuite/gcc.target/i386/sse-12.c
+++ b/gcc/testsuite/gcc.target/i386/sse-12.c
@@ -1,9 +1,9 @@ 
 /* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, xopintrin.h, mm3dnow.h,
-   fma4intrin.h, abmintrin.h, bmiintrin.h, lwpintrin.h,
+   fma4intrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
    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 -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mlwp -mfsgsbase -mrdrnd -mf16c" } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -m3dnow -mavx -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mbmi -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */
 
 #include <x86intrin.h>
 
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index 01809d0..752ec8c 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -5,9 +5,9 @@ 
 
 /* Test that the intrinsics compile with optimization.  All of them
    are defined as inline functions in {,x,e,p,t,s,w,a,b,i}mmintrin.h,
-   xopintrin.h, abmintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h
-   that reference the proper builtin functions.  Defining away
-   "extern" and "__inline" results in all of them being compiled as
+   xopintrin.h, abmintrin.h, tbmintrin.h, lwpintrin.h, popcntintrin.h
+   and mm3dnow.h that reference the proper builtin functions.  Defining
+   away "extern" and "__inline" results in all of them being compiled as
    proper functions.  */
 
 #define extern
@@ -141,4 +141,9 @@ 
 #define __builtin_ia32_lwpins32(D2, D1, F) __builtin_ia32_lwpins32 (D2, D1, 1)
 #define __builtin_ia32_lwpins64(D2, D1, F) __builtin_ia32_lwpins64 (D2, D1, 1)
 
+/* tbmintrin.h */
+#define __builtin_ia32_bextri_u32(X, Y) __builtin_ia32_bextri_u32 (X, 1, 1)
+#define __builtin_ia32_bextri_u64(X, Y) __builtin_ia32_bextri_u64 (X, 1, 1)
+
+
 #include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index d256e68..41bde1b 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 -m3dnow -mavx -mxop -msse4a -maes -mpclmul -mpopcnt -mabm -mlwp -mfsgsbase -mrdrnd -mf16c" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mxop -msse4a -maes -mpclmul -mpopcnt -mabm -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c" } */
 
 #include <mm_malloc.h>
 
@@ -177,3 +177,9 @@  test_2 ( __lwpins32, unsigned char, unsigned int, unsigned int, 1)
 test_2 ( __lwpval64, void, unsigned long long, unsigned int, 1)
 test_2 ( __lwpins64, unsigned char, unsigned long long, unsigned int, 1)
 #endif
+
+/* tbmintrin.h */
+test_1 ( __bextri_u32, unsigned int, unsigned int, 1)
+#ifdef __x86_64__
+test_1 ( __bextri_u64, unsigned long long, unsigned long long, 1)
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index bb0472d..e28164d 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -6,10 +6,10 @@ 
 
 /* Test that the intrinsics compile without optimization.  All of them
    are defined as inline functions in {,x,e,p,t,s,w,a}mmintrin.h,
-   xopintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h that
-   reference the proper builtin functions.  Defining away "extern" and
-   "__inline" results in all of them being compiled as proper
-   functions.  */
+   xopintrin.h, tbmintrin.h, lwpintrin.h, popcntintrin.h and
+   mm3dnow.h that reference the proper builtin functions.  Defining
+   away "extern" and "__inline" results in all of them being compiled as
+   proper functions.  */
 
 #define extern
 #define __inline
@@ -39,7 +39,7 @@ 
 
 
 #ifndef DIFFERENT_PRAGMAS
-#pragma GCC target ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse4a,aes,pclmul,xop,popcnt,abm,lwp,fsgsbase,rdrnd,f16c")
+#pragma GCC target ("mmx,3dnow,sse,sse2,sse3,ssse3,sse4.1,sse4.2,sse4a,aes,pclmul,xop,popcnt,abm,lwp,fsgsbase,rdrnd,f16c,tbm")
 #endif
 
 /* Following intrinsics require immediate arguments.  They
@@ -188,3 +188,13 @@  test_2 ( __lwpins64, unsigned char, unsigned long long, unsigned int, 1)
 test_1 (_cvtss_sh, unsigned short, float, 1)
 test_1 (_mm_cvtps_ph, __m128i, __m128, 1)
 test_1 (_mm256_cvtps_ph, __m128i, __m256, 1)
+
+/* tbmintrin.h (TBM). */
+#ifdef DIFFERENT_PRAGMAS
+#pragma GCC target ("tbm")
+#endif
+#include <x86intrin.h>
+test_1 ( __bextri_u32, unsigned int, unsigned int, 1)
+#ifdef __x86_64__
+test_1 ( __bextri_u64, unsigned long long, unsigned long long, 1)
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index 0e15bb2..d3da301 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -5,9 +5,9 @@ 
 
 /* Test that the intrinsics compile with optimization.  All of them
    are defined as inline functions in {,x,e,p,t,s,w,a}mmintrin.h,
-   xopintrin.h, lwpintrin.h, popcntintrin.h and mm3dnow.h that
-   reference the proper builtin functions.  Defining away "extern" and
-   "__inline" results in all of them being compiled as proper
+   xopintrin.h, lwpintrin.h, tbmintrin.h, popcntintrin.h and mm3dnow.h
+   that reference the proper builtin functions.  Defining away "extern"
+   and "__inline" results in all of them being compiled as proper
    functions.  */
 
 #define extern
@@ -141,7 +141,11 @@ 
 #define __builtin_ia32_lwpins32(D2, D1, F) __builtin_ia32_lwpins32 (D2, D1, 1)
 #define __builtin_ia32_lwpins64(D2, D1, F) __builtin_ia32_lwpins64 (D2, D1, 1)
 
-#pragma GCC target ("3dnow,sse4,sse4a,aes,pclmul,xop,abm,popcnt,lwp,fsgsbase,rdrnd,f16c")
+/* tbmintrin.h */
+#define __builtin_ia32_bextri_u32(X, Y, Z) __builtin_ia32_bextr_u32 (X, 1, 1)
+#define __builtin_ia32_bextri_u64(X, Y, Z) __builtin_ia32_bextr_u64 (X, 1, 1)
+
+#pragma GCC target ("3dnow,sse4,sse4a,aes,pclmul,xop,abm,popcnt,lwp,tbm,fsgsbase,rdrnd,f16c")
 #include <wmmintrin.h>
 #include <smmintrin.h>
 #include <mm3dnow.h>
diff --git a/gcc/testsuite/gcc.target/i386/tbm-1.c b/gcc/testsuite/gcc.target/i386/tbm-1.c
new file mode 100644
index 0000000..2459a1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/tbm-1.c
@@ -0,0 +1,74 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtbm" } */
+/* { dg-final { scan-assembler "bextr\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blcfill\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blci\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blcic\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blcmsk\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blcs\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blsfill\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "blsic\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "t1mskc\[^\\n]*(%|)eax" } } */
+/* { dg-final { scan-assembler "tzmsk\[^\\n]*(%|)eax" } } */
+
+#include <x86intrin.h>
+
+unsigned int
+func_bextri32 (unsigned int X)
+{
+  return __bextri_u32 (X, 1);
+}
+
+unsigned int
+func_blcfill32 (unsigned int X)
+{
+  return __blcfill_u32 (X);
+}
+
+unsigned int
+func_blci32 (unsigned int X)
+{
+  return __blci_u32 (X);
+}
+
+unsigned int
+func_blcic32 (unsigned int X)
+{
+  return __blcic_u32 (X);
+}
+
+unsigned int
+func_blcmsk32 (unsigned int X)
+{
+  return __blcmsk_u32 (X);
+}
+
+unsigned int
+func_blcs32 (unsigned int X)
+{
+  return __blcs_u32 (X);
+}
+
+unsigned int
+func_blsfill32 (unsigned int X)
+{
+  return __blsfill_u32 (X);
+}
+
+unsigned int
+func_blsic32 (unsigned int X)
+{
+  return __blsic_u32 (X);
+}
+
+unsigned int
+func_t1mskc32 (unsigned int X)
+{
+  return __t1mskc_u32 (X);
+}
+
+unsigned int
+func_tzmsk32 (unsigned int X)
+{
+  return __tzmsk_u32 (X);
+}
diff --git a/gcc/testsuite/gcc.target/i386/tbm-2.c b/gcc/testsuite/gcc.target/i386/tbm-2.c
new file mode 100644
index 0000000..c845eef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/tbm-2.c
@@ -0,0 +1,75 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mtbm" } */
+/* { dg-final { scan-assembler "bextr\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blcfill\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blci\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blcic\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blcmsk\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blcs\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blsfill\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "blsic\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "t1mskc\[^\\n]*(%|)rax" } } */
+/* { dg-final { scan-assembler "tzmsk\[^\\n]*(%|)rax" } } */
+
+#include <x86intrin.h>
+
+unsigned long long
+func_bextri64 (unsigned long long X)
+{
+  return __bextri_u64 (X, 1);
+}
+
+unsigned long long
+func_blcfill64 (unsigned long long X)
+{
+  return __blcfill_u64 (X);
+}
+
+unsigned long long
+func_blci64 (unsigned long long X)
+{
+  return __blci_u64 (X);
+}
+
+unsigned long long
+func_blcic64 (unsigned long long X)
+{
+  return __blcic_u64 (X);
+}
+
+unsigned long long
+func_blcmsk64 (unsigned long long X)
+{
+  return __blcmsk_u64 (X);
+}
+
+unsigned long long
+func_blcs64 (unsigned long long X)
+{
+  return __blcs_u64 (X);
+}
+
+unsigned long long
+func_blsfill64 (unsigned long long X)
+{
+  return __blsfill_u64 (X);
+}
+
+unsigned long long
+func_blsic64 (unsigned long long X)
+{
+  return __blsic_u64 (X);
+}
+
+unsigned long long
+func_t1mskc64 (unsigned long long X)
+{
+  return __t1mskc_u64 (X);
+}
+
+unsigned long long
+func_tzmsk64 (unsigned long long X)
+{
+  return __tzmsk_u64 (X);
+}