return SDValue();
}
-static SDValue combineShiftRightLogical(SDNode *N, SelectionDAG &DAG) {
+static SDValue combineShiftRightLogical(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
EVT VT = N0.getValueType();
+ // Only do this on the last DAG combine as it can interfere with other
+ // combines.
+ if (!DCI.isAfterLegalizeVectorOps())
+ return SDValue();
+
// Try to improve a sequence of srl (and X, C1), C2 by inverting the order.
// TODO: This is a generic DAG combine that became an x86-only combine to
// avoid shortcomings in other folds such as bswap, bit-test ('bt'), and
return V;
if (N->getOpcode() == ISD::SRL)
- if (SDValue V = combineShiftRightLogical(N, DAG))
+ if (SDValue V = combineShiftRightLogical(N, DAG, DCI))
return V;
return SDValue();
define void @g64xh(i64 inreg %x) nounwind {
; CHECK-LINUX64-LABEL: g64xh:
; CHECK-LINUX64: # %bb.0:
-; CHECK-LINUX64-NEXT: btl $11, %edi
-; CHECK-LINUX64-NEXT: jb .LBB0_2
+; CHECK-LINUX64-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-LINUX64-NEXT: jne .LBB0_2
; CHECK-LINUX64-NEXT: # %bb.1: # %yes
; CHECK-LINUX64-NEXT: pushq %rax
; CHECK-LINUX64-NEXT: callq bar
; CHECK-WIN32-64-LABEL: g64xh:
; CHECK-WIN32-64: # %bb.0:
; CHECK-WIN32-64-NEXT: subq $40, %rsp
-; CHECK-WIN32-64-NEXT: btl $11, %ecx
-; CHECK-WIN32-64-NEXT: jb .LBB0_2
+; CHECK-WIN32-64-NEXT: testl $2048, %ecx # imm = 0x800
+; CHECK-WIN32-64-NEXT: jne .LBB0_2
; CHECK-WIN32-64-NEXT: # %bb.1: # %yes
; CHECK-WIN32-64-NEXT: callq bar
; CHECK-WIN32-64-NEXT: .LBB0_2: # %no
;
; CHECK-X86-LABEL: g64xh:
; CHECK-X86: # %bb.0:
-; CHECK-X86-NEXT: btl $11, %eax
-; CHECK-X86-NEXT: jb .LBB0_2
+; CHECK-X86-NEXT: testl $2048, %eax # imm = 0x800
+; CHECK-X86-NEXT: jne .LBB0_2
; CHECK-X86-NEXT: # %bb.1: # %yes
; CHECK-X86-NEXT: calll bar
; CHECK-X86-NEXT: .LBB0_2: # %no
define void @g32xh(i32 inreg %x) nounwind {
; CHECK-LINUX64-LABEL: g32xh:
; CHECK-LINUX64: # %bb.0:
-; CHECK-LINUX64-NEXT: btl $11, %edi
-; CHECK-LINUX64-NEXT: jb .LBB2_2
+; CHECK-LINUX64-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-LINUX64-NEXT: jne .LBB2_2
; CHECK-LINUX64-NEXT: # %bb.1: # %yes
; CHECK-LINUX64-NEXT: pushq %rax
; CHECK-LINUX64-NEXT: callq bar
; CHECK-WIN32-64-LABEL: g32xh:
; CHECK-WIN32-64: # %bb.0:
; CHECK-WIN32-64-NEXT: subq $40, %rsp
-; CHECK-WIN32-64-NEXT: btl $11, %ecx
-; CHECK-WIN32-64-NEXT: jb .LBB2_2
+; CHECK-WIN32-64-NEXT: testl $2048, %ecx # imm = 0x800
+; CHECK-WIN32-64-NEXT: jne .LBB2_2
; CHECK-WIN32-64-NEXT: # %bb.1: # %yes
; CHECK-WIN32-64-NEXT: callq bar
; CHECK-WIN32-64-NEXT: .LBB2_2: # %no
;
; CHECK-X86-LABEL: g32xh:
; CHECK-X86: # %bb.0:
-; CHECK-X86-NEXT: btl $11, %eax
-; CHECK-X86-NEXT: jb .LBB2_2
+; CHECK-X86-NEXT: testl $2048, %eax # imm = 0x800
+; CHECK-X86-NEXT: jne .LBB2_2
; CHECK-X86-NEXT: # %bb.1: # %yes
; CHECK-X86-NEXT: calll bar
; CHECK-X86-NEXT: .LBB2_2: # %no
define void @g16xh(i16 inreg %x) nounwind {
; CHECK-LINUX64-LABEL: g16xh:
; CHECK-LINUX64: # %bb.0:
-; CHECK-LINUX64-NEXT: btl $11, %edi
-; CHECK-LINUX64-NEXT: jb .LBB4_2
+; CHECK-LINUX64-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-LINUX64-NEXT: jne .LBB4_2
; CHECK-LINUX64-NEXT: # %bb.1: # %yes
; CHECK-LINUX64-NEXT: pushq %rax
; CHECK-LINUX64-NEXT: callq bar
; CHECK-WIN32-64-LABEL: g16xh:
; CHECK-WIN32-64: # %bb.0:
; CHECK-WIN32-64-NEXT: subq $40, %rsp
-; CHECK-WIN32-64-NEXT: btl $11, %ecx
-; CHECK-WIN32-64-NEXT: jb .LBB4_2
+; CHECK-WIN32-64-NEXT: testl $2048, %ecx # imm = 0x800
+; CHECK-WIN32-64-NEXT: jne .LBB4_2
; CHECK-WIN32-64-NEXT: # %bb.1: # %yes
; CHECK-WIN32-64-NEXT: callq bar
; CHECK-WIN32-64-NEXT: .LBB4_2: # %no
;
; CHECK-X86-LABEL: g16xh:
; CHECK-X86: # %bb.0:
-; CHECK-X86-NEXT: btl $11, %eax
-; CHECK-X86-NEXT: jb .LBB4_2
+; CHECK-X86-NEXT: testl $2048, %eax # imm = 0x800
+; CHECK-X86-NEXT: jne .LBB4_2
; CHECK-X86-NEXT: # %bb.1: # %yes
; CHECK-X86-NEXT: calll bar
; CHECK-X86-NEXT: .LBB4_2: # %no
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: btl $11, %edi
-; CHECK-NEXT: jb .LBB0_2
+; CHECK-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-NEXT: jne .LBB0_2
; CHECK-NEXT: # %bb.1: # %yes
; CHECK-NEXT: callq bar
; CHECK-NEXT: .LBB0_2: # %no
ret void
}
+; This test is identical to test64 above with only the destination of the br
+; reversed. This somehow causes the two functions to get slightly different
+; initial IR. One has an extra invert of the setcc. This previous caused one
+; the functions to use a BT while the other used a TEST due to another DAG
+; combine messing with an expected canonical form.
define void @test64_2(i64 inreg %x) {
; CHECK-LABEL: test64_2:
; CHECK: # %bb.0:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: btl $11, %edi
-; CHECK-NEXT: jb .LBB8_2
+; CHECK-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-NEXT: jne .LBB8_2
; CHECK-NEXT: # %bb.1: # %yes
; CHECK-NEXT: callq bar
; CHECK-NEXT: .LBB8_2: # %no
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: btl $11, %edi
-; CHECK-NEXT: jb .LBB12_2
+; CHECK-NEXT: testl $2048, %edi # imm = 0x800
+; CHECK-NEXT: jne .LBB12_2
; CHECK-NEXT: # %bb.1: # %yes
; CHECK-NEXT: callq bar
; CHECK-NEXT: .LBB12_2: # %no