[llvm] [SelectionDAG] Add BUILD_PAIR to computeKnownBits (PR #225073)
Timur Golubovich via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 05:44:26 PDT 2026
https://github.com/timurgol007 created https://github.com/llvm/llvm-project/pull/225073
Concatenate the known bits of both halves, with operand 0 as the low half and operand 1 as the high half, matching TargetLowering::SimplifyDemandedBits and GlobalISel's G_MERGE_VALUES.
>From d3ea14d46b92b4a99b0e9e18b643d26495c8f38b Mon Sep 17 00:00:00 2001
From: Timur Golubovich <timur.golubovich at intel.com>
Date: Mon, 21 Sep 2026 14:42:56 +0200
Subject: [PATCH] [SelectionDAG] Add BUILD_PAIR to computeKnownBits
Concatenate the known bits of both halves, with operand 0 as the low half and
operand 1 as the high half, matching TargetLowering::SimplifyDemandedBits and
GlobalISel's G_MERGE_VALUES.
---
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 +
llvm/test/CodeGen/X86/knownbits-build-pair.ll | 42 +++
llvm/test/CodeGen/X86/pr38539.ll | 271 ++++++++----------
.../Target/X86/X86SelectionDAGTest.cpp | 28 ++
4 files changed, 193 insertions(+), 156 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/knownbits-build-pair.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 0a3eb65965826..80e9083e6bf74 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4322,6 +4322,14 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
Known = Known.anyext(BitWidth);
break;
}
+ case ISD::BUILD_PAIR: {
+ // Operand 0 is the low half and operand 1 the high half,
+ // KnownBits::concat places its argument in the low bits.
+ Known = computeKnownBits(Op.getOperand(0), Depth + 1);
+ Known2 = computeKnownBits(Op.getOperand(1), Depth + 1);
+ Known = Known2.concat(Known);
+ break;
+ }
case ISD::INSERT_VECTOR_ELT: {
if (Op.getValueType().isScalableVector())
break;
diff --git a/llvm/test/CodeGen/X86/knownbits-build-pair.ll b/llvm/test/CodeGen/X86/knownbits-build-pair.ll
new file mode 100644
index 0000000000000..fe1c1ac13daf2
--- /dev/null
+++ b/llvm/test/CodeGen/X86/knownbits-build-pair.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X64
+
+; In %bb the zero %v is an ISD::BUILD_PAIR of known-zero parts, because cross-block
+; values are passed in parts. computeKnownBits() has to see through it to fold the
+; shift here: type legalization expands variable shifts via memory and loses the zero.
+
+define i128 @shl_zero_i128(i128 %x, i128 %amt, i1 %c) nounwind {
+; X86-LABEL: shl_zero_i128:
+; X86: # %bb.0: # %entry
+; X86-NEXT: pushl %ebp
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: andl $-16, %esp
+; X86-NEXT: subl $16, %esp
+; X86-NEXT: movl 8(%ebp), %eax
+; X86-NEXT: testb $1, 56(%ebp)
+; X86-NEXT: movl $0, 12(%eax)
+; X86-NEXT: movl $0, 8(%eax)
+; X86-NEXT: movl $0, 4(%eax)
+; X86-NEXT: movl $0, (%eax)
+; X86-NEXT: movl %ebp, %esp
+; X86-NEXT: popl %ebp
+; X86-NEXT: retl $4
+;
+; X64-LABEL: shl_zero_i128:
+; X64: # %bb.0: # %entry
+; X64-NEXT: testb $1, %r8b
+; X64-NEXT: xorl %eax, %eax
+; X64-NEXT: xorl %edx, %edx
+; X64-NEXT: retq
+entry:
+ %v = and i128 %x, 0
+ br i1 %c, label %bb, label %exit
+
+bb:
+ %s = shl i128 %v, %amt
+ ret i128 %s
+
+exit:
+ ret i128 0
+}
diff --git a/llvm/test/CodeGen/X86/pr38539.ll b/llvm/test/CodeGen/X86/pr38539.ll
index eecd15dd2afe9..e0e6f6bec4876 100644
--- a/llvm/test/CodeGen/X86/pr38539.ll
+++ b/llvm/test/CodeGen/X86/pr38539.ll
@@ -22,223 +22,182 @@ define void @f() nounwind {
; X86-NEXT: pushl %edi
; X86-NEXT: pushl %esi
; X86-NEXT: andl $-16, %esp
-; X86-NEXT: subl $176, %esp
-; X86-NEXT: movl {{[0-9]+}}(%esp), %edi
-; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT: subl $96, %esp
+; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
; X86-NEXT: movzbl (%eax), %eax
; X86-NEXT: movzbl (%eax), %ecx
; X86-NEXT: movzbl %al, %eax
; X86-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill
; X86-NEXT: divb %cl
-; X86-NEXT: movl %edi, %eax
+; X86-NEXT: movl %edx, %eax
; X86-NEXT: shll $30, %eax
; X86-NEXT: movl %eax, %ecx
; X86-NEXT: sarl $30, %ecx
; X86-NEXT: sarl $31, %eax
-; X86-NEXT: xorl %eax, %edi
-; X86-NEXT: xorl %eax, %ebx
+; X86-NEXT: xorl %eax, %edx
+; X86-NEXT: xorl %eax, %esi
; X86-NEXT: shrdl $1, %eax, %ecx
-; X86-NEXT: xorl %ecx, %esi
-; X86-NEXT: subl %ecx, %esi
-; X86-NEXT: sbbl %eax, %ebx
-; X86-NEXT: sbbl %eax, %edi
-; X86-NEXT: movl %edi, %ecx
-; X86-NEXT: shldl $30, %ebx, %ecx
-; X86-NEXT: movl %esi, %edx
-; X86-NEXT: shrdl $2, %ebx, %edx
-; X86-NEXT: testl %ecx, %ecx
-; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: xorl %ecx, %ebx
+; X86-NEXT: subl %ecx, %ebx
+; X86-NEXT: sbbl %eax, %esi
+; X86-NEXT: sbbl %eax, %edx
+; X86-NEXT: movl %edx, %eax
+; X86-NEXT: shldl $30, %esi, %eax
+; X86-NEXT: movl %ebx, %edi
+; X86-NEXT: movl %ebx, %ecx
+; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: shrdl $2, %esi, %ecx
+; X86-NEXT: testl %eax, %eax
+; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: jne .LBB0_1
; X86-NEXT: # %bb.2: # %BB_udiv-special-cases
-; X86-NEXT: bsrl %edx, %eax
-; X86-NEXT: xorl $31, %eax
-; X86-NEXT: orl $32, %eax
+; X86-NEXT: bsrl %ecx, %esi
+; X86-NEXT: xorl $31, %esi
+; X86-NEXT: orl $32, %esi
; X86-NEXT: jmp .LBB0_3
; X86-NEXT: .LBB0_1:
-; X86-NEXT: bsrl %ecx, %eax
-; X86-NEXT: xorl $31, %eax
+; X86-NEXT: bsrl %eax, %esi
+; X86-NEXT: xorl $31, %esi
; X86-NEXT: .LBB0_3: # %BB_udiv-special-cases
-; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: shll $30, %esi
+; X86-NEXT: movl %edi, %edx
+; X86-NEXT: shll $30, %edx
; X86-NEXT: jne .LBB0_4
; X86-NEXT: # %bb.5: # %BB_udiv-special-cases
-; X86-NEXT: movl $64, %esi
-; X86-NEXT: orl %ecx, %edx
+; X86-NEXT: movl $64, %edx
+; X86-NEXT: orl %eax, %ecx
; X86-NEXT: je .LBB0_7
; X86-NEXT: jmp .LBB0_8
; X86-NEXT: .LBB0_4:
-; X86-NEXT: bsrl %esi, %esi
-; X86-NEXT: xorl $31, %esi
-; X86-NEXT: orl %ecx, %edx
+; X86-NEXT: bsrl %edx, %edx
+; X86-NEXT: xorl $31, %edx
+; X86-NEXT: orl %eax, %ecx
; X86-NEXT: jne .LBB0_8
; X86-NEXT: .LBB0_7: # %BB_udiv-special-cases
-; X86-NEXT: addl $64, %esi
-; X86-NEXT: movl %esi, %eax
+; X86-NEXT: addl $64, %edx
+; X86-NEXT: movl %edx, %esi
; X86-NEXT: .LBB0_8: # %BB_udiv-special-cases
-; X86-NEXT: addl $-66, %eax
+; X86-NEXT: movl %esi, %edx
+; X86-NEXT: addl $-66, %edx
; X86-NEXT: movl $0, %ebx
; X86-NEXT: adcl $-1, %ebx
; X86-NEXT: movl $0, %esi
; X86-NEXT: adcl $3, %esi
; X86-NEXT: andl $3, %esi
-; X86-NEXT: movb $1, %cl
-; X86-NEXT: testb %cl, %cl
+; X86-NEXT: movb $1, %al
+; X86-NEXT: testb %al, %al
; X86-NEXT: jne .LBB0_10
; X86-NEXT: # %bb.9: # %select.false.sink
-; X86-NEXT: xorl %ecx, %ecx
-; X86-NEXT: movl $65, %edx
-; X86-NEXT: cmpl %eax, %edx
-; X86-NEXT: movl $0, %edx
-; X86-NEXT: sbbl %ebx, %edx
-; X86-NEXT: movl $0, %edx
-; X86-NEXT: sbbl %esi, %edx
-; X86-NEXT: sbbl %ecx, %ecx
-; X86-NEXT: setb %cl
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: movl $65, %ecx
+; X86-NEXT: cmpl %edx, %ecx
+; X86-NEXT: movl $0, %ecx
+; X86-NEXT: sbbl %ebx, %ecx
+; X86-NEXT: movl $0, %ecx
+; X86-NEXT: sbbl %esi, %ecx
+; X86-NEXT: sbbl %eax, %eax
+; X86-NEXT: setb %al
; X86-NEXT: .LBB0_10: # %select.end
-; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: testb %cl, %cl
+; X86-NEXT: testb %al, %al
; X86-NEXT: jne .LBB0_15
; X86-NEXT: # %bb.11: # %select.end
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: xorl $65, %ecx
-; X86-NEXT: orl %esi, %ecx
-; X86-NEXT: orl %ebx, %ecx
+; X86-NEXT: movl %edx, %eax
+; X86-NEXT: xorl $65, %eax
+; X86-NEXT: orl %esi, %eax
+; X86-NEXT: orl %ebx, %eax
; X86-NEXT: je .LBB0_15
; X86-NEXT: # %bb.12: # %udiv-bb1
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: addl $1, %ecx
-; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: addl $1, %edx
+; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: adcl $0, %ebx
; X86-NEXT: adcl $0, %esi
; X86-NEXT: andl $3, %esi
; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: movb $65, %cl
-; X86-NEXT: subb %al, %cl
-; X86-NEXT: movl %ecx, %eax
-; X86-NEXT: shrb $3, %al
-; X86-NEXT: andb $12, %al
-; X86-NEXT: negb %al
-; X86-NEXT: movsbl %al, %edx
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl 128(%esp,%edx), %eax
-; X86-NEXT: movl 132(%esp,%edx), %edi
-; X86-NEXT: movl 136(%esp,%edx), %edx
-; X86-NEXT: shldl %cl, %edi, %edx
-; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: shldl %cl, %eax, %edi
-; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: shll %cl, %eax
-; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
+; X86-NEXT: movl %edx, %eax
; X86-NEXT: orl %esi, %eax
-; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: orl %ebx, %eax
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
; X86-NEXT: je .LBB0_15
; X86-NEXT: # %bb.13: # %udiv-preheader
-; X86-NEXT: andl $3, %esi
-; X86-NEXT: andl $3, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl $0, {{[0-9]+}}(%esp)
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload
-; X86-NEXT: movl %ecx, %eax
-; X86-NEXT: shrb $3, %al
-; X86-NEXT: andb $12, %al
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: movl 88(%esp,%eax), %edi
-; X86-NEXT: movl 80(%esp,%eax), %ebx
-; X86-NEXT: movl 84(%esp,%eax), %eax
-; X86-NEXT: movl %eax, %edx
-; X86-NEXT: shrdl %cl, %edi, %edx
-; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: # kill: def $cl killed $cl killed $ecx
-; X86-NEXT: shrdl %cl, %eax, %ebx
+; X86-NEXT: andl $3, %eax
+; X86-NEXT: xorl %ecx, %ecx
; X86-NEXT: movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
-; X86-NEXT: addl $-1, %eax
+; X86-NEXT: movl %edi, %edx
+; X86-NEXT: addl $-1, %edx
+; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT: adcl $-1, %edx
+; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
-; X86-NEXT: adcl $-1, %eax
+; X86-NEXT: adcl $3, %eax
+; X86-NEXT: andl $3, %eax
; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: adcl $3, %esi
-; X86-NEXT: andl $3, %esi
-; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
-; X86-NEXT: xorl %ecx, %ecx
+; X86-NEXT: movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; X86-NEXT: xorl %esi, %esi
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; X86-NEXT: movl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: .p2align 4
; X86-NEXT: .LBB0_14: # %udiv-do-while
; X86-NEXT: # =>This Inner Loop Header: Depth=1
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
-; X86-NEXT: shldl $1, %edx, %ecx
-; X86-NEXT: shldl $1, %ebx, %edx
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload
-; X86-NEXT: movl %edi, %esi
-; X86-NEXT: andl $2, %esi
-; X86-NEXT: shrl %esi
-; X86-NEXT: leal (%esi,%ebx,2), %ebx
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
-; X86-NEXT: shldl $1, %esi, %edi
-; X86-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
-; X86-NEXT: shldl $1, %eax, %esi
-; X86-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload
; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: addl %eax, %eax
-; X86-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload
-; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: andl $3, %edi
-; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: cmpl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
-; X86-NEXT: sbbl %edx, %esi
+; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: shldl $1, %esi, %eax
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
-; X86-NEXT: sbbl %ecx, %esi
-; X86-NEXT: shll $30, %esi
-; X86-NEXT: movl %esi, %edi
-; X86-NEXT: sarl $31, %edi
-; X86-NEXT: sarl $30, %esi
-; X86-NEXT: shrdl $1, %edi, %esi
-; X86-NEXT: movl %esi, %eax
-; X86-NEXT: andl $1, %eax
-; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload
-; X86-NEXT: movl %edi, %eax
-; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload
-; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload
-; X86-NEXT: subl %esi, %ebx
+; X86-NEXT: shldl $1, %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
+; X86-NEXT: movl %ecx, %edx
+; X86-NEXT: andl $2, %edx
+; X86-NEXT: shrl %edx
+; X86-NEXT: leal (%edx,%esi,2), %esi
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload
+; X86-NEXT: shldl $1, %edi, %ecx
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT: orl %edx, %ecx
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload
+; X86-NEXT: shldl $1, %ebx, %edi
+; X86-NEXT: orl %edx, %edi
+; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: addl %ebx, %ebx
+; X86-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload
; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: sbbl %edi, %edx
-; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: sbbl %eax, %ecx
; X86-NEXT: andl $3, %ecx
-; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
-; X86-NEXT: addl $-1, %eax
+; X86-NEXT: cmpl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT: sbbl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT: sbbl %eax, %edx
+; X86-NEXT: shll $30, %edx
+; X86-NEXT: movl %edx, %ebx
+; X86-NEXT: sarl $31, %ebx
+; X86-NEXT: sarl $30, %edx
+; X86-NEXT: shrdl $1, %ebx, %edx
+; X86-NEXT: movl %edx, %edi
+; X86-NEXT: andl $1, %edi
+; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload
+; X86-NEXT: movl %ebx, %edi
+; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload
+; X86-NEXT: andl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload
+; X86-NEXT: subl %edx, %esi
+; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
-; X86-NEXT: adcl $-1, %esi
+; X86-NEXT: sbbl %ebx, %esi
+; X86-NEXT: sbbl %edi, %eax
+; X86-NEXT: andl $3, %eax
+; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload
+; X86-NEXT: addl $-1, %edx
+; X86-NEXT: adcl $-1, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload
; X86-NEXT: adcl $3, %ebx
; X86-NEXT: andl $3, %ebx
-; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: orl %ebx, %eax
+; X86-NEXT: orl %ebx, %edx
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload
-; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
-; X86-NEXT: orl %esi, %eax
+; X86-NEXT: orl %ebx, %edx
; X86-NEXT: jne .LBB0_14
; X86-NEXT: .LBB0_15: # %udiv-end
; X86-NEXT: cmpb $0, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Reload
diff --git a/llvm/unittests/Target/X86/X86SelectionDAGTest.cpp b/llvm/unittests/Target/X86/X86SelectionDAGTest.cpp
index 07164dd504104..fdf66b23d7f0a 100644
--- a/llvm/unittests/Target/X86/X86SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/X86/X86SelectionDAGTest.cpp
@@ -150,4 +150,32 @@ TEST_F(X86SelectionDAGTest, computeKnownBits_FXOR) {
EXPECT_FALSE(KnownHi2xF64.isNonNegative());
}
+TEST_F(X86SelectionDAGTest, computeKnownBits_BUILD_PAIR) {
+ SDLoc Loc;
+
+ // Operand 0 holds the low half and operand 1 the high half.
+ SDValue Lo = DAG->getConstant(0xdeadbeef, Loc, MVT::i32);
+ SDValue Hi = DAG->getConstant(0xcafebabe, Loc, MVT::i32);
+ SDValue Pair = DAG->getNode(ISD::BUILD_PAIR, Loc, MVT::i64, Lo, Hi);
+ KnownBits Known = DAG->computeKnownBits(Pair);
+ EXPECT_TRUE(Known.isConstant());
+ EXPECT_EQ(Known.getConstant(), APInt(64, 0xcafebabedeadbeefULL));
+
+ // Partially known halves: the bits known for each operand have to stay within
+ // that operand's half of the result.
+ SDValue Src = DAG->getCopyFromReg(DAG->getEntryNode(), Loc,
+ Register::index2VirtReg(1), MVT::i32);
+ SDValue LoMasked = DAG->getNode(ISD::AND, Loc, MVT::i32, Src,
+ DAG->getConstant(0x0000beef, Loc, MVT::i32));
+ SDValue HiMasked = DAG->getNode(ISD::AND, Loc, MVT::i32, Src,
+ DAG->getConstant(0xdead0000, Loc, MVT::i32));
+ SDValue MaskedPair =
+ DAG->getNode(ISD::BUILD_PAIR, Loc, MVT::i64, LoMasked, HiMasked);
+ KnownBits KnownMasked = DAG->computeKnownBits(MaskedPair);
+ // The known zeros of each half are the complement of its mask:
+ // ~0xdead0000 for the high half and ~0x0000beef for the low half.
+ EXPECT_EQ(KnownMasked.Zero, APInt(64, 0x2152ffffffff4110ULL));
+ EXPECT_TRUE(KnownMasked.One.isZero());
+}
+
} // end namespace llvm
More information about the llvm-commits
mailing list