[llvm] [X86] Optimize (a & 0xff) | ((b & 0xff) << 8) into high-byte register insertions (PR #214645)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 7 08:30:08 PDT 2026
https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/214645
>From eb4a27eed1b0a16043273371fa28374ad86dfa9d Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 7 Aug 2026 01:24:04 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)
---
llvm/test/CodeGen/X86/h-register-insert.ll | 73 ++++++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/h-register-insert.ll
diff --git a/llvm/test/CodeGen/X86/h-register-insert.ll b/llvm/test/CodeGen/X86/h-register-insert.ll
new file mode 100644
index 0000000000000..77c1d8d6ffa24
--- /dev/null
+++ b/llvm/test/CodeGen/X86/h-register-insert.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
+
+define i32 @test_insert_32(i8 inreg %A, i8 inreg %B) {
+; X86-LABEL: test_insert_32:
+; X86: # %bb.0:
+; X86-NEXT: movzbl %al, %ecx
+; X86-NEXT: movzbl %dl, %eax
+; X86-NEXT: shll $8, %eax
+; X86-NEXT: orl %ecx, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: test_insert_32:
+; X64: # %bb.0:
+; X64-NEXT: movzbl %dil, %ecx
+; X64-NEXT: movzbl %sil, %eax
+; X64-NEXT: shll $8, %eax
+; X64-NEXT: orl %ecx, %eax
+; X64-NEXT: retq
+ %conv = zext i8 %A to i32
+ %conv1 = zext i8 %B to i32
+ %shl = shl nuw nsw i32 %conv1, 8
+ %or = or disjoint i32 %shl, %conv
+ ret i32 %or
+}
+
+define i16 @test_insert_16(i8 inreg %A, i8 inreg %B) {
+; X86-LABEL: test_insert_16:
+; X86: # %bb.0:
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: shll $8, %edx
+; X86-NEXT: orl %edx, %eax
+; X86-NEXT: # kill: def $ax killed $ax killed $eax
+; X86-NEXT: retl
+;
+; X64-LABEL: test_insert_16:
+; X64: # %bb.0:
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: shll $8, %esi
+; X64-NEXT: orl %esi, %eax
+; X64-NEXT: # kill: def $ax killed $ax killed $eax
+; X64-NEXT: retq
+ %conv = zext i8 %A to i16
+ %conv1 = zext i8 %B to i16
+ %shl = shl nuw nsw i16 %conv1, 8
+ %or = or disjoint i16 %shl, %conv
+ ret i16 %or
+}
+
+define i64 @test_insert_64(i8 inreg %A, i8 inreg %B) {
+; X86-LABEL: test_insert_64:
+; X86: # %bb.0:
+; X86-NEXT: movzbl %al, %ecx
+; X86-NEXT: movzbl %dl, %eax
+; X86-NEXT: shll $8, %eax
+; X86-NEXT: orl %ecx, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: test_insert_64:
+; X64: # %bb.0:
+; X64-NEXT: movzbl %dil, %ecx
+; X64-NEXT: movzbl %sil, %eax
+; X64-NEXT: shll $8, %eax
+; X64-NEXT: orl %ecx, %eax
+; X64-NEXT: retq
+ %conv = zext i8 %A to i64
+ %conv1 = zext i8 %B to i64
+ %shl = shl nuw nsw i64 %conv1, 8
+ %or = or disjoint i64 %shl, %conv
+ ret i64 %or
+}
>From 4df08224f4ffecc4834531aa71b67c16066af987 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Fri, 7 Aug 2026 02:05:48 -0400
Subject: [PATCH 2/2] [X86] Optimize (a & 0xff) | ((b & 0xff) << 8) into
high-byte register insertions
This had to be done in dagtodag because tablegen would not work.
---
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 118 +++++++++++++++++++++
llvm/test/CodeGen/X86/extract-bits.ll | 51 +++------
llvm/test/CodeGen/X86/h-register-insert.ll | 55 ++++++++--
3 files changed, 182 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index d078117061677..8b10874cc1fc9 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -599,6 +599,7 @@ namespace {
uint8_t Imm);
bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask);
bool tryMatchBitSelect(SDNode *N);
+ bool tryMatchHRegisterInsert(SDNode *N);
MachineSDNode *emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad,
const SDLoc &dl, MVT VT, SDNode *Node);
@@ -5403,6 +5404,121 @@ bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *N) {
Ternlog.getNode(), A, B, C, 0xCA);
}
+bool X86DAGToDAGISel::tryMatchHRegisterInsert(SDNode *N) {
+ if (Subtarget->is64Bit())
+ return false;
+
+ if (N->getOpcode() != ISD::OR)
+ return false;
+ if (N->getValueType(0) != MVT::i32)
+ return false;
+
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+
+ bool NeedMovzx = false;
+ SDValue LoBase;
+
+ auto isLoBase = [&](SDValue V) {
+ if (!V.hasOneUse())
+ return false;
+
+ if (V.getOpcode() == ISD::AND) {
+ auto *C = dyn_cast<ConstantSDNode>(V.getOperand(1));
+ if (!C)
+ return false;
+ uint64_t Mask = C->getZExtValue();
+ if (Mask == 0xFF) {
+ NeedMovzx = true;
+ LoBase = V.getOperand(0);
+ return true;
+ }
+ if (Mask == 0xFFFF00FF) {
+ NeedMovzx = false;
+ // Keep V.getOperand(0) to bypass the AND! INSERT_SUBREG overwrites bits
+ // 8-15 anyway, so we don't need the AND to clear them. This saves an
+ // instruction!
+ LoBase = V.getOperand(0);
+ return true;
+ }
+ } else if ((V.getOpcode() == ISD::ZERO_EXTEND ||
+ V.getOpcode() == ISD::ANY_EXTEND) &&
+ V.getOperand(0).getValueType() == MVT::i8) {
+ NeedMovzx = true;
+ LoBase = V.getOperand(0);
+ return true;
+ }
+ return false;
+ };
+
+ SDValue HiBase;
+ auto isShl8 = [&](SDValue V) {
+ if (V.getOpcode() != ISD::SHL)
+ return false;
+ auto *C = dyn_cast<ConstantSDNode>(V.getOperand(1));
+ if (!C || C->getZExtValue() != 8)
+ return false;
+ if (!V.hasOneUse())
+ return false;
+ SDValue Src = V.getOperand(0);
+ if (Src.getOpcode() == ISD::AND) {
+ auto *M = dyn_cast<ConstantSDNode>(Src.getOperand(1));
+ if (!M || M->getZExtValue() != 255)
+ return false;
+ Src = Src.getOperand(0);
+ } else if ((Src.getOpcode() == ISD::ZERO_EXTEND ||
+ Src.getOpcode() == ISD::ANY_EXTEND) &&
+ Src.getOperand(0).getValueType() == MVT::i8) {
+ Src = Src.getOperand(0);
+ } else {
+ return false;
+ }
+ HiBase = Src;
+ return true;
+ };
+
+ if (!(isLoBase(LHS) && isShl8(RHS)) && !(isLoBase(RHS) && isShl8(LHS)))
+ return false;
+
+ SDLoc dl(N);
+ SDValue Sub8 = CurDAG->getTargetConstant(X86::sub_8bit, dl, MVT::i32);
+ SDValue RC_ABCD =
+ CurDAG->getTargetConstant(X86::GR32_ABCDRegClassID, dl, MVT::i32);
+
+ SDValue DestBase;
+ if (NeedMovzx) {
+ SDValue LoExtr =
+ (LoBase.getValueType() == MVT::i8)
+ ? LoBase
+ : SDValue(CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl,
+ MVT::i8, LoBase, Sub8),
+ 0);
+ DestBase = SDValue(
+ CurDAG->getMachineNode(X86::MOVZX32rr8, dl, MVT::i32, LoExtr), 0);
+ DestBase = SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
+ dl, MVT::i32, DestBase, RC_ABCD),
+ 0);
+ } else {
+ DestBase = SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
+ dl, MVT::i32, LoBase, RC_ABCD),
+ 0);
+ }
+
+ SDValue HiExtr =
+ (HiBase.getValueType() == MVT::i8)
+ ? HiBase
+ : SDValue(CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl,
+ MVT::i8, HiBase, Sub8),
+ 0);
+
+ SDValue Sub8Hi = CurDAG->getTargetConstant(X86::sub_8bit_hi, dl, MVT::i32);
+ SDNode *Insert = CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, dl,
+ MVT::i32, DestBase, HiExtr, Sub8Hi);
+
+ ReplaceNode(N, Insert);
+ return true;
+}
+
void X86DAGToDAGISel::Select(SDNode *Node) {
MVT NVT = Node->getSimpleValueType(0);
unsigned Opcode = Node->getOpcode();
@@ -5715,6 +5831,8 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
return;
if (Opcode == ISD::OR && tryMatchBitSelect(Node))
return;
+ if (Opcode == ISD::OR && tryMatchHRegisterInsert(Node))
+ return;
if (tryVPTERNLOG(Node))
return;
diff --git a/llvm/test/CodeGen/X86/extract-bits.ll b/llvm/test/CodeGen/X86/extract-bits.ll
index 90e075bfabf0a..d7b812a04de46 100644
--- a/llvm/test/CodeGen/X86/extract-bits.ll
+++ b/llvm/test/CodeGen/X86/extract-bits.ll
@@ -49,9 +49,8 @@ define i32 @bextr32_a0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
; X86-BMI1-LABEL: bextr32_a0:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -181,9 +180,8 @@ define i32 @bextr32_a1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %
; X86-BMI1-LABEL: bextr32_a1_indexzext:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -249,9 +247,8 @@ define i32 @bextr32_a2_load(ptr %w, i32 %numskipbits, i32 %numlowbits) nounwind
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -319,9 +316,8 @@ define i32 @bextr32_a3_load_indexzext(ptr %w, i8 zeroext %numskipbits, i8 zeroex
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -388,9 +384,8 @@ define i32 @bextr32_a4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits)
; X86-BMI1-LABEL: bextr32_a4_commutative:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -464,9 +459,8 @@ define i32 @bextr32_a5_skipextrauses(i32 %val, i32 %numskipbits, i32 %numlowbits
; X86-BMI1-NEXT: subl $8, %esp
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl %al, %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, {{[0-9]+}}(%esp), %esi
; X86-BMI1-NEXT: movl %eax, (%esp)
; X86-BMI1-NEXT: calll use32 at PLT
@@ -2231,9 +2225,8 @@ define i32 @bextr32_b0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
; X86-BMI1-LABEL: bextr32_b0:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -2296,9 +2289,8 @@ define i32 @bextr32_b1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %
; X86-BMI1-LABEL: bextr32_b1_indexzext:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -2364,9 +2356,8 @@ define i32 @bextr32_b2_load(ptr %w, i32 %numskipbits, i32 %numlowbits) nounwind
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -2434,9 +2425,8 @@ define i32 @bextr32_b3_load_indexzext(ptr %w, i8 zeroext %numskipbits, i8 zeroex
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -2503,9 +2493,8 @@ define i32 @bextr32_b4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits)
; X86-BMI1-LABEL: bextr32_b4_commutative:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -2579,9 +2568,8 @@ define i32 @bextr32_b5_skipextrauses(i32 %val, i32 %numskipbits, i32 %numlowbits
; X86-BMI1-NEXT: subl $8, %esp
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl %al, %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, {{[0-9]+}}(%esp), %esi
; X86-BMI1-NEXT: movl %eax, (%esp)
; X86-BMI1-NEXT: calll use32 at PLT
@@ -6552,9 +6540,8 @@ define i32 @bextr32_d0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind {
; X86-BMI1-LABEL: bextr32_d0:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -6614,9 +6601,8 @@ define i32 @bextr32_d1_indexzext(i32 %val, i8 %numskipbits, i8 %numlowbits) noun
; X86-BMI1-LABEL: bextr32_d1_indexzext:
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: orl %eax, %ecx
+; X86-BMI1-NEXT: movb %al, %ch
; X86-BMI1-NEXT: bextrl %ecx, {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: retl
;
@@ -6680,9 +6666,8 @@ define i32 @bextr32_d2_load(ptr %w, i32 %numskipbits, i32 %numlowbits) nounwind
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -6746,9 +6731,8 @@ define i32 @bextr32_d3_load_indexzext(ptr %w, i8 %numskipbits, i8 %numlowbits) n
; X86-BMI1: # %bb.0:
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, (%eax), %eax
; X86-BMI1-NEXT: retl
;
@@ -6823,9 +6807,8 @@ define i32 @bextr32_d5_skipextrauses(i32 %val, i32 %numskipbits, i32 %numlowbits
; X86-BMI1-NEXT: subl $8, %esp
; X86-BMI1-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
; X86-BMI1-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-BMI1-NEXT: shll $8, %ecx
; X86-BMI1-NEXT: movzbl %al, %edx
-; X86-BMI1-NEXT: orl %ecx, %edx
+; X86-BMI1-NEXT: movb %cl, %dh
; X86-BMI1-NEXT: bextrl %edx, {{[0-9]+}}(%esp), %esi
; X86-BMI1-NEXT: movl %eax, (%esp)
; X86-BMI1-NEXT: calll use32 at PLT
diff --git a/llvm/test/CodeGen/X86/h-register-insert.ll b/llvm/test/CodeGen/X86/h-register-insert.ll
index 77c1d8d6ffa24..1133e1ad6e79a 100644
--- a/llvm/test/CodeGen/X86/h-register-insert.ll
+++ b/llvm/test/CodeGen/X86/h-register-insert.ll
@@ -5,10 +5,8 @@
define i32 @test_insert_32(i8 inreg %A, i8 inreg %B) {
; X86-LABEL: test_insert_32:
; X86: # %bb.0:
-; X86-NEXT: movzbl %al, %ecx
-; X86-NEXT: movzbl %dl, %eax
-; X86-NEXT: shll $8, %eax
-; X86-NEXT: orl %ecx, %eax
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: movb %dl, %ah
; X86-NEXT: retl
;
; X64-LABEL: test_insert_32:
@@ -51,10 +49,8 @@ define i16 @test_insert_16(i8 inreg %A, i8 inreg %B) {
define i64 @test_insert_64(i8 inreg %A, i8 inreg %B) {
; X86-LABEL: test_insert_64:
; X86: # %bb.0:
-; X86-NEXT: movzbl %al, %ecx
-; X86-NEXT: movzbl %dl, %eax
-; X86-NEXT: shll $8, %eax
-; X86-NEXT: orl %ecx, %eax
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: movb %dl, %ah
; X86-NEXT: xorl %edx, %edx
; X86-NEXT: retl
;
@@ -71,3 +67,46 @@ define i64 @test_insert_64(i8 inreg %A, i8 inreg %B) {
%or = or disjoint i64 %shl, %conv
ret i64 %or
}
+
+define i32 @test_insert_mask_32(i32 %a, i8 inreg %b) {
+; X86-LABEL: test_insert_mask_32:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movb %al, %ch
+; X86-NEXT: movl %ecx, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: test_insert_mask_32:
+; X64: # %bb.0:
+; X64-NEXT: andl $-65281, %edi # imm = 0xFFFF00FF
+; X64-NEXT: movzbl %sil, %eax
+; X64-NEXT: shll $8, %eax
+; X64-NEXT: orl %edi, %eax
+; X64-NEXT: retq
+ %mask = and i32 %a, 4294902015 ; 0xFFFF00FF
+ %conv = zext i8 %b to i32
+ %shl = shl nuw nsw i32 %conv, 8
+ %or = or disjoint i32 %mask, %shl
+ ret i32 %or
+}
+
+define i32 @test_insert_negative_not_byte_sized(i32 %a, i32 %b) {
+; X86-LABEL: test_insert_negative_not_byte_sized:
+; X86: # %bb.0:
+; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: shll $8, %eax
+; X86-NEXT: orl %ecx, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: test_insert_negative_not_byte_sized:
+; X64: # %bb.0:
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: shll $8, %esi
+; X64-NEXT: orl %esi, %eax
+; X64-NEXT: retq
+ %mask = and i32 %a, 255
+ %shl = shl i32 %b, 8
+ %or = or disjoint i32 %mask, %shl
+ ret i32 %or
+}
More information about the llvm-commits
mailing list