[llvm] [DAG][X86] Bitfield insertion can combine into SHL + SHRD (PR #220182)

Pratyay Pande via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 03:31:22 PDT 2026


https://github.com/pratyaypande updated https://github.com/llvm/llvm-project/pull/220182

>From 41fe1c2b7923511710c8758a78d347ba63146b17 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Fri, 28 Aug 2026 01:25:02 +0530
Subject: [PATCH 01/20] Initial Combine implementation

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 49 +++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 3a66310ff1b3c..4e67db90b5b3d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53768,6 +53768,52 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
   return SDValue();
 }
 
+// Matches the following pattern:
+//
+//   (or (and X, HighBitsMask(C)), (srl Y, C)) --> (fshl (srl X, BW-C), Y, BW-C)
+static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
+										const X86Subtarget &Subtarget) {
+	using namespace SDPatternMatch;
+
+	N->dump();
+
+	// Bail if the OR is not disjoint or if SHLD is slow
+	if (!N->getFlags().hasDisjoint() || Subtarget.isSHLDSlow())
+		return SDValue();
+
+	EVT VT = N->getValueType(0);
+	APInt Mask;
+	uint64_t ShiftAmount;
+	SDValue X, Y;
+
+	bool Match = sd_match(N, 
+			m_Or( m_OneUse(m_And( m_Value(X), m_ConstInt(Mask))), 
+					 m_OneUse(m_Shl( m_Value(Y), m_ConstInt(ShiftAmount)))));
+
+	// Max bit-width of operands
+	uint64_t MaxMaskBitWidth = VT.getSizeInBits();
+
+	// Check for Mask and ShiftAmount
+	//
+	// (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
+	// so X must keep exactly the low ShiftAmount.
+	APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
+
+	bool Applicable = Match && (ShiftAmount > 0) 
+							&& (ShiftAmount < MaxMaskBitWidth)
+							&& (Mask == ExpectedMask);
+
+	if (!Applicable)
+		return SDValue();
+
+	uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
+	SDValue ShVal = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
+	SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShVal);
+	SDValue fin = DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShVal);
+
+	return fin;
+}
+
 static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
                          TargetLowering::DAGCombinerInfo &DCI,
                          const X86Subtarget &Subtarget) {
@@ -53830,6 +53876,9 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
   if (SDValue R = combineOrWithGF2P8AFFINEQB(N, dl, DAG, VT))
     return R;
 
+  if (SDValue R = combineDisjointORToSHLD(N, dl, DAG, Subtarget))
+  	  return R;
+
   if (DCI.isBeforeLegalizeOps())
     return SDValue();
 

>From f80151951e0b5b242762f776749e5bf3f9fb0030 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Mon, 31 Aug 2026 18:07:42 +0530
Subject: [PATCH 02/20] [DAG][X86] Do not bail if OR is not disjoint Removed
 debug statements

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 4e67db90b5b3d..728abe31e3ccb 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53775,10 +53775,8 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 										const X86Subtarget &Subtarget) {
 	using namespace SDPatternMatch;
 
-	N->dump();
-
-	// Bail if the OR is not disjoint or if SHLD is slow
-	if (!N->getFlags().hasDisjoint() || Subtarget.isSHLDSlow())
+	// Bail if SHLD is slow
+	if (Subtarget.isSHLDSlow())
 		return SDValue();
 
 	EVT VT = N->getValueType(0);

>From 94fba6273c53c94ae3231583df5cb9279d92b69d Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Mon, 31 Aug 2026 18:21:34 +0530
Subject: [PATCH 03/20] [DAG][X86] Bail early if pattern match fails Added
 descriptive comments

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 728abe31e3ccb..f05341162a0ca 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53784,10 +53784,15 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 	uint64_t ShiftAmount;
 	SDValue X, Y;
 
+	// Check for the following pattern:
+	//   (or (and X, HighBitsMask(C)), (srl Y, C))
 	bool Match = sd_match(N, 
 			m_Or( m_OneUse(m_And( m_Value(X), m_ConstInt(Mask))), 
 					 m_OneUse(m_Shl( m_Value(Y), m_ConstInt(ShiftAmount)))));
 
+	if (!Match)
+		return SDValue();
+
 	// Max bit-width of operands
 	uint64_t MaxMaskBitWidth = VT.getSizeInBits();
 
@@ -53797,9 +53802,8 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 	// so X must keep exactly the low ShiftAmount.
 	APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
 
-	bool Applicable = Match && (ShiftAmount > 0) 
-							&& (ShiftAmount < MaxMaskBitWidth)
-							&& (Mask == ExpectedMask);
+	bool Applicable = (ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth)
+										&& (Mask == ExpectedMask);
 
 	if (!Applicable)
 		return SDValue();

>From 29f7e7311a1edfdb0e88146b1285bba61f1c9438 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Mon, 31 Aug 2026 18:23:02 +0530
Subject: [PATCH 04/20] [DAG][X86][NFC] Cleaned up return statement

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f05341162a0ca..bf93ad4c64313 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53808,12 +53808,12 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 	if (!Applicable)
 		return SDValue();
 
+	LLVM_DEBUG(dbgs() << "The optimization is applicable.\n");
+
 	uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
 	SDValue ShVal = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
 	SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShVal);
-	SDValue fin = DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShVal);
-
-	return fin;
+	return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShVal);
 }
 
 static SDValue combineOr(SDNode *N, SelectionDAG &DAG,

>From 9afdc1138d7e1cf5e358824410e2c98eee73b810 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Mon, 31 Aug 2026 21:16:19 +0530
Subject: [PATCH 05/20] [DAG][X86] SHRD does not support 8--bit operands

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index bf93ad4c64313..b487e3a38dad3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53780,6 +53780,11 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 		return SDValue();
 
 	EVT VT = N->getValueType(0);
+
+	// SHRD does not suppport 8-bit operands
+	if (VT == MVT::i8)
+		return SDValue();
+
 	APInt Mask;
 	uint64_t ShiftAmount;
 	SDValue X, Y;

>From fec97cbf838a7d04d840638dcd6e51a25298c3c7 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 11:03:32 +0530
Subject: [PATCH 06/20] [DAG][X86] Renamed implementation to `combineORToSHRD`
 Added an assertion to check for `ISD::OR`. Updated comments to be a bit more
 descriptive Renamed variables

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b487e3a38dad3..8946904f9a92b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53768,12 +53768,13 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
   return SDValue();
 }
 
-// Matches the following pattern:
-//
-//   (or (and X, HighBitsMask(C)), (srl Y, C)) --> (fshl (srl X, BW-C), Y, BW-C)
-static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
+ 
+// Fold an OR with a masked destination and a left-shifted
+// source into a shift + double-precision shift (SHRD):
+static SDValue combineORToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 										const X86Subtarget &Subtarget) {
 	using namespace SDPatternMatch;
+	assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
 
 	// Bail if SHLD is slow
 	if (Subtarget.isSHLDSlow())
@@ -53816,9 +53817,9 @@ static SDValue combineDisjointORToSHLD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 	LLVM_DEBUG(dbgs() << "The optimization is applicable.\n");
 
 	uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
-	SDValue ShVal = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
-	SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShVal);
-	return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShVal);
+	SDValue ShAConst = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
+	SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShAConst);
+	return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShAConst);
 }
 
 static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
@@ -53883,7 +53884,7 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
   if (SDValue R = combineOrWithGF2P8AFFINEQB(N, dl, DAG, VT))
     return R;
 
-  if (SDValue R = combineDisjointORToSHLD(N, dl, DAG, Subtarget))
+  if (SDValue R = combineORToSHRD(N, dl, DAG, Subtarget))
   	  return R;
 
   if (DCI.isBeforeLegalizeOps())

>From 82068c80b065acf674c360bdd70c32a274a79d7c Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 11:38:13 +0530
Subject: [PATCH 07/20] [DAG][X86][NFC] Rename impl. method to something more
 descriptive

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8946904f9a92b..5e80c125b9757 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53771,7 +53771,7 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
  
 // Fold an OR with a masked destination and a left-shifted
 // source into a shift + double-precision shift (SHRD):
-static SDValue combineORToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
+static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 										const X86Subtarget &Subtarget) {
 	using namespace SDPatternMatch;
 	assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
@@ -53884,7 +53884,7 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
   if (SDValue R = combineOrWithGF2P8AFFINEQB(N, dl, DAG, VT))
     return R;
 
-  if (SDValue R = combineORToSHRD(N, dl, DAG, Subtarget))
+  if (SDValue R = combineOrOnSHLToSHRD(N, dl, DAG, Subtarget))
   	  return R;
 
   if (DCI.isBeforeLegalizeOps())

>From cf1bf80e32b0635e144a7e673194875ff1b0a155 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 11:50:55 +0530
Subject: [PATCH 08/20] [DAG][X86] Tests for `combineOrOnSHLToSHRD` in
 `X86ISelLowering.cpp`

---
 llvm/test/CodeGen/X86/insert-bitfield.ll | 349 +++++++++++++++++++++++
 1 file changed, 349 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/insert-bitfield.ll

diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll
new file mode 100644
index 0000000000000..c51c0c2a2878f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/insert-bitfield.ll
@@ -0,0 +1,349 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=X64
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+slow-shld | FileCheck %s --check-prefixes=X64-SLOW
+
+define i64 @insert_10_i64(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_10_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+define i64 @insert_10_i64_disjoint(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_10_i64_disjoint:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64_disjoint:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or disjoint i64 %shl, %and
+  ret i64 %or
+}
+
+; Commuted operands.
+define i64 @insert_10_i64_commute(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_10_i64_commute:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64_commute:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or i64 %and, %shl
+  ret i64 %or
+}
+
+define i64 @insert_33_i64(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_33_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $33, %rax
+; X64-NEXT:    shrdq $33, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_33_i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    andl $2147483647, %edi # imm = 0x7FFFFFFF
+; X64-SLOW-NEXT:    shlq $31, %rsi
+; X64-SLOW-NEXT:    leaq (%rsi,%rdi), %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 2147483647
+  %shl = shl i64 %b, 31
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+define i64 @insert_1_i64(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_1_i64:
+; X64:       # %bb.0:
+; X64-NEXT:    leaq (%rdi,%rdi), %rax
+; X64-NEXT:    shrdq $1, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_1_i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $9223372036854775807, %rax # imm = 0x7FFFFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $63, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 9223372036854775807
+  %shl = shl i64 %b, 63
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; i32 inputs and mask
+define i32 @insert_10_i32(i32 %a, i32 %b) nounwind {
+; X64-LABEL: insert_10_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    shll $10, %eax
+; X64-NEXT:    shrdl $10, %esi, %eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i32:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    andl $4194303, %edi # imm = 0x3FFFFF
+; X64-SLOW-NEXT:    shll $22, %esi
+; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    retq
+  %and = and i32 %a, 4194303
+  %shl = shl i32 %b, 22
+  %or = or i32 %shl, %and
+  ret i32 %or
+}
+
+; i16 inputs and mask
+define i16 @insert_6_i16(i16 %a, i16 %b) nounwind {
+; X64-LABEL: insert_6_i16:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    shll $6, %eax
+; X64-NEXT:    shrdw $6, %si, %ax
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_6_i16:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    andl $1023, %edi # imm = 0x3FF
+; X64-SLOW-NEXT:    shll $10, %esi
+; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-SLOW-NEXT:    retq
+  %and = and i16 %a, 1023
+  %shl = shl i16 %b, 10
+  %or = or i16 %shl, %and
+  ret i16 %or
+}
+
+; Negative test for i8: SHRD does not accept an 8-bit operand
+define i8 @insert_3_i8(i8 %a, i8 %b) nounwind {
+; X64-LABEL: insert_3_i8:
+; X64:       # %bb.0:
+; X64-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-NEXT:    andb $31, %dil
+; X64-NEXT:    shlb $5, %sil
+; X64-NEXT:    leal (%rsi,%rdi), %eax
+; X64-NEXT:    # kill: def $al killed $al killed $eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_3_i8:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    andb $31, %dil
+; X64-SLOW-NEXT:    shlb $5, %sil
+; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    # kill: def $al killed $al killed $eax
+; X64-SLOW-NEXT:    retq
+  %and = and i8 %a, 31
+  %shl = shl i8 %b, 5
+  %or = or i8 %shl, %and
+  ret i8 %or
+}
+
+; Negative test: the mask and the shift amount describe different split points,
+; so the result is not a plain concatenation of A and B.
+define i64 @mask_shift_mismatch(i64 %a, i64 %b) nounwind {
+; X64-LABEL: mask_shift_mismatch:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-NEXT:    andq %rdi, %rax
+; X64-NEXT:    shlq $55, %rsi
+; X64-NEXT:    orq %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: mask_shift_mismatch:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $55, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 55
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; Negative test: the mask keeps too many bits, so the shifted-in value would be
+; OR'd on top of bits of A instead of replacing them.
+define i64 @mask_too_wide(i64 %a, i64 %b) nounwind {
+; X64-LABEL: mask_too_wide:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $36028797018963967, %rax # imm = 0x7FFFFFFFFFFFFF
+; X64-NEXT:    andq %rdi, %rax
+; X64-NEXT:    shlq $54, %rsi
+; X64-NEXT:    orq %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: mask_too_wide:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $36028797018963967, %rax # imm = 0x7FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 36028797018963967
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; Negative test: extra use of the AND means the mask has to be materialized
+; anyway, so folding would only add instructions.
+define i64 @multi_use_and(i64 %a, i64 %b, ptr %p) nounwind {
+; X64-LABEL: multi_use_and:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-NEXT:    andq %rdi, %rax
+; X64-NEXT:    movq %rax, (%rdx)
+; X64-NEXT:    shlq $54, %rsi
+; X64-NEXT:    orq %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: multi_use_and:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    movq %rax, (%rdx)
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  store i64 %and, ptr %p
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; Negative test: extra use of the SHL.
+define i64 @multi_use_shl(i64 %a, i64 %b, ptr %p) nounwind {
+; X64-LABEL: multi_use_shl:
+; X64:       # %bb.0:
+; X64-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-NEXT:    andq %rdi, %rax
+; X64-NEXT:    shlq $54, %rsi
+; X64-NEXT:    movq %rsi, (%rdx)
+; X64-NEXT:    orq %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: multi_use_shl:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    movq %rsi, (%rdx)
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  store i64 %shl, ptr %p
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; Slow-SHLD targets still fold when optimizing for size.
+define i64 @insert_10_i64_optsize(i64 %a, i64 %b) nounwind optsize {
+; X64-LABEL: insert_10_i64_optsize:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64_optsize:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+define i64 @insert_10_i64_minsize(i64 %a, i64 %b) nounwind minsize {
+; X64-LABEL: insert_10_i64_minsize:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64_minsize:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+; A loaded destination operand.
+define i64 @insert_10_i64_load(ptr %p, i64 %b) nounwind {
+; X64-LABEL: insert_10_i64_load:
+; X64:       # %bb.0:
+; X64-NEXT:    movq (%rdi), %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+; 
+; X64-SLOW-LABEL: insert_10_i64_load:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq (%rdi), %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+  %a = load i64, ptr %p
+  %and = and i64 %a, 18014398509481983
+  %shl = shl i64 %b, 54
+  %or = or i64 %shl, %and
+  ret i64 %or
+}

>From 04a111d653895c01a6eb05c082be6ca16637b2ab Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 12:40:49 +0530
Subject: [PATCH 09/20] [NFC] Remove extra line

---
 llvm/test/CodeGen/X86/insert-bitfield.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll
index c51c0c2a2878f..54e6027c6a105 100644
--- a/llvm/test/CodeGen/X86/insert-bitfield.ll
+++ b/llvm/test/CodeGen/X86/insert-bitfield.ll
@@ -333,7 +333,7 @@ define i64 @insert_10_i64_load(ptr %p, i64 %b) nounwind {
 ; X64-NEXT:    shlq $10, %rax
 ; X64-NEXT:    shrdq $10, %rsi, %rax
 ; X64-NEXT:    retq
-; 
+;
 ; X64-SLOW-LABEL: insert_10_i64_load:
 ; X64-SLOW:       # %bb.0:
 ; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF

>From 8c2aa26aeaecf065d985e77bec436a29af567ab0 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 12:43:56 +0530
Subject: [PATCH 10/20] [DAG][X86] Do not combine multi-use AND and SHL They do
 not result in more performant code

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 5e80c125b9757..e93bafb546b12 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53792,8 +53792,10 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
 
 	// Check for the following pattern:
 	//   (or (and X, HighBitsMask(C)), (srl Y, C))
-	bool Match = sd_match(N, 
-			m_Or( m_OneUse(m_And( m_Value(X), m_ConstInt(Mask))), 
+	// Do not combine if there are multi-use AND and OR.
+	// It does not result in more performant code.
+	bool Match = sd_match(N,
+			m_Or( m_OneUse(m_And( m_Value(X), m_ConstInt(Mask))),
 					 m_OneUse(m_Shl( m_Value(Y), m_ConstInt(ShiftAmount)))));
 
 	if (!Match)

>From 920683bab4c6cec85dbb6262db0ec271133f6d99 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 12:58:34 +0530
Subject: [PATCH 11/20] [DAG][X86] clang-format and remove logging

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 77 ++++++++++++-------------
 1 file changed, 37 insertions(+), 40 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 74f79b448ebc4..da1030fc57394 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53859,60 +53859,57 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
   return SDValue();
 }
 
- 
 // Fold an OR with a masked destination and a left-shifted
 // source into a shift + double-precision shift (SHRD):
 static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
-										const X86Subtarget &Subtarget) {
-	using namespace SDPatternMatch;
-	assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
-
-	// Bail if SHLD is slow
-	if (Subtarget.isSHLDSlow())
-		return SDValue();
+                                    const X86Subtarget &Subtarget) {
+  using namespace SDPatternMatch;
+  assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
 
-	EVT VT = N->getValueType(0);
+  // Bail if SHLD is slow
+  if (Subtarget.isSHLDSlow())
+    return SDValue();
 
-	// SHRD does not suppport 8-bit operands
-	if (VT == MVT::i8)
-		return SDValue();
+  EVT VT = N->getValueType(0);
 
-	APInt Mask;
-	uint64_t ShiftAmount;
-	SDValue X, Y;
+  // SHRD does not suppport 8-bit operands
+  if (VT == MVT::i8)
+    return SDValue();
 
-	// Check for the following pattern:
-	//   (or (and X, HighBitsMask(C)), (srl Y, C))
-	// Do not combine if there are multi-use AND and OR.
-	// It does not result in more performant code.
-	bool Match = sd_match(N,
-			m_Or( m_OneUse(m_And( m_Value(X), m_ConstInt(Mask))),
-					 m_OneUse(m_Shl( m_Value(Y), m_ConstInt(ShiftAmount)))));
+  APInt Mask;
+  uint64_t ShiftAmount;
+  SDValue X, Y;
 
-	if (!Match)
-		return SDValue();
+  // Check for the following pattern:
+  //   (or (and X, HighBitsMask(C)), (srl Y, C))
+  // Do not combine if there are multi-use AND and OR.
+  // It does not result in more performant code.
+  bool Match =
+      sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
+                       m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount)))));
 
-	// Max bit-width of operands
-	uint64_t MaxMaskBitWidth = VT.getSizeInBits();
+  if (!Match)
+    return SDValue();
 
-	// Check for Mask and ShiftAmount
-	//
-	// (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
-	// so X must keep exactly the low ShiftAmount.
-	APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
+  // Max bit-width of operands
+  uint64_t MaxMaskBitWidth = VT.getSizeInBits();
 
-	bool Applicable = (ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth)
-										&& (Mask == ExpectedMask);
+  // Check for Mask and ShiftAmount
+  //
+  // (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
+  // so X must keep exactly the low ShiftAmount.
+  APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
 
-	if (!Applicable)
-		return SDValue();
+  bool Applicable = (ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth) &&
+                    (Mask == ExpectedMask);
 
-	LLVM_DEBUG(dbgs() << "The optimization is applicable.\n");
+  if (!Applicable)
+    return SDValue();
 
-	uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
-	SDValue ShAConst = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
-	SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShAConst);
-	return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShAConst);
+  uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
+  SDValue ShAConst = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
+  SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShAConst);
+  return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShAConst);
 }
 
 static SDValue combineOr(SDNode *N, SelectionDAG &DAG,

>From c82ebcd335a3af9983793cdf2eabe0810a1498ed Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 16:41:12 +0530
Subject: [PATCH 12/20] [DAG][X86] Combine to SHRD if optimizing for code size
 Combine runs even if SHLD is slow only if we are optimizing for code size.
 Updated tests

---
 llvm/lib/Target/X86/X86ISelLowering.cpp  |  8 +++++---
 llvm/test/CodeGen/X86/insert-bitfield.ll | 14 ++++++--------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index da1030fc57394..b667351fe6b04 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53866,9 +53866,11 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
   using namespace SDPatternMatch;
   assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
 
-  // Bail if SHLD is slow
-  if (Subtarget.isSHLDSlow())
-    return SDValue();
+  // If optimizing for code size, run irrespective of slow SHLD.
+  // If not optimizing for code size and SHLD is slow, then bail.
+  bool IsOptSize = DAG.getMachineFunction().getFunction().hasOptSize();
+  if (!IsOptSize && Subtarget.isSHLDSlow())
+      return SDValue();
 
   EVT VT = N->getValueType(0);
 
diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll
index 54e6027c6a105..4d78d1afc9fb1 100644
--- a/llvm/test/CodeGen/X86/insert-bitfield.ll
+++ b/llvm/test/CodeGen/X86/insert-bitfield.ll
@@ -293,10 +293,9 @@ define i64 @insert_10_i64_optsize(i64 %a, i64 %b) nounwind optsize {
 ;
 ; X64-SLOW-LABEL: insert_10_i64_optsize:
 ; X64-SLOW:       # %bb.0:
-; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
-; X64-SLOW-NEXT:    andq %rdi, %rax
-; X64-SLOW-NEXT:    shlq $54, %rsi
-; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    movq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $10, %rax
+; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
@@ -314,10 +313,9 @@ define i64 @insert_10_i64_minsize(i64 %a, i64 %b) nounwind minsize {
 ;
 ; X64-SLOW-LABEL: insert_10_i64_minsize:
 ; X64-SLOW:       # %bb.0:
-; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
-; X64-SLOW-NEXT:    andq %rdi, %rax
-; X64-SLOW-NEXT:    shlq $54, %rsi
-; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    movq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $10, %rax
+; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54

>From ef459526b0272e3362b2a1bb9e90763c67a86178 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Tue, 1 Sep 2026 16:41:12 +0530
Subject: [PATCH 13/20] [DAG][X86] Combine to SHRD if optimizing for code size
 Combine runs even if SHLD is slow only if we are optimizing for code size.
 Updated tests

---
 llvm/lib/Target/X86/X86ISelLowering.cpp  |  8 +++++---
 llvm/test/CodeGen/X86/insert-bitfield.ll | 14 ++++++--------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index da1030fc57394..b667351fe6b04 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53866,9 +53866,11 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
   using namespace SDPatternMatch;
   assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
 
-  // Bail if SHLD is slow
-  if (Subtarget.isSHLDSlow())
-    return SDValue();
+  // If optimizing for code size, run irrespective of slow SHLD.
+  // If not optimizing for code size and SHLD is slow, then bail.
+  bool IsOptSize = DAG.getMachineFunction().getFunction().hasOptSize();
+  if (!IsOptSize && Subtarget.isSHLDSlow())
+      return SDValue();
 
   EVT VT = N->getValueType(0);
 
diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll
index 54e6027c6a105..4d78d1afc9fb1 100644
--- a/llvm/test/CodeGen/X86/insert-bitfield.ll
+++ b/llvm/test/CodeGen/X86/insert-bitfield.ll
@@ -293,10 +293,9 @@ define i64 @insert_10_i64_optsize(i64 %a, i64 %b) nounwind optsize {
 ;
 ; X64-SLOW-LABEL: insert_10_i64_optsize:
 ; X64-SLOW:       # %bb.0:
-; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
-; X64-SLOW-NEXT:    andq %rdi, %rax
-; X64-SLOW-NEXT:    shlq $54, %rsi
-; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    movq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $10, %rax
+; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
@@ -314,10 +313,9 @@ define i64 @insert_10_i64_minsize(i64 %a, i64 %b) nounwind minsize {
 ;
 ; X64-SLOW-LABEL: insert_10_i64_minsize:
 ; X64-SLOW:       # %bb.0:
-; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
-; X64-SLOW-NEXT:    andq %rdi, %rax
-; X64-SLOW-NEXT:    shlq $54, %rsi
-; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    movq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $10, %rax
+; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54

>From a8160fde3f01b479e52b9dfb38890142cc18309c Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Fri, 4 Sep 2026 13:33:50 +0530
Subject: [PATCH 14/20] [DAG][X86][NFC] Fix clang-format warnings

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 23d3932b9d55d..7265f76a394f6 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53894,7 +53894,7 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
   // If not optimizing for code size and SHLD is slow, then bail.
   bool IsOptSize = DAG.getMachineFunction().getFunction().hasOptSize();
   if (!IsOptSize && Subtarget.isSHLDSlow())
-      return SDValue();
+    return SDValue();
 
   EVT VT = N->getValueType(0);
 
@@ -54001,7 +54001,7 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
     return R;
 
   if (SDValue R = combineOrOnSHLToSHRD(N, dl, DAG, Subtarget))
-  	  return R;
+    return R;
 
   if (DCI.isBeforeLegalizeOps())
     return SDValue();

>From 964c4c713fd2d7561ba1028a2fee100b1be8e773 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Fri, 4 Sep 2026 13:39:45 +0530
Subject: [PATCH 15/20] [DAG][X86][NFC] Embed `sd_match` in if-statement

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7265f76a394f6..e6d3678916be4 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53910,11 +53910,8 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
   //   (or (and X, HighBitsMask(C)), (srl Y, C))
   // Do not combine if there are multi-use AND and OR.
   // It does not result in more performant code.
-  bool Match =
-      sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
-                       m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount)))));
-
-  if (!Match)
+  if (!sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
+                        m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount))))))
     return SDValue();
 
   // Max bit-width of operands

>From f86b42bda651c71ebb6de93c81385febe54b13eb Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Fri, 4 Sep 2026 13:41:27 +0530
Subject: [PATCH 16/20] [DAG][X86][NFC] Remove assert for OR

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index e6d3678916be4..8b69fbe8c7d71 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53888,7 +53888,6 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
 static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
                                     const X86Subtarget &Subtarget) {
   using namespace SDPatternMatch;
-  assert(N->getOpcode() == ISD::OR && "Invalid Node. Expected OR.");
 
   // If optimizing for code size, run irrespective of slow SHLD.
   // If not optimizing for code size and SHLD is slow, then bail.

>From 45fd6c3d0f3ce4ac72978f3f0202db76e96c02a2 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Fri, 4 Sep 2026 13:58:03 +0530
Subject: [PATCH 17/20] [DAG][X86][NFC] Embed Applicability check in
 if-statement

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8b69fbe8c7d71..5566ecac3f426 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53922,10 +53922,8 @@ static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
   // so X must keep exactly the low ShiftAmount.
   APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
 
-  bool Applicable = (ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth) &&
-                    (Mask == ExpectedMask);
-
-  if (!Applicable)
+  if (!((ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth) &&
+        (Mask == ExpectedMask)))
     return SDValue();
 
   uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;

>From abe2bfbf2beb88ade7a90202a2fb12e22b9546b9 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Thu, 10 Sep 2026 15:31:51 +0530
Subject: [PATCH 18/20] [DAGCombiner][X86] Move OR to Funnel Shift combiner to
 DAGCombiner

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 41 +++++++++++++++
 llvm/lib/Target/X86/X86ISelLowering.cpp       | 52 -------------------
 2 files changed, 41 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 733d0eb9baa40..2d707518dce74 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -8837,6 +8837,43 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1,
   return SDValue();
 }
 
+// Fold an OR with a masked destination and a left-shifted
+// source into a shift + double-precision shift (SHRD):
+static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG) {
+  EVT VT = N->getValueType(0);
+
+  APInt Mask;
+  uint64_t ShiftAmount;
+  SDValue X, Y;
+
+  // Check for the following pattern:
+  //   (or (and X, HighBitsMask(C)), (srl Y, C))
+  // Do not combine if there are multi-use AND and OR.
+  // It does not result in more performant code.
+  if (!sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
+                        m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount))))))
+    return SDValue();
+
+  // Max bit-width of operands
+  uint64_t MaxMaskBitWidth = VT.getScalarSizeInBits();
+
+  // Check for Mask and ShiftAmount
+  //
+  // (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
+  // so X must keep exactly the low ShiftAmount.
+  APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
+
+  if (!((ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth) &&
+        (Mask == ExpectedMask)))
+    return SDValue();
+
+  uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
+  SDValue ShAConst = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
+  SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShAConst);
+
+  return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShAConst);
+}
+
 SDValue DAGCombiner::visitOR(SDNode *N) {
   SDValue N0 = N->getOperand(0);
   SDValue N1 = N->getOperand(1);
@@ -9036,6 +9073,10 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
   if (SDValue Load = MatchLoadCombine(N))
     return Load;
 
+  if (Level == CombineLevel::BeforeLegalizeTypes)
+    if (SDValue Res = combineOrOnSHLToSHRD(N, DL, DAG))
+      return Res;
+
   // Simplify the operands using demanded-bits information.
   if (SimplifyDemandedBits(SDValue(N, 0)))
     return SDValue(N, 0);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 713bae0fe753f..d41405645cc34 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -54096,55 +54096,6 @@ static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
   return SDValue();
 }
 
-// Fold an OR with a masked destination and a left-shifted
-// source into a shift + double-precision shift (SHRD):
-static SDValue combineOrOnSHLToSHRD(SDNode *N, SDLoc &DL, SelectionDAG &DAG,
-                                    const X86Subtarget &Subtarget) {
-  using namespace SDPatternMatch;
-
-  // If optimizing for code size, run irrespective of slow SHLD.
-  // If not optimizing for code size and SHLD is slow, then bail.
-  bool IsOptSize = DAG.getMachineFunction().getFunction().hasOptSize();
-  if (!IsOptSize && Subtarget.isSHLDSlow())
-    return SDValue();
-
-  EVT VT = N->getValueType(0);
-
-  // SHRD does not suppport 8-bit operands
-  if (VT == MVT::i8)
-    return SDValue();
-
-  APInt Mask;
-  uint64_t ShiftAmount;
-  SDValue X, Y;
-
-  // Check for the following pattern:
-  //   (or (and X, HighBitsMask(C)), (srl Y, C))
-  // Do not combine if there are multi-use AND and OR.
-  // It does not result in more performant code.
-  if (!sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
-                        m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount))))))
-    return SDValue();
-
-  // Max bit-width of operands
-  uint64_t MaxMaskBitWidth = VT.getSizeInBits();
-
-  // Check for Mask and ShiftAmount
-  //
-  // (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
-  // so X must keep exactly the low ShiftAmount.
-  APInt ExpectedMask = APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount);
-
-  if (!((ShiftAmount > 0) && (ShiftAmount < MaxMaskBitWidth) &&
-        (Mask == ExpectedMask)))
-    return SDValue();
-
-  uint64_t InvShAmt = MaxMaskBitWidth - ShiftAmount;
-  SDValue ShAConst = DAG.getShiftAmountConstant(InvShAmt, VT, DL);
-  SDValue SHLVal = DAG.getNode(ISD::SHL, DL, VT, X, ShAConst);
-  return DAG.getNode(ISD::FSHR, DL, VT, Y, SHLVal, ShAConst);
-}
-
 static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
                          TargetLowering::DAGCombinerInfo &DCI,
                          const X86Subtarget &Subtarget) {
@@ -54207,9 +54158,6 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
   if (SDValue R = combineOrWithGF2P8AFFINEQB(N, dl, DAG, VT))
     return R;
 
-  if (SDValue R = combineOrOnSHLToSHRD(N, dl, DAG, Subtarget))
-    return R;
-
   if (DCI.isBeforeLegalizeOps())
     return SDValue();
 

>From 41ec16c464ab80ac480252f7a5f03e1b9cc703ec Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Thu, 10 Sep 2026 15:43:10 +0530
Subject: [PATCH 19/20] [X86] Expand funnel shift on SHL into OR on SHL and AND

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 38 ++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d41405645cc34..c62321292d10f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32285,8 +32285,44 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget,
     return DAG.getZExtOrTrunc(Res, DL, VT);
   }
 
-  if (VT == MVT::i8 || ExpandFunnel)
+  // If expanding the funnel shift is required OR the value type is unsupported
+  if (VT == MVT::i8 || ExpandFunnel) {
+    // Proceed if one operand is the result of an ISD::SHL or the node is
+    // MVT::i8
+    if (Op1.getOpcode() == ISD::SHL && isa<ConstantSDNode>(Amt.getNode())) {
+
+      ConstantSDNode *C = dyn_cast<ConstantSDNode>(Amt.getNode());
+      SDValue SHLOperandShiftAmount = Op1->getOperand(1);
+      APInt InvMaskWidth = C->getAPIntValue();
+
+      if (ConstantSDNode *EC =
+              dyn_cast<ConstantSDNode>(SHLOperandShiftAmount.getNode())) {
+        APInt ExpectedShiftAmount = EC->getAPIntValue();
+
+        // Check if the shift amounts match.
+        if (ExpectedShiftAmount != InvMaskWidth)
+          return SDValue();
+      }
+
+      APInt MaskWidth = EltSizeInBits - InvMaskWidth;
+      uint64_t ShiftAmount = MaskWidth.getZExtValue();
+      SDValue SHLOperand = Op1.getOperand(0);
+
+      APInt Mask = APInt::getLowBitsSet(EltSizeInBits, ShiftAmount);
+
+      SDValue MaskBitNum = DAG.getShiftAmountConstant(
+          ShiftAmount, SHLOperand.getValueType(), DL);
+      SDValue MaskNode = DAG.getConstant(Mask, DL, VT);
+      SDValue AndMask = DAG.getNode(ISD::AND, DL, SHLOperand.getValueType(),
+                                    SHLOperand, MaskNode);
+      SDValue SHL =
+          DAG.getNode(ISD::SHL, DL, Op0.getValueType(), Op0, MaskBitNum);
+      SDValue ORVal = DAG.getNode(ISD::OR, DL, VT, AndMask, SHL);
+
+      return ORVal;
+    }
     return SDValue();
+  }
 
   // i16 needs to modulo the shift amount, but i32/i64 have implicit modulo.
   if (VT == MVT::i16) {

>From 73aa972ad86ad5571c9aa7a47daf7c5ae63cc275 Mon Sep 17 00:00:00 2001
From: Pratyay Pande <pratyaypande at outlook.com>
Date: Thu, 10 Sep 2026 15:49:16 +0530
Subject: [PATCH 20/20] [DAG][X86] Add tests for `llvm.fshr.*` and vector types

---
 llvm/test/CodeGen/X86/insert-bitfield.ll | 1287 +++++++++++++++++++++-
 1 file changed, 1277 insertions(+), 10 deletions(-)

diff --git a/llvm/test/CodeGen/X86/insert-bitfield.ll b/llvm/test/CodeGen/X86/insert-bitfield.ll
index 4d78d1afc9fb1..ddb0dc85d89a6 100644
--- a/llvm/test/CodeGen/X86/insert-bitfield.ll
+++ b/llvm/test/CodeGen/X86/insert-bitfield.ll
@@ -1,6 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=X64
 ; RUN: llc < %s -mtriple=x86_64-- -mattr=+slow-shld | FileCheck %s --check-prefixes=X64-SLOW
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=X64-AVX2
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512bw,+avx512vl | FileCheck %s --check-prefixes=X64-AVX512
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512vbmi2,+avx512vl | FileCheck %s --check-prefixes=X64-AVX512-BMI2
 
 define i64 @insert_10_i64(i64 %a, i64 %b) nounwind {
 ; X64-LABEL: insert_10_i64:
@@ -17,6 +20,27 @@ define i64 @insert_10_i64(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or i64 %shl, %and
@@ -38,6 +62,27 @@ define i64 @insert_10_i64_disjoint(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_disjoint:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_disjoint:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_disjoint:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or disjoint i64 %shl, %and
@@ -60,6 +105,27 @@ define i64 @insert_10_i64_commute(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_commute:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_commute:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_commute:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or i64 %and, %shl
@@ -76,10 +142,31 @@ define i64 @insert_33_i64(i64 %a, i64 %b) nounwind {
 ;
 ; X64-SLOW-LABEL: insert_33_i64:
 ; X64-SLOW:       # %bb.0:
-; X64-SLOW-NEXT:    andl $2147483647, %edi # imm = 0x7FFFFFFF
 ; X64-SLOW-NEXT:    shlq $31, %rsi
-; X64-SLOW-NEXT:    leaq (%rsi,%rdi), %rax
+; X64-SLOW-NEXT:    andl $2147483647, %edi # imm = 0x7FFFFFFF
+; X64-SLOW-NEXT:    leaq (%rdi,%rsi), %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_33_i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $33, %rax
+; X64-AVX2-NEXT:    shrdq $33, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_33_i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $33, %rax
+; X64-AVX512-NEXT:    shrdq $33, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_33_i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $33, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $33, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 2147483647
   %shl = shl i64 %b, 31
   %or = or i64 %shl, %and
@@ -100,6 +187,24 @@ define i64 @insert_1_i64(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $63, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_1_i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    leaq (%rdi,%rdi), %rax
+; X64-AVX2-NEXT:    shrdq $1, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_1_i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    leaq (%rdi,%rdi), %rax
+; X64-AVX512-NEXT:    shrdq $1, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_1_i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    leaq (%rdi,%rdi), %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $1, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 9223372036854775807
   %shl = shl i64 %b, 63
   %or = or i64 %shl, %and
@@ -119,10 +224,31 @@ define i32 @insert_10_i32(i32 %a, i32 %b) nounwind {
 ; X64-SLOW:       # %bb.0:
 ; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
 ; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-SLOW-NEXT:    andl $4194303, %edi # imm = 0x3FFFFF
 ; X64-SLOW-NEXT:    shll $22, %esi
-; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    andl $4194303, %edi # imm = 0x3FFFFF
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i32:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movl %edi, %eax
+; X64-AVX2-NEXT:    shll $10, %eax
+; X64-AVX2-NEXT:    shrdl $10, %esi, %eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i32:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movl %edi, %eax
+; X64-AVX512-NEXT:    shll $10, %eax
+; X64-AVX512-NEXT:    shrdl $10, %esi, %eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i32:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movl %edi, %eax
+; X64-AVX512-BMI2-NEXT:    shll $10, %eax
+; X64-AVX512-BMI2-NEXT:    shrdl $10, %esi, %eax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i32 %a, 4194303
   %shl = shl i32 %b, 22
   %or = or i32 %shl, %and
@@ -143,11 +269,35 @@ define i16 @insert_6_i16(i16 %a, i16 %b) nounwind {
 ; X64-SLOW:       # %bb.0:
 ; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
 ; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-SLOW-NEXT:    andl $1023, %edi # imm = 0x3FF
 ; X64-SLOW-NEXT:    shll $10, %esi
-; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    andl $1023, %edi # imm = 0x3FF
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
 ; X64-SLOW-NEXT:    # kill: def $ax killed $ax killed $eax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_6_i16:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movl %edi, %eax
+; X64-AVX2-NEXT:    shll $6, %eax
+; X64-AVX2-NEXT:    shrdw $6, %si, %ax
+; X64-AVX2-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_6_i16:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movl %edi, %eax
+; X64-AVX512-NEXT:    shll $6, %eax
+; X64-AVX512-NEXT:    shrdw $6, %si, %ax
+; X64-AVX512-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_6_i16:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movl %edi, %eax
+; X64-AVX512-BMI2-NEXT:    shll $6, %eax
+; X64-AVX512-BMI2-NEXT:    shrdw $6, %si, %ax
+; X64-AVX512-BMI2-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i16 %a, 1023
   %shl = shl i16 %b, 10
   %or = or i16 %shl, %and
@@ -160,9 +310,9 @@ define i8 @insert_3_i8(i8 %a, i8 %b) nounwind {
 ; X64:       # %bb.0:
 ; X64-NEXT:    # kill: def $esi killed $esi def $rsi
 ; X64-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-NEXT:    andb $31, %dil
 ; X64-NEXT:    shlb $5, %sil
-; X64-NEXT:    leal (%rsi,%rdi), %eax
+; X64-NEXT:    andb $31, %dil
+; X64-NEXT:    leal (%rdi,%rsi), %eax
 ; X64-NEXT:    # kill: def $al killed $al killed $eax
 ; X64-NEXT:    retq
 ;
@@ -170,11 +320,41 @@ define i8 @insert_3_i8(i8 %a, i8 %b) nounwind {
 ; X64-SLOW:       # %bb.0:
 ; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
 ; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
-; X64-SLOW-NEXT:    andb $31, %dil
 ; X64-SLOW-NEXT:    shlb $5, %sil
-; X64-SLOW-NEXT:    leal (%rsi,%rdi), %eax
+; X64-SLOW-NEXT:    andb $31, %dil
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
 ; X64-SLOW-NEXT:    # kill: def $al killed $al killed $eax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_3_i8:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX2-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX2-NEXT:    shlb $5, %sil
+; X64-AVX2-NEXT:    andb $31, %dil
+; X64-AVX2-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX2-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_3_i8:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX512-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX512-NEXT:    shlb $5, %sil
+; X64-AVX512-NEXT:    andb $31, %dil
+; X64-AVX512-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX512-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_3_i8:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX512-BMI2-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX512-BMI2-NEXT:    shlb $5, %sil
+; X64-AVX512-BMI2-NEXT:    andb $31, %dil
+; X64-AVX512-BMI2-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX512-BMI2-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i8 %a, 31
   %shl = shl i8 %b, 5
   %or = or i8 %shl, %and
@@ -199,6 +379,30 @@ define i64 @mask_shift_mismatch(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $55, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: mask_shift_mismatch:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX2-NEXT:    andq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $55, %rsi
+; X64-AVX2-NEXT:    orq %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: mask_shift_mismatch:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-NEXT:    andq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $55, %rsi
+; X64-AVX512-NEXT:    orq %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: mask_shift_mismatch:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-BMI2-NEXT:    andq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $55, %rsi
+; X64-AVX512-BMI2-NEXT:    orq %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 55
   %or = or i64 %shl, %and
@@ -223,6 +427,30 @@ define i64 @mask_too_wide(i64 %a, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: mask_too_wide:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movabsq $36028797018963967, %rax # imm = 0x7FFFFFFFFFFFFF
+; X64-AVX2-NEXT:    andq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $54, %rsi
+; X64-AVX2-NEXT:    orq %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: mask_too_wide:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movabsq $36028797018963967, %rax # imm = 0x7FFFFFFFFFFFFF
+; X64-AVX512-NEXT:    andq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $54, %rsi
+; X64-AVX512-NEXT:    orq %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: mask_too_wide:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movabsq $36028797018963967, %rax # imm = 0x7FFFFFFFFFFFFF
+; X64-AVX512-BMI2-NEXT:    andq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $54, %rsi
+; X64-AVX512-BMI2-NEXT:    orq %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 36028797018963967
   %shl = shl i64 %b, 54
   %or = or i64 %shl, %and
@@ -249,6 +477,33 @@ define i64 @multi_use_and(i64 %a, i64 %b, ptr %p) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: multi_use_and:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX2-NEXT:    andq %rdi, %rax
+; X64-AVX2-NEXT:    movq %rax, (%rdx)
+; X64-AVX2-NEXT:    shlq $54, %rsi
+; X64-AVX2-NEXT:    orq %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: multi_use_and:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-NEXT:    andq %rdi, %rax
+; X64-AVX512-NEXT:    movq %rax, (%rdx)
+; X64-AVX512-NEXT:    shlq $54, %rsi
+; X64-AVX512-NEXT:    orq %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: multi_use_and:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-BMI2-NEXT:    andq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    movq %rax, (%rdx)
+; X64-AVX512-BMI2-NEXT:    shlq $54, %rsi
+; X64-AVX512-BMI2-NEXT:    orq %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   store i64 %and, ptr %p
   %shl = shl i64 %b, 54
@@ -275,6 +530,33 @@ define i64 @multi_use_shl(i64 %a, i64 %b, ptr %p) nounwind {
 ; X64-SLOW-NEXT:    movq %rsi, (%rdx)
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: multi_use_shl:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX2-NEXT:    andq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $54, %rsi
+; X64-AVX2-NEXT:    movq %rsi, (%rdx)
+; X64-AVX2-NEXT:    orq %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: multi_use_shl:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-NEXT:    andq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $54, %rsi
+; X64-AVX512-NEXT:    movq %rsi, (%rdx)
+; X64-AVX512-NEXT:    orq %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: multi_use_shl:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-AVX512-BMI2-NEXT:    andq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $54, %rsi
+; X64-AVX512-BMI2-NEXT:    movq %rsi, (%rdx)
+; X64-AVX512-BMI2-NEXT:    orq %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   store i64 %shl, ptr %p
@@ -297,6 +579,27 @@ define i64 @insert_10_i64_optsize(i64 %a, i64 %b) nounwind optsize {
 ; X64-SLOW-NEXT:    shlq $10, %rax
 ; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_optsize:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_optsize:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_optsize:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or i64 %shl, %and
@@ -317,6 +620,27 @@ define i64 @insert_10_i64_minsize(i64 %a, i64 %b) nounwind minsize {
 ; X64-SLOW-NEXT:    shlq $10, %rax
 ; X64-SLOW-NEXT:    shrdq $10, %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_minsize:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_minsize:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_minsize:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or i64 %shl, %and
@@ -339,9 +663,952 @@ define i64 @insert_10_i64_load(ptr %p, i64 %b) nounwind {
 ; X64-SLOW-NEXT:    shlq $54, %rsi
 ; X64-SLOW-NEXT:    orq %rsi, %rax
 ; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_load:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq (%rdi), %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_load:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq (%rdi), %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_load:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq (%rdi), %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
   %a = load i64, ptr %p
   %and = and i64 %a, 18014398509481983
   %shl = shl i64 %b, 54
   %or = or i64 %shl, %and
   ret i64 %or
 }
+
+; Test for expansion of `llvm.fshr`
+define i64 @insert_10_i64_intrinsic(i64 %a, i64 %b) nounwind {
+; X64-LABEL: insert_10_i64_intrinsic:
+; X64:       # %bb.0:
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    shlq $10, %rax
+; X64-NEXT:    shrdq $10, %rsi, %rax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_i64_intrinsic:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    movabsq $18014398509481983, %rax # imm = 0x3FFFFFFFFFFFFF
+; X64-SLOW-NEXT:    andq %rdi, %rax
+; X64-SLOW-NEXT:    shlq $54, %rsi
+; X64-SLOW-NEXT:    orq %rsi, %rax
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_i64_intrinsic:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movq %rdi, %rax
+; X64-AVX2-NEXT:    shlq $10, %rax
+; X64-AVX2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_i64_intrinsic:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movq %rdi, %rax
+; X64-AVX512-NEXT:    shlq $10, %rax
+; X64-AVX512-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_i64_intrinsic:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movq %rdi, %rax
+; X64-AVX512-BMI2-NEXT:    shlq $10, %rax
+; X64-AVX512-BMI2-NEXT:    shrdq $10, %rsi, %rax
+; X64-AVX512-BMI2-NEXT:    retq
+  %ashift = shl i64 %a, 10
+  %res = call i64 @llvm.fshr.i64(i64 %b, i64 %ashift, i64 10)
+  ret i64 %res
+}
+
+define i32 @insert_5_i32_intrinsic(i32 %a, i32 %b) nounwind {
+; X64-LABEL: insert_5_i32_intrinsic:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    shll $5, %eax
+; X64-NEXT:    shrdl $5, %esi, %eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_5_i32_intrinsic:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    shll $27, %esi
+; X64-SLOW-NEXT:    andl $134217727, %edi # imm = 0x7FFFFFF
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_5_i32_intrinsic:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movl %edi, %eax
+; X64-AVX2-NEXT:    shll $5, %eax
+; X64-AVX2-NEXT:    shrdl $5, %esi, %eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_5_i32_intrinsic:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movl %edi, %eax
+; X64-AVX512-NEXT:    shll $5, %eax
+; X64-AVX512-NEXT:    shrdl $5, %esi, %eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_5_i32_intrinsic:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movl %edi, %eax
+; X64-AVX512-BMI2-NEXT:    shll $5, %eax
+; X64-AVX512-BMI2-NEXT:    shrdl $5, %esi, %eax
+; X64-AVX512-BMI2-NEXT:    retq
+  %ashift = shl i32 %a, 5
+  %res = call i32 @llvm.fshr.i32(i32 %b, i32 %ashift, i32 5)
+  ret i32 %res
+}
+
+define i16 @insert_3_i16_intrinsic(i16 %a, i16 %b) nounwind {
+; X64-LABEL: insert_3_i16_intrinsic:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    shll $3, %eax
+; X64-NEXT:    shrdw $3, %si, %ax
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_3_i16_intrinsic:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    shll $13, %esi
+; X64-SLOW-NEXT:    andl $8191, %edi # imm = 0x1FFF
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
+; X64-SLOW-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_3_i16_intrinsic:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    movl %edi, %eax
+; X64-AVX2-NEXT:    shll $3, %eax
+; X64-AVX2-NEXT:    shrdw $3, %si, %ax
+; X64-AVX2-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_3_i16_intrinsic:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    movl %edi, %eax
+; X64-AVX512-NEXT:    shll $3, %eax
+; X64-AVX512-NEXT:    shrdw $3, %si, %ax
+; X64-AVX512-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_3_i16_intrinsic:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    movl %edi, %eax
+; X64-AVX512-BMI2-NEXT:    shll $3, %eax
+; X64-AVX512-BMI2-NEXT:    shrdw $3, %si, %ax
+; X64-AVX512-BMI2-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-AVX512-BMI2-NEXT:    retq
+  %ashift = shl i16 %a, 3
+  %res = call i16 @llvm.fshr.i16(i16 %b, i16 %ashift, i16 3)
+  ret i16 %res
+}
+
+define i8 @insert_2_i8_intrinsic(i8 %a, i8 %b) nounwind {
+; X64-LABEL: insert_2_i8_intrinsic:
+; X64:       # %bb.0:
+; X64-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-NEXT:    shlb $6, %sil
+; X64-NEXT:    andb $63, %dil
+; X64-NEXT:    leal (%rdi,%rsi), %eax
+; X64-NEXT:    # kill: def $al killed $al killed $eax
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_2_i8_intrinsic:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-SLOW-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-SLOW-NEXT:    shlb $6, %sil
+; X64-SLOW-NEXT:    andb $63, %dil
+; X64-SLOW-NEXT:    leal (%rdi,%rsi), %eax
+; X64-SLOW-NEXT:    # kill: def $al killed $al killed $eax
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_2_i8_intrinsic:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX2-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX2-NEXT:    shlb $6, %sil
+; X64-AVX2-NEXT:    andb $63, %dil
+; X64-AVX2-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX2-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_2_i8_intrinsic:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX512-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX512-NEXT:    shlb $6, %sil
+; X64-AVX512-NEXT:    andb $63, %dil
+; X64-AVX512-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX512-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_2_i8_intrinsic:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    # kill: def $esi killed $esi def $rsi
+; X64-AVX512-BMI2-NEXT:    # kill: def $edi killed $edi def $rdi
+; X64-AVX512-BMI2-NEXT:    shlb $6, %sil
+; X64-AVX512-BMI2-NEXT:    andb $63, %dil
+; X64-AVX512-BMI2-NEXT:    leal (%rdi,%rsi), %eax
+; X64-AVX512-BMI2-NEXT:    # kill: def $al killed $al killed $eax
+; X64-AVX512-BMI2-NEXT:    retq
+  %ashift = shl i8 %a, 2
+  %res = call i8 @llvm.fshr.i8(i8 %b, i8 %ashift, i8 2)
+  ret i8 %res
+}
+
+; Tests for different vector types
+
+; Tests for type i64:
+define <2 x i64> @insert_10_v2i64(<2 x i64> %a, <2 x i64> %b) nounwind {
+; X64-LABEL: insert_10_v2i64:
+; X64:       # %bb.0:
+; X64-NEXT:    psllq $54, %xmm1
+; X64-NEXT:    psllq $10, %xmm0
+; X64-NEXT:    psrlq $10, %xmm0
+; X64-NEXT:    por %xmm1, %xmm0
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_v2i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllq $54, %xmm1
+; X64-SLOW-NEXT:    psllq $10, %xmm0
+; X64-SLOW-NEXT:    psrlq $10, %xmm0
+; X64-SLOW-NEXT:    por %xmm1, %xmm0
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_v2i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllq $54, %xmm1, %xmm1
+; X64-AVX2-NEXT:    vpsllq $10, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpsrlq $10, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_v2i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllq $54, %xmm1, %xmm1
+; X64-AVX512-NEXT:    vpsllq $10, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpsrlq $10, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_v2i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllq $10, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdq $10, %xmm1, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <2 x i64> %a, <i64 18014398509481983, i64 18014398509481983>
+  %shl = shl <2 x i64> %b, <i64 54, i64 54>
+  %or = or <2 x i64> %shl, %and
+  ret <2 x i64> %or
+}
+
+define <4 x i64> @insert_10_v4i64(<4 x i64> %a, <4 x i64> %b) nounwind {
+; X64-LABEL: insert_10_v4i64:
+; X64:       # %bb.0:
+; X64-NEXT:    psllq $54, %xmm2
+; X64-NEXT:    psllq $10, %xmm0
+; X64-NEXT:    psrlq $10, %xmm0
+; X64-NEXT:    por %xmm2, %xmm0
+; X64-NEXT:    psllq $54, %xmm3
+; X64-NEXT:    psllq $10, %xmm1
+; X64-NEXT:    psrlq $10, %xmm1
+; X64-NEXT:    por %xmm3, %xmm1
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_v4i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllq $54, %xmm2
+; X64-SLOW-NEXT:    psllq $10, %xmm0
+; X64-SLOW-NEXT:    psrlq $10, %xmm0
+; X64-SLOW-NEXT:    por %xmm2, %xmm0
+; X64-SLOW-NEXT:    psllq $54, %xmm3
+; X64-SLOW-NEXT:    psllq $10, %xmm1
+; X64-SLOW-NEXT:    psrlq $10, %xmm1
+; X64-SLOW-NEXT:    por %xmm3, %xmm1
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_v4i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllq $54, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsllq $10, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlq $10, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_v4i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllq $54, %ymm1, %ymm1
+; X64-AVX512-NEXT:    vpsllq $10, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpsrlq $10, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_v4i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllq $10, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpshrdq $10, %ymm1, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <4 x i64> %a, <i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983>
+  %shl = shl <4 x i64> %b, <i64 54, i64 54, i64 54, i64 54>
+  %or = or <4 x i64> %shl, %and
+  ret <4 x i64> %or
+}
+
+define <8 x i64> @insert_10_v8i64(<8 x i64> %a, <8 x i64> %b) nounwind {
+; X64-LABEL: insert_10_v8i64:
+; X64:       # %bb.0:
+; X64-NEXT:    psllq $54, %xmm4
+; X64-NEXT:    psllq $10, %xmm0
+; X64-NEXT:    psrlq $10, %xmm0
+; X64-NEXT:    por %xmm4, %xmm0
+; X64-NEXT:    psllq $54, %xmm5
+; X64-NEXT:    psllq $10, %xmm1
+; X64-NEXT:    psrlq $10, %xmm1
+; X64-NEXT:    por %xmm5, %xmm1
+; X64-NEXT:    psllq $54, %xmm6
+; X64-NEXT:    psllq $10, %xmm2
+; X64-NEXT:    psrlq $10, %xmm2
+; X64-NEXT:    por %xmm6, %xmm2
+; X64-NEXT:    psllq $54, %xmm7
+; X64-NEXT:    psllq $10, %xmm3
+; X64-NEXT:    psrlq $10, %xmm3
+; X64-NEXT:    por %xmm7, %xmm3
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_10_v8i64:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllq $54, %xmm4
+; X64-SLOW-NEXT:    psllq $10, %xmm0
+; X64-SLOW-NEXT:    psrlq $10, %xmm0
+; X64-SLOW-NEXT:    por %xmm4, %xmm0
+; X64-SLOW-NEXT:    psllq $54, %xmm5
+; X64-SLOW-NEXT:    psllq $10, %xmm1
+; X64-SLOW-NEXT:    psrlq $10, %xmm1
+; X64-SLOW-NEXT:    por %xmm5, %xmm1
+; X64-SLOW-NEXT:    psllq $54, %xmm6
+; X64-SLOW-NEXT:    psllq $10, %xmm2
+; X64-SLOW-NEXT:    psrlq $10, %xmm2
+; X64-SLOW-NEXT:    por %xmm6, %xmm2
+; X64-SLOW-NEXT:    psllq $54, %xmm7
+; X64-SLOW-NEXT:    psllq $10, %xmm3
+; X64-SLOW-NEXT:    psrlq $10, %xmm3
+; X64-SLOW-NEXT:    por %xmm7, %xmm3
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_10_v8i64:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllq $54, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpsllq $10, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlq $10, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm2, %ymm0
+; X64-AVX2-NEXT:    vpsllq $54, %ymm3, %ymm2
+; X64-AVX2-NEXT:    vpsllq $10, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsrlq $10, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpor %ymm1, %ymm2, %ymm1
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_10_v8i64:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllq $54, %zmm1, %zmm1
+; X64-AVX512-NEXT:    vpsllq $10, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpsrlq $10, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vporq %zmm0, %zmm1, %zmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_10_v8i64:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllq $10, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdq $10, %zmm1, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <8 x i64> %a, <i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983, i64 18014398509481983>
+  %shl = shl <8 x i64> %b, <i64 54, i64 54, i64 54, i64 54, i64 54, i64 54, i64 54, i64 54>
+  %or = or <8 x i64> %shl, %and
+  ret <8 x i64> %or
+}
+
+
+; Tests for type i32:
+define <4 x i32> @insert_5_v4i32(<4 x i32> %a, <4 x i32> %b) nounwind {
+; X64-LABEL: insert_5_v4i32:
+; X64:       # %bb.0:
+; X64-NEXT:    pslld $27, %xmm1
+; X64-NEXT:    pslld $5, %xmm0
+; X64-NEXT:    psrld $5, %xmm0
+; X64-NEXT:    por %xmm1, %xmm0
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_5_v4i32:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    pslld $27, %xmm1
+; X64-SLOW-NEXT:    pslld $5, %xmm0
+; X64-SLOW-NEXT:    psrld $5, %xmm0
+; X64-SLOW-NEXT:    por %xmm1, %xmm0
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_5_v4i32:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpslld $27, %xmm1, %xmm1
+; X64-AVX2-NEXT:    vpslld $5, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpsrld $5, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_5_v4i32:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpslld $27, %xmm1, %xmm1
+; X64-AVX512-NEXT:    vpslld $5, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpsrld $5, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_5_v4i32:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpslld $5, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdd $5, %xmm1, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <4 x i32> %a, <i32 134217727, i32 134217727, i32 134217727, i32 134217727>
+  %shl = shl <4 x i32> %b, <i32 27, i32 27, i32 27, i32 27>
+  %or = or <4 x i32> %shl, %and
+  ret <4 x i32> %or
+}
+
+define <8 x i32> @insert_5_v8i32(<8 x i32> %a, <8 x i32> %b) nounwind {
+; X64-LABEL: insert_5_v8i32:
+; X64:       # %bb.0:
+; X64-NEXT:    pslld $27, %xmm2
+; X64-NEXT:    pslld $5, %xmm0
+; X64-NEXT:    psrld $5, %xmm0
+; X64-NEXT:    por %xmm2, %xmm0
+; X64-NEXT:    pslld $27, %xmm3
+; X64-NEXT:    pslld $5, %xmm1
+; X64-NEXT:    psrld $5, %xmm1
+; X64-NEXT:    por %xmm3, %xmm1
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_5_v8i32:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    pslld $27, %xmm2
+; X64-SLOW-NEXT:    pslld $5, %xmm0
+; X64-SLOW-NEXT:    psrld $5, %xmm0
+; X64-SLOW-NEXT:    por %xmm2, %xmm0
+; X64-SLOW-NEXT:    pslld $27, %xmm3
+; X64-SLOW-NEXT:    pslld $5, %xmm1
+; X64-SLOW-NEXT:    psrld $5, %xmm1
+; X64-SLOW-NEXT:    por %xmm3, %xmm1
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_5_v8i32:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpslld $27, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpslld $5, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrld $5, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_5_v8i32:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpslld $27, %ymm1, %ymm1
+; X64-AVX512-NEXT:    vpslld $5, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpsrld $5, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_5_v8i32:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpslld $5, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpshrdd $5, %ymm1, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <8 x i32> %a, <i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727>
+  %shl = shl <8 x i32> %b, <i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27>
+  %or = or <8 x i32> %shl, %and
+  ret <8 x i32> %or
+}
+
+define <16 x i32> @insert_5_v16i32(<16 x i32> %a, <16 x i32> %b) nounwind {
+; X64-LABEL: insert_5_v16i32:
+; X64:       # %bb.0:
+; X64-NEXT:    pslld $27, %xmm4
+; X64-NEXT:    pslld $5, %xmm0
+; X64-NEXT:    psrld $5, %xmm0
+; X64-NEXT:    por %xmm4, %xmm0
+; X64-NEXT:    pslld $27, %xmm5
+; X64-NEXT:    pslld $5, %xmm1
+; X64-NEXT:    psrld $5, %xmm1
+; X64-NEXT:    por %xmm5, %xmm1
+; X64-NEXT:    pslld $27, %xmm6
+; X64-NEXT:    pslld $5, %xmm2
+; X64-NEXT:    psrld $5, %xmm2
+; X64-NEXT:    por %xmm6, %xmm2
+; X64-NEXT:    pslld $27, %xmm7
+; X64-NEXT:    pslld $5, %xmm3
+; X64-NEXT:    psrld $5, %xmm3
+; X64-NEXT:    por %xmm7, %xmm3
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_5_v16i32:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    pslld $27, %xmm4
+; X64-SLOW-NEXT:    pslld $5, %xmm0
+; X64-SLOW-NEXT:    psrld $5, %xmm0
+; X64-SLOW-NEXT:    por %xmm4, %xmm0
+; X64-SLOW-NEXT:    pslld $27, %xmm5
+; X64-SLOW-NEXT:    pslld $5, %xmm1
+; X64-SLOW-NEXT:    psrld $5, %xmm1
+; X64-SLOW-NEXT:    por %xmm5, %xmm1
+; X64-SLOW-NEXT:    pslld $27, %xmm6
+; X64-SLOW-NEXT:    pslld $5, %xmm2
+; X64-SLOW-NEXT:    psrld $5, %xmm2
+; X64-SLOW-NEXT:    por %xmm6, %xmm2
+; X64-SLOW-NEXT:    pslld $27, %xmm7
+; X64-SLOW-NEXT:    pslld $5, %xmm3
+; X64-SLOW-NEXT:    psrld $5, %xmm3
+; X64-SLOW-NEXT:    por %xmm7, %xmm3
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_5_v16i32:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpslld $27, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpslld $5, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrld $5, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm2, %ymm0
+; X64-AVX2-NEXT:    vpslld $27, %ymm3, %ymm2
+; X64-AVX2-NEXT:    vpslld $5, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsrld $5, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpor %ymm1, %ymm2, %ymm1
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_5_v16i32:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpslld $27, %zmm1, %zmm1
+; X64-AVX512-NEXT:    vpslld $5, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpsrld $5, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpord %zmm0, %zmm1, %zmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_5_v16i32:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpslld $5, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdd $5, %zmm1, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <16 x i32> %a, <i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727, i32 134217727>
+  %shl = shl <16 x i32> %b, <i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27, i32 27>
+  %or = or <16 x i32> %shl, %and
+  ret <16 x i32> %or
+}
+
+
+; Tests for type i16:
+define <8 x i16> @insert_3_v8i16(<8 x i16> %a, <8 x i16> %b) nounwind {
+; X64-LABEL: insert_3_v8i16:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $13, %xmm1
+; X64-NEXT:    psllw $3, %xmm0
+; X64-NEXT:    psrlw $3, %xmm0
+; X64-NEXT:    por %xmm1, %xmm0
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_3_v8i16:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $13, %xmm1
+; X64-SLOW-NEXT:    psllw $3, %xmm0
+; X64-SLOW-NEXT:    psrlw $3, %xmm0
+; X64-SLOW-NEXT:    por %xmm1, %xmm0
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_3_v8i16:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $13, %xmm1, %xmm1
+; X64-AVX2-NEXT:    vpsllw $3, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpsrlw $3, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_3_v8i16:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $13, %xmm1, %xmm1
+; X64-AVX512-NEXT:    vpsllw $3, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpsrlw $3, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_3_v8i16:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $3, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdw $3, %xmm1, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <8 x i16> %a, <i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191>
+  %shl = shl <8 x i16> %b, <i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13>
+  %or = or <8 x i16> %shl, %and
+  ret <8 x i16> %or
+}
+
+define <16 x i16> @insert_3_v16i16(<16 x i16> %a, <16 x i16> %b) nounwind {
+; X64-LABEL: insert_3_v16i16:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $13, %xmm2
+; X64-NEXT:    psllw $3, %xmm0
+; X64-NEXT:    psrlw $3, %xmm0
+; X64-NEXT:    por %xmm2, %xmm0
+; X64-NEXT:    psllw $13, %xmm3
+; X64-NEXT:    psllw $3, %xmm1
+; X64-NEXT:    psrlw $3, %xmm1
+; X64-NEXT:    por %xmm3, %xmm1
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_3_v16i16:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $13, %xmm2
+; X64-SLOW-NEXT:    psllw $3, %xmm0
+; X64-SLOW-NEXT:    psrlw $3, %xmm0
+; X64-SLOW-NEXT:    por %xmm2, %xmm0
+; X64-SLOW-NEXT:    psllw $13, %xmm3
+; X64-SLOW-NEXT:    psllw $3, %xmm1
+; X64-SLOW-NEXT:    psrlw $3, %xmm1
+; X64-SLOW-NEXT:    por %xmm3, %xmm1
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_3_v16i16:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $13, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsllw $3, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlw $3, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_3_v16i16:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $13, %ymm1, %ymm1
+; X64-AVX512-NEXT:    vpsllw $3, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpsrlw $3, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_3_v16i16:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $3, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpshrdw $3, %ymm1, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <16 x i16> %a, <i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191>
+  %shl = shl <16 x i16> %b, <i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13>
+  %or = or <16 x i16> %shl, %and
+  ret <16 x i16> %or
+}
+
+define <32 x i16> @insert_3_v32i16(<32 x i16> %a, <32 x i16> %b) nounwind {
+; X64-LABEL: insert_3_v32i16:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $13, %xmm4
+; X64-NEXT:    psllw $3, %xmm0
+; X64-NEXT:    psrlw $3, %xmm0
+; X64-NEXT:    por %xmm4, %xmm0
+; X64-NEXT:    psllw $13, %xmm5
+; X64-NEXT:    psllw $3, %xmm1
+; X64-NEXT:    psrlw $3, %xmm1
+; X64-NEXT:    por %xmm5, %xmm1
+; X64-NEXT:    psllw $13, %xmm6
+; X64-NEXT:    psllw $3, %xmm2
+; X64-NEXT:    psrlw $3, %xmm2
+; X64-NEXT:    por %xmm6, %xmm2
+; X64-NEXT:    psllw $13, %xmm7
+; X64-NEXT:    psllw $3, %xmm3
+; X64-NEXT:    psrlw $3, %xmm3
+; X64-NEXT:    por %xmm7, %xmm3
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_3_v32i16:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $13, %xmm4
+; X64-SLOW-NEXT:    psllw $3, %xmm0
+; X64-SLOW-NEXT:    psrlw $3, %xmm0
+; X64-SLOW-NEXT:    por %xmm4, %xmm0
+; X64-SLOW-NEXT:    psllw $13, %xmm5
+; X64-SLOW-NEXT:    psllw $3, %xmm1
+; X64-SLOW-NEXT:    psrlw $3, %xmm1
+; X64-SLOW-NEXT:    por %xmm5, %xmm1
+; X64-SLOW-NEXT:    psllw $13, %xmm6
+; X64-SLOW-NEXT:    psllw $3, %xmm2
+; X64-SLOW-NEXT:    psrlw $3, %xmm2
+; X64-SLOW-NEXT:    por %xmm6, %xmm2
+; X64-SLOW-NEXT:    psllw $13, %xmm7
+; X64-SLOW-NEXT:    psllw $3, %xmm3
+; X64-SLOW-NEXT:    psrlw $3, %xmm3
+; X64-SLOW-NEXT:    por %xmm7, %xmm3
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_3_v32i16:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $13, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpsllw $3, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlw $3, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm2, %ymm0
+; X64-AVX2-NEXT:    vpsllw $13, %ymm3, %ymm2
+; X64-AVX2-NEXT:    vpsllw $3, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsrlw $3, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpor %ymm1, %ymm2, %ymm1
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_3_v32i16:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $13, %zmm1, %zmm1
+; X64-AVX512-NEXT:    vpsllw $3, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpsrlw $3, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vporq %zmm0, %zmm1, %zmm0
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_3_v32i16:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $3, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpshrdw $3, %zmm1, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <32 x i16> %a, <i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191, i16 8191>
+  %shl = shl <32 x i16> %b, <i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13, i16 13>
+  %or = or <32 x i16> %shl, %and
+  ret <32 x i16> %or
+}
+
+
+; Negative tests for type i8:
+define <16 x i8> @insert_2_v16i8(<16 x i8> %a, <16 x i8> %b) nounwind {
+; X64-LABEL: insert_2_v16i8:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $6, %xmm1
+; X64-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    psrlw $2, %xmm0
+; X64-NEXT:    por %xmm1, %xmm0
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_2_v16i8:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $6, %xmm1
+; X64-SLOW-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    psrlw $2, %xmm0
+; X64-SLOW-NEXT:    por %xmm1, %xmm0
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_2_v16i8:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $6, %xmm1, %xmm1
+; X64-AVX2-NEXT:    vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1
+; X64-AVX2-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpsrlw $2, %xmm0, %xmm0
+; X64-AVX2-NEXT:    vpor %xmm0, %xmm1, %xmm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_2_v16i8:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $6, %xmm1, %xmm1
+; X64-AVX512-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpsrlw $2, %xmm0, %xmm0
+; X64-AVX512-NEXT:    vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_2_v16i8:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $6, %xmm1, %xmm1
+; X64-AVX512-BMI2-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpaddb %xmm0, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpsrlw $2, %xmm0, %xmm0
+; X64-AVX512-BMI2-NEXT:    vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <16 x i8> %a, <i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63>
+  %shl = shl <16 x i8> %b, <i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6>
+  %or = or <16 x i8> %shl, %and
+  ret <16 x i8> %or
+}
+
+define <32 x i8> @insert_2_v32i8(<32 x i8> %a, <32 x i8> %b) nounwind {
+; X64-LABEL: insert_2_v32i8:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $6, %xmm2
+; X64-NEXT:    movdqa {{.*#+}} xmm4 = [192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192]
+; X64-NEXT:    pand %xmm4, %xmm2
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    psrlw $2, %xmm0
+; X64-NEXT:    por %xmm2, %xmm0
+; X64-NEXT:    psllw $6, %xmm3
+; X64-NEXT:    pand %xmm3, %xmm4
+; X64-NEXT:    paddb %xmm1, %xmm1
+; X64-NEXT:    paddb %xmm1, %xmm1
+; X64-NEXT:    psrlw $2, %xmm1
+; X64-NEXT:    por %xmm4, %xmm1
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_2_v32i8:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $6, %xmm2
+; X64-SLOW-NEXT:    movdqa {{.*#+}} xmm4 = [192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192]
+; X64-SLOW-NEXT:    pand %xmm4, %xmm2
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    psrlw $2, %xmm0
+; X64-SLOW-NEXT:    por %xmm2, %xmm0
+; X64-SLOW-NEXT:    psllw $6, %xmm3
+; X64-SLOW-NEXT:    pand %xmm3, %xmm4
+; X64-SLOW-NEXT:    paddb %xmm1, %xmm1
+; X64-SLOW-NEXT:    paddb %xmm1, %xmm1
+; X64-SLOW-NEXT:    psrlw $2, %xmm1
+; X64-SLOW-NEXT:    por %xmm4, %xmm1
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_2_v32i8:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $6, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlw $2, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm1, %ymm0
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_2_v32i8:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $6, %ymm1, %ymm1
+; X64-AVX512-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpsrlw $2, %ymm0, %ymm0
+; X64-AVX512-NEXT:    vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_2_v32i8:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $6, %ymm1, %ymm1
+; X64-AVX512-BMI2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpsrlw $2, %ymm0, %ymm0
+; X64-AVX512-BMI2-NEXT:    vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <32 x i8> %a, <i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63>
+  %shl = shl <32 x i8> %b, <i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6>
+  %or = or <32 x i8> %shl, %and
+  ret <32 x i8> %or
+}
+
+define <64 x i8> @insert_2_v64i8(<64 x i8> %a, <64 x i8> %b) nounwind {
+; X64-LABEL: insert_2_v64i8:
+; X64:       # %bb.0:
+; X64-NEXT:    psllw $6, %xmm4
+; X64-NEXT:    movdqa {{.*#+}} xmm8 = [192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192]
+; X64-NEXT:    pand %xmm8, %xmm4
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    paddb %xmm0, %xmm0
+; X64-NEXT:    psrlw $2, %xmm0
+; X64-NEXT:    por %xmm4, %xmm0
+; X64-NEXT:    psllw $6, %xmm5
+; X64-NEXT:    pand %xmm8, %xmm5
+; X64-NEXT:    paddb %xmm1, %xmm1
+; X64-NEXT:    paddb %xmm1, %xmm1
+; X64-NEXT:    psrlw $2, %xmm1
+; X64-NEXT:    por %xmm5, %xmm1
+; X64-NEXT:    psllw $6, %xmm6
+; X64-NEXT:    pand %xmm8, %xmm6
+; X64-NEXT:    paddb %xmm2, %xmm2
+; X64-NEXT:    paddb %xmm2, %xmm2
+; X64-NEXT:    psrlw $2, %xmm2
+; X64-NEXT:    por %xmm6, %xmm2
+; X64-NEXT:    psllw $6, %xmm7
+; X64-NEXT:    pand %xmm7, %xmm8
+; X64-NEXT:    paddb %xmm3, %xmm3
+; X64-NEXT:    paddb %xmm3, %xmm3
+; X64-NEXT:    psrlw $2, %xmm3
+; X64-NEXT:    por %xmm8, %xmm3
+; X64-NEXT:    retq
+;
+; X64-SLOW-LABEL: insert_2_v64i8:
+; X64-SLOW:       # %bb.0:
+; X64-SLOW-NEXT:    psllw $6, %xmm4
+; X64-SLOW-NEXT:    movdqa {{.*#+}} xmm8 = [192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192]
+; X64-SLOW-NEXT:    pand %xmm8, %xmm4
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    paddb %xmm0, %xmm0
+; X64-SLOW-NEXT:    psrlw $2, %xmm0
+; X64-SLOW-NEXT:    por %xmm4, %xmm0
+; X64-SLOW-NEXT:    psllw $6, %xmm5
+; X64-SLOW-NEXT:    pand %xmm8, %xmm5
+; X64-SLOW-NEXT:    paddb %xmm1, %xmm1
+; X64-SLOW-NEXT:    paddb %xmm1, %xmm1
+; X64-SLOW-NEXT:    psrlw $2, %xmm1
+; X64-SLOW-NEXT:    por %xmm5, %xmm1
+; X64-SLOW-NEXT:    psllw $6, %xmm6
+; X64-SLOW-NEXT:    pand %xmm8, %xmm6
+; X64-SLOW-NEXT:    paddb %xmm2, %xmm2
+; X64-SLOW-NEXT:    paddb %xmm2, %xmm2
+; X64-SLOW-NEXT:    psrlw $2, %xmm2
+; X64-SLOW-NEXT:    por %xmm6, %xmm2
+; X64-SLOW-NEXT:    psllw $6, %xmm7
+; X64-SLOW-NEXT:    pand %xmm7, %xmm8
+; X64-SLOW-NEXT:    paddb %xmm3, %xmm3
+; X64-SLOW-NEXT:    paddb %xmm3, %xmm3
+; X64-SLOW-NEXT:    psrlw $2, %xmm3
+; X64-SLOW-NEXT:    por %xmm8, %xmm3
+; X64-SLOW-NEXT:    retq
+;
+; X64-AVX2-LABEL: insert_2_v64i8:
+; X64-AVX2:       # %bb.0:
+; X64-AVX2-NEXT:    vpsllw $6, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpbroadcastb {{.*#+}} ymm4 = [192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192]
+; X64-AVX2-NEXT:    vpand %ymm4, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpaddb %ymm0, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpsrlw $2, %ymm0, %ymm0
+; X64-AVX2-NEXT:    vpor %ymm0, %ymm2, %ymm0
+; X64-AVX2-NEXT:    vpsllw $6, %ymm3, %ymm2
+; X64-AVX2-NEXT:    vpand %ymm4, %ymm2, %ymm2
+; X64-AVX2-NEXT:    vpaddb %ymm1, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpaddb %ymm1, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpsrlw $2, %ymm1, %ymm1
+; X64-AVX2-NEXT:    vpor %ymm1, %ymm2, %ymm1
+; X64-AVX2-NEXT:    retq
+;
+; X64-AVX512-LABEL: insert_2_v64i8:
+; X64-AVX512:       # %bb.0:
+; X64-AVX512-NEXT:    vpsllw $6, %zmm1, %zmm1
+; X64-AVX512-NEXT:    vpaddb %zmm0, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpaddb %zmm0, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpsrlw $2, %zmm0, %zmm0
+; X64-AVX512-NEXT:    vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; X64-AVX512-NEXT:    retq
+;
+; X64-AVX512-BMI2-LABEL: insert_2_v64i8:
+; X64-AVX512-BMI2:       # %bb.0:
+; X64-AVX512-BMI2-NEXT:    vpsllw $6, %zmm1, %zmm1
+; X64-AVX512-BMI2-NEXT:    vpaddb %zmm0, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpaddb %zmm0, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpsrlw $2, %zmm0, %zmm0
+; X64-AVX512-BMI2-NEXT:    vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; X64-AVX512-BMI2-NEXT:    retq
+  %and = and <64 x i8> %a, <i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63, i8 63>
+  %shl = shl <64 x i8> %b, <i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6, i8 6>
+  %or = or <64 x i8> %shl, %and
+  ret <64 x i8> %or
+}
+
+



More information about the llvm-commits mailing list