if (SDValue RXOR = reassociateOps(ISD::XOR, DL, N0, N1, N->getFlags()))
return RXOR;
+ // fold (a^b) -> (a|b) iff a and b share no bits.
+ if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) &&
+ DAG.haveNoCommonBitsSet(N0, N1))
+ return DAG.getNode(ISD::OR, DL, VT, N0, N1);
+
// look for 'add-like' folds:
// XOR(N0,MIN_SIGNED_VALUE) == ADD(N0,MIN_SIGNED_VALUE)
if ((!LegalOperations || TLI.isOperationLegal(ISD::ADD, VT)) &&
define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
; CHECK-LABEL: in_constant_mone_vary:
; CHECK: // %bb.0:
-; CHECK-NEXT: bic w8, w2, w1
-; CHECK-NEXT: eor w0, w8, w1
+; CHECK-NEXT: orr w0, w2, w1
; CHECK-NEXT: ret
%n0 = xor i32 -1, %y ; %x
%n1 = and i32 %n0, %mask
define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
; CHECK-LABEL: in_constant_mone_vary_invmask:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn w8, w1
-; CHECK-NEXT: bic w8, w8, w2
-; CHECK-NEXT: eor w0, w8, w1
+; CHECK-NEXT: orn w0, w1, w2
; CHECK-NEXT: ret
%notmask = xor i32 %mask, -1
%n0 = xor i32 -1, %y ; %x
define <4 x i32> @in_constant_mone_vary(<4 x i32> %x, <4 x i32> %y, <4 x i32> %mask) {
; CHECK-LABEL: in_constant_mone_vary:
; CHECK: // %bb.0:
-; CHECK-NEXT: bic v0.16b, v2.16b, v1.16b
-; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: orr v0.16b, v2.16b, v1.16b
; CHECK-NEXT: ret
%n0 = xor <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, %y ; %x
%n1 = and <4 x i32> %n0, %mask
define <4 x i32> @in_constant_mone_vary_invmask(<4 x i32> %x, <4 x i32> %y, <4 x i32> %mask) {
; CHECK-LABEL: in_constant_mone_vary_invmask:
; CHECK: // %bb.0:
-; CHECK-NEXT: mvn v0.16b, v1.16b
-; CHECK-NEXT: bic v0.16b, v0.16b, v2.16b
-; CHECK-NEXT: eor v0.16b, v0.16b, v1.16b
+; CHECK-NEXT: orn v0.16b, v1.16b, v2.16b
; CHECK-NEXT: ret
%notmask = xor <4 x i32> %mask, <i32 -1, i32 -1, i32 -1, i32 -1>
%n0 = xor <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, %y ; %x
}
define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
-; CHECK-I-LABEL: in_constant_mone_vary:
-; CHECK-I: # %bb.0:
-; CHECK-I-NEXT: not a0, a1
-; CHECK-I-NEXT: and a0, a0, a2
-; CHECK-I-NEXT: xor a0, a0, a1
-; CHECK-I-NEXT: ret
-;
-; CHECK-ZBB-LABEL: in_constant_mone_vary:
-; CHECK-ZBB: # %bb.0:
-; CHECK-ZBB-NEXT: andn a0, a2, a1
-; CHECK-ZBB-NEXT: xor a0, a0, a1
-; CHECK-ZBB-NEXT: ret
+; CHECK-LABEL: in_constant_mone_vary:
+; CHECK: # %bb.0:
+; CHECK-NEXT: or a0, a2, a1
+; CHECK-NEXT: ret
%n0 = xor i32 -1, %y ; %x
%n1 = and i32 %n0, %mask
%r = xor i32 %n1, %y
; CHECK-I-LABEL: in_constant_mone_vary_invmask:
; CHECK-I: # %bb.0:
; CHECK-I-NEXT: not a0, a2
-; CHECK-I-NEXT: not a2, a1
-; CHECK-I-NEXT: and a0, a2, a0
-; CHECK-I-NEXT: xor a0, a0, a1
+; CHECK-I-NEXT: or a0, a0, a1
; CHECK-I-NEXT: ret
;
; CHECK-ZBB-LABEL: in_constant_mone_vary_invmask:
; CHECK-ZBB: # %bb.0:
-; CHECK-ZBB-NEXT: not a0, a1
-; CHECK-ZBB-NEXT: andn a0, a0, a2
-; CHECK-ZBB-NEXT: xor a0, a0, a1
+; CHECK-ZBB-NEXT: orn a0, a1, a2
; CHECK-ZBB-NEXT: ret
%notmask = xor i32 %mask, -1
%n0 = xor i32 -1, %y ; %x
; CHECK-NOBMI-LABEL: in_constant_mone_vary:
; CHECK-NOBMI: # %bb.0:
; CHECK-NOBMI-NEXT: movl %esi, %eax
-; CHECK-NOBMI-NEXT: notl %eax
-; CHECK-NOBMI-NEXT: andl %edx, %eax
-; CHECK-NOBMI-NEXT: xorl %esi, %eax
+; CHECK-NOBMI-NEXT: orl %edx, %eax
; CHECK-NOBMI-NEXT: retq
;
; CHECK-BMI-LABEL: in_constant_mone_vary:
; CHECK-BMI: # %bb.0:
-; CHECK-BMI-NEXT: andnl %edx, %esi, %eax
-; CHECK-BMI-NEXT: xorl %esi, %eax
+; CHECK-BMI-NEXT: movl %esi, %eax
+; CHECK-BMI-NEXT: orl %edx, %eax
; CHECK-BMI-NEXT: retq
%n0 = xor i32 -1, %y ; %x
%n1 = and i32 %n0, %mask
define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
; CHECK-NOBMI-LABEL: in_constant_mone_vary_invmask:
; CHECK-NOBMI: # %bb.0:
-; CHECK-NOBMI-NEXT: notl %edx
-; CHECK-NOBMI-NEXT: movl %esi, %eax
+; CHECK-NOBMI-NEXT: movl %edx, %eax
; CHECK-NOBMI-NEXT: notl %eax
-; CHECK-NOBMI-NEXT: andl %edx, %eax
-; CHECK-NOBMI-NEXT: xorl %esi, %eax
+; CHECK-NOBMI-NEXT: orl %esi, %eax
; CHECK-NOBMI-NEXT: retq
;
; CHECK-BMI-LABEL: in_constant_mone_vary_invmask:
; CHECK-BMI: # %bb.0:
-; CHECK-BMI-NEXT: notl %edx
-; CHECK-BMI-NEXT: andnl %edx, %esi, %eax
-; CHECK-BMI-NEXT: xorl %esi, %eax
+; CHECK-BMI-NEXT: movl %edx, %eax
+; CHECK-BMI-NEXT: notl %eax
+; CHECK-BMI-NEXT: orl %esi, %eax
; CHECK-BMI-NEXT: retq
%notmask = xor i32 %mask, -1
%n0 = xor i32 -1, %y ; %x
; CHECK-SSE1-LABEL: in_constant_mone_vary:
; CHECK-SSE1: # %bb.0:
; CHECK-SSE1-NEXT: movq %rdi, %rax
-; CHECK-SSE1-NEXT: movaps (%rdx), %xmm0
-; CHECK-SSE1-NEXT: movaps %xmm0, %xmm1
-; CHECK-SSE1-NEXT: andnps (%rcx), %xmm1
-; CHECK-SSE1-NEXT: xorps %xmm0, %xmm1
-; CHECK-SSE1-NEXT: movaps %xmm1, (%rdi)
+; CHECK-SSE1-NEXT: movaps (%rcx), %xmm0
+; CHECK-SSE1-NEXT: orps (%rdx), %xmm0
+; CHECK-SSE1-NEXT: movaps %xmm0, (%rdi)
; CHECK-SSE1-NEXT: retq
;
; CHECK-SSE2-LABEL: in_constant_mone_vary:
; CHECK-SSE2: # %bb.0:
-; CHECK-SSE2-NEXT: movaps (%rsi), %xmm1
-; CHECK-SSE2-NEXT: movaps %xmm1, %xmm0
-; CHECK-SSE2-NEXT: andnps (%rdx), %xmm0
-; CHECK-SSE2-NEXT: xorps %xmm1, %xmm0
+; CHECK-SSE2-NEXT: movaps (%rdx), %xmm0
+; CHECK-SSE2-NEXT: orps (%rsi), %xmm0
; CHECK-SSE2-NEXT: retq
;
; CHECK-XOP-LABEL: in_constant_mone_vary:
; CHECK-XOP: # %bb.0:
-; CHECK-XOP-NEXT: vmovaps (%rsi), %xmm0
-; CHECK-XOP-NEXT: vandnps (%rdx), %xmm0, %xmm1
-; CHECK-XOP-NEXT: vxorps %xmm0, %xmm1, %xmm0
+; CHECK-XOP-NEXT: vmovaps (%rdx), %xmm0
+; CHECK-XOP-NEXT: vorps (%rsi), %xmm0, %xmm0
; CHECK-XOP-NEXT: retq
%x = load <4 x i32>, ptr%px, align 16
%y = load <4 x i32>, ptr%py, align 16
; CHECK-SSE1-LABEL: in_constant_mone_vary_invmask:
; CHECK-SSE1: # %bb.0:
; CHECK-SSE1-NEXT: movq %rdi, %rax
-; CHECK-SSE1-NEXT: movaps (%rdx), %xmm0
-; CHECK-SSE1-NEXT: movaps (%rcx), %xmm1
-; CHECK-SSE1-NEXT: xorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
-; CHECK-SSE1-NEXT: movaps %xmm0, %xmm2
-; CHECK-SSE1-NEXT: andnps %xmm1, %xmm2
-; CHECK-SSE1-NEXT: xorps %xmm0, %xmm2
-; CHECK-SSE1-NEXT: movaps %xmm2, (%rdi)
+; CHECK-SSE1-NEXT: movaps (%rcx), %xmm0
+; CHECK-SSE1-NEXT: xorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-SSE1-NEXT: orps (%rdx), %xmm0
+; CHECK-SSE1-NEXT: movaps %xmm0, (%rdi)
; CHECK-SSE1-NEXT: retq
;
; CHECK-SSE2-LABEL: in_constant_mone_vary_invmask:
; CHECK-SSE2: # %bb.0:
-; CHECK-SSE2-NEXT: movdqa (%rsi), %xmm1
-; CHECK-SSE2-NEXT: pcmpeqd %xmm2, %xmm2
-; CHECK-SSE2-NEXT: pxor (%rdx), %xmm2
-; CHECK-SSE2-NEXT: movdqa %xmm1, %xmm0
-; CHECK-SSE2-NEXT: pandn %xmm2, %xmm0
-; CHECK-SSE2-NEXT: pxor %xmm1, %xmm0
+; CHECK-SSE2-NEXT: pcmpeqd %xmm0, %xmm0
+; CHECK-SSE2-NEXT: pxor (%rdx), %xmm0
+; CHECK-SSE2-NEXT: por (%rsi), %xmm0
; CHECK-SSE2-NEXT: retq
;
; CHECK-XOP-LABEL: in_constant_mone_vary_invmask:
; CHECK-XOP: # %bb.0:
-; CHECK-XOP-NEXT: vmovdqa (%rsi), %xmm0
-; CHECK-XOP-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-XOP-NEXT: vpxor (%rdx), %xmm1, %xmm1
-; CHECK-XOP-NEXT: vpandn %xmm1, %xmm0, %xmm1
-; CHECK-XOP-NEXT: vpxor %xmm0, %xmm1, %xmm0
+; CHECK-XOP-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0
+; CHECK-XOP-NEXT: vpxor (%rdx), %xmm0, %xmm0
+; CHECK-XOP-NEXT: vpor (%rsi), %xmm0, %xmm0
; CHECK-XOP-NEXT: retq
%x = load <4 x i32>, ptr%px, align 16
%y = load <4 x i32>, ptr%py, align 16