diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 3b6c4a85579..fec5cef0b55 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -1270,8 +1270,8 @@ BDESC (OPTION_MASK_ISA_BMI, 0, CODE_FOR_tzcnt_si, "__builtin_ia32_tzcnt_u32", IX
 BDESC (OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_64BIT, 0, CODE_FOR_tzcnt_di, "__builtin_ia32_tzcnt_u64", IX86_BUILTIN_TZCNT64, UNKNOWN, (int) UINT64_FTYPE_UINT64)
 
 /* TBM */
-BDESC (OPTION_MASK_ISA_TBM, 0, CODE_FOR_tbm_bextri_si, "__builtin_ia32_bextri_u32", IX86_BUILTIN_BEXTRI32, UNKNOWN, (int) UINT_FTYPE_UINT_UINT)
-BDESC (OPTION_MASK_ISA_TBM | OPTION_MASK_ISA_64BIT, 0, CODE_FOR_tbm_bextri_di, "__builtin_ia32_bextri_u64", IX86_BUILTIN_BEXTRI64, UNKNOWN, (int) UINT64_FTYPE_UINT64_UINT64)
+BDESC (OPTION_MASK_ISA_TBM, 0, CODE_FOR_nothing, "__builtin_ia32_bextri_u32", IX86_BUILTIN_BEXTRI32, UNKNOWN, (int) UINT_FTYPE_UINT_UINT)
+BDESC (OPTION_MASK_ISA_TBM | OPTION_MASK_ISA_64BIT, 0, CODE_FOR_nothing, "__builtin_ia32_bextri_u64", IX86_BUILTIN_BEXTRI64, UNKNOWN, (int) UINT64_FTYPE_UINT64_UINT64)
 
 /* F16C */
 BDESC (OPTION_MASK_ISA_F16C, 0, CODE_FOR_vcvtph2ps, "__builtin_ia32_vcvtph2ps", IX86_BUILTIN_CVTPH2PS, UNKNOWN, (int) V4SF_FTYPE_V8HI)
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 9de6f5029b9..d8368bfd4a9 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -11709,24 +11709,26 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_BEXTRI32:
     case IX86_BUILTIN_BEXTRI64:
+      mode = (fcode == IX86_BUILTIN_BEXTRI32 ? SImode : DImode);
+
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
       op0 = expand_normal (arg0);
       op1 = expand_normal (arg1);
-      icode = (fcode == IX86_BUILTIN_BEXTRI32
-	  ? CODE_FOR_tbm_bextri_si
-	  : CODE_FOR_tbm_bextri_di);
+
       if (!CONST_INT_P (op1))
-        {
-          error ("last argument must be an immediate");
-          return const0_rtx;
-        }
+	{
+	  error ("last argument must be an immediate");
+	  return const0_rtx;
+	}
       else
-        {
-          unsigned char length = (INTVAL (op1) >> 8) & 0xFF;
-          unsigned char lsb_index = INTVAL (op1) & 0xFF;
-          op1 = GEN_INT (length);
-          op2 = GEN_INT (lsb_index);
+	{
+	  unsigned char lsb_index = UINTVAL (op1);
+	  unsigned char length = UINTVAL (op1) >> 8;
+
+	  unsigned char bitsize = GET_MODE_BITSIZE (mode);
+
+	  icode = code_for_tbm_bextri (mode);
 
 	  mode1 = insn_data[icode].operand[1].mode;
 	  if (!insn_data[icode].operand[1].predicate (op0, mode1))
@@ -11737,25 +11739,32 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	      || !register_operand (target, mode0))
 	    target = gen_reg_rtx (mode0);
 
-          pat = GEN_FCN (icode) (target, op0, op1, op2);
-          if (pat)
-            emit_insn (pat);
-          return target;
-        }
+	  if (length == 0 || lsb_index >= bitsize)
+	    {
+	      emit_move_insn (target, const0_rtx);
+	      return target;
+	    }
+
+	  if (length + lsb_index > bitsize)
+	    length = bitsize - lsb_index;
+
+	  op1 = GEN_INT (length);
+	  op2 = GEN_INT (lsb_index);
+
+	  emit_insn (GEN_FCN (icode) (target, op0, op1, op2));
+	  return target;
+	}
 
     case IX86_BUILTIN_RDRAND16_STEP:
-      icode = CODE_FOR_rdrandhi_1;
-      mode0 = HImode;
+      mode = HImode;
       goto rdrand_step;
 
     case IX86_BUILTIN_RDRAND32_STEP:
-      icode = CODE_FOR_rdrandsi_1;
-      mode0 = SImode;
+      mode = SImode;
       goto rdrand_step;
 
     case IX86_BUILTIN_RDRAND64_STEP:
-      icode = CODE_FOR_rdranddi_1;
-      mode0 = DImode;
+      mode = DImode;
 
 rdrand_step:
       arg0 = CALL_EXPR_ARG (exp, 0);
@@ -11766,16 +11775,15 @@ rdrand_step:
 	  op1 = copy_addr_to_reg (op1);
 	}
 
-      op0 = gen_reg_rtx (mode0);
-      emit_insn (GEN_FCN (icode) (op0));
+      op0 = gen_reg_rtx (mode);
+      emit_insn (gen_rdrand (mode, op0));
 
-      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
+      emit_move_insn (gen_rtx_MEM (mode, op1), op0);
 
-      op1 = gen_reg_rtx (SImode);
-      emit_move_insn (op1, CONST1_RTX (SImode));
+      op1 = force_reg (SImode, const1_rtx);
 
       /* Emit SImode conditional move.  */
-      if (mode0 == HImode)
+      if (mode == HImode)
 	{
 	  if (TARGET_ZERO_EXTEND_WITH_AND
 	      && optimize_function_for_speed_p (cfun))
@@ -11792,7 +11800,7 @@ rdrand_step:
 	      emit_insn (gen_zero_extendhisi2 (op2, op0));
 	    }
 	}
-      else if (mode0 == SImode)
+      else if (mode == SImode)
 	op2 = op0;
       else
 	op2 = gen_rtx_SUBREG (SImode, op0, 0);
@@ -11808,18 +11816,15 @@ rdrand_step:
       return target;
 
     case IX86_BUILTIN_RDSEED16_STEP:
-      icode = CODE_FOR_rdseedhi_1;
-      mode0 = HImode;
+      mode = HImode;
       goto rdseed_step;
 
     case IX86_BUILTIN_RDSEED32_STEP:
-      icode = CODE_FOR_rdseedsi_1;
-      mode0 = SImode;
+      mode = SImode;
       goto rdseed_step;
 
     case IX86_BUILTIN_RDSEED64_STEP:
-      icode = CODE_FOR_rdseeddi_1;
-      mode0 = DImode;
+      mode = DImode;
 
 rdseed_step:
       arg0 = CALL_EXPR_ARG (exp, 0);
@@ -11830,10 +11835,10 @@ rdseed_step:
 	  op1 = copy_addr_to_reg (op1);
 	}
 
-      op0 = gen_reg_rtx (mode0);
-      emit_insn (GEN_FCN (icode) (op0));
+      op0 = gen_reg_rtx (mode);
+      emit_insn (gen_rdseed (mode, op0));
 
-      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
+      emit_move_insn (gen_rtx_MEM (mode, op1), op0);
 
       op2 = gen_reg_rtx (QImode);
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index bfc600c6a9c..09dcaa36cf1 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -14524,28 +14524,7 @@
    (set_attr "mode" "<MODE>")])
 
 ;; TBM instructions.
-(define_expand "tbm_bextri_<mode>"
-  [(parallel
-    [(set (match_operand:SWI48 0 "register_operand")
-	  (zero_extract:SWI48
-	    (match_operand:SWI48 1 "nonimmediate_operand")
-	    (match_operand 2 "const_0_to_255_operand" "N")
-	    (match_operand 3 "const_0_to_255_operand" "N")))
-     (clobber (reg:CC FLAGS_REG))])]
-  "TARGET_TBM"
-{
-  if (operands[2] == const0_rtx
-      || INTVAL (operands[3]) >= <MODE_SIZE> * BITS_PER_UNIT)
-    {
-      emit_move_insn (operands[0], const0_rtx);
-      DONE;
-    }
-  if (INTVAL (operands[2]) + INTVAL (operands[3])
-      > <MODE_SIZE> * BITS_PER_UNIT)
-    operands[2] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT - INTVAL (operands[3]));
-})
-
-(define_insn "*tbm_bextri_<mode>"
+(define_insn "@tbm_bextri_<mode>"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
         (zero_extract:SWI48
           (match_operand:SWI48 1 "nonimmediate_operand" "rm")
@@ -21174,7 +21153,7 @@
   [(set_attr "type" "other")
    (set_attr "prefix_extra" "2")])
 
-(define_insn "rdrand<mode>_1"
+(define_insn "@rdrand<mode>"
   [(set (match_operand:SWI248 0 "register_operand" "=r")
 	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRAND))
    (set (reg:CCC FLAGS_REG)
@@ -21184,7 +21163,7 @@
   [(set_attr "type" "other")
    (set_attr "prefix_extra" "1")])
 
-(define_insn "rdseed<mode>_1"
+(define_insn "@rdseed<mode>"
   [(set (match_operand:SWI248 0 "register_operand" "=r")
 	(unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDSEED))
    (set (reg:CCC FLAGS_REG)
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-1.c b/gcc/testsuite/gcc.target/i386/rdrand-1.c
index beec9f1b8aa..5eec19a7e72 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-1.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-1.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mrdrnd -dp" } */
-/* { dg-final { scan-assembler-times "rdrandhi_1" 1 } } */
+/* { dg-final { scan-assembler-times "rdrandhi" 1 } } */
 /* { dg-final { scan-assembler-times "\\*movsicc_noc" 1 } } */
 
 #include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-2.c b/gcc/testsuite/gcc.target/i386/rdrand-2.c
index ea8e9064953..a7173157d75 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-2.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-2.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mrdrnd -dp" } */
-/* { dg-final { scan-assembler-times "rdrandsi_1" 1 } } */
+/* { dg-final { scan-assembler-times "rdrandsi" 1 } } */
 /* { dg-final { scan-assembler-times "\\*movsicc_noc" 1 } } */
 
 #include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/rdrand-3.c b/gcc/testsuite/gcc.target/i386/rdrand-3.c
index a35fafe02cf..48b4ee25a27 100644
--- a/gcc/testsuite/gcc.target/i386/rdrand-3.c
+++ b/gcc/testsuite/gcc.target/i386/rdrand-3.c
@@ -1,6 +1,6 @@
 /* { dg-do compile { target { ! ia32 } } } */
 /* { dg-options "-O2 -mrdrnd -dp" } */
-/* { dg-final { scan-assembler-times "rdranddi_1" 1 } } */
+/* { dg-final { scan-assembler-times "rdranddi" 1 } } */
 /* { dg-final { scan-assembler-times "\\*movsicc_noc" 1 } } */
 
 #include <immintrin.h>
