Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4542,10 +4542,25 @@ } // FIXME: unify with llvm::haveNoCommonBitsSet. -// FIXME: could also handle masked merge pattern (X & ~M) op (Y & M) bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const { assert(A.getValueType() == B.getValueType() && "Values must have the same type"); + // Match masked merge pattern (X & ~M) op (Y & M) + if (A->getOpcode() == ISD::AND && B->getOpcode() == ISD::AND) { + auto MatchNoCommonBitsPattern = [&](SDValue NotM, SDValue And) { + if (isBitwiseNot(NotM, true)) { + SDValue NotOperand = NotM->getOperand(0); + return NotOperand == And->getOperand(0) || + NotOperand == And->getOperand(1); + } + return false; + }; + if (MatchNoCommonBitsPattern(A->getOperand(0), B) || + MatchNoCommonBitsPattern(A->getOperand(1), B) || + MatchNoCommonBitsPattern(B->getOperand(0), A) || + MatchNoCommonBitsPattern(B->getOperand(1), A)) + return true; + } return KnownBits::haveNoCommonBitsSet(computeKnownBits(A), computeKnownBits(B)); } Index: llvm/test/CodeGen/X86/or-lea.ll =================================================================== --- llvm/test/CodeGen/X86/or-lea.ll +++ llvm/test/CodeGen/X86/or-lea.ll @@ -146,10 +146,10 @@ ; ; BMI-LABEL: or_and_and_rhs_neg_i32: ; BMI: # %bb.0: # %entry +; BMI-NEXT: # kill: def $edx killed $edx def $rdx ; BMI-NEXT: andl %esi, %edx ; BMI-NEXT: andnl %edi, %esi, %eax -; BMI-NEXT: orl %edx, %eax -; BMI-NEXT: incl %eax +; BMI-NEXT: leal 1(%rdx,%rax), %eax ; BMI-NEXT: retq entry: %and1 = and i32 %z, %y @@ -172,10 +172,10 @@ ; ; BMI-LABEL: or_and_and_lhs_neg_i32: ; BMI: # %bb.0: # %entry +; BMI-NEXT: # kill: def $edx killed $edx def $rdx ; BMI-NEXT: andl %esi, %edx ; BMI-NEXT: andnl %edi, %esi, %eax -; BMI-NEXT: orl %edx, %eax -; BMI-NEXT: incl %eax +; BMI-NEXT: leal 1(%rdx,%rax), %eax ; BMI-NEXT: retq entry: %and1 = and i32 %z, %y @@ -198,10 +198,10 @@ ; ; BMI-LABEL: or_and_rhs_neg_and_i32: ; BMI: # %bb.0: # %entry +; BMI-NEXT: # kill: def $edi killed $edi def $rdi ; BMI-NEXT: andnl %edx, %esi, %eax ; BMI-NEXT: andl %esi, %edi -; BMI-NEXT: orl %edi, %eax -; BMI-NEXT: incl %eax +; BMI-NEXT: leal 1(%rax,%rdi), %eax ; BMI-NEXT: retq entry: %xor = xor i32 %y, -1 @@ -224,10 +224,10 @@ ; ; BMI-LABEL: or_and_lhs_neg_and_i32: ; BMI: # %bb.0: # %entry +; BMI-NEXT: # kill: def $edi killed $edi def $rdi ; BMI-NEXT: andnl %edx, %esi, %eax ; BMI-NEXT: andl %esi, %edi -; BMI-NEXT: orl %edi, %eax -; BMI-NEXT: incl %eax +; BMI-NEXT: leal 1(%rax,%rdi), %eax ; BMI-NEXT: retq entry: %xor = xor i32 %y, -1 @@ -251,8 +251,7 @@ ; BMI: # %bb.0: # %entry ; BMI-NEXT: andq %rsi, %rdx ; BMI-NEXT: andnq %rdi, %rsi, %rax -; BMI-NEXT: orq %rdx, %rax -; BMI-NEXT: incq %rax +; BMI-NEXT: leaq 1(%rdx,%rax), %rax ; BMI-NEXT: retq entry: %and1 = and i64 %z, %y @@ -276,8 +275,7 @@ ; BMI: # %bb.0: # %entry ; BMI-NEXT: andq %rsi, %rdx ; BMI-NEXT: andnq %rdi, %rsi, %rax -; BMI-NEXT: orq %rdx, %rax -; BMI-NEXT: incq %rax +; BMI-NEXT: leaq 1(%rdx,%rax), %rax ; BMI-NEXT: retq entry: %and1 = and i64 %z, %y @@ -301,8 +299,7 @@ ; BMI: # %bb.0: # %entry ; BMI-NEXT: andnq %rdx, %rsi, %rax ; BMI-NEXT: andq %rsi, %rdi -; BMI-NEXT: orq %rdi, %rax -; BMI-NEXT: incq %rax +; BMI-NEXT: leaq 1(%rax,%rdi), %rax ; BMI-NEXT: retq entry: %xor = xor i64 %y, -1 @@ -326,8 +323,7 @@ ; BMI: # %bb.0: # %entry ; BMI-NEXT: andnq %rdx, %rsi, %rax ; BMI-NEXT: andq %rsi, %rdi -; BMI-NEXT: orq %rdi, %rax -; BMI-NEXT: incq %rax +; BMI-NEXT: leaq 1(%rax,%rdi), %rax ; BMI-NEXT: retq entry: %xor = xor i64 %y, -1 Index: llvm/test/CodeGen/X86/vec_no-common-bits.ll =================================================================== --- llvm/test/CodeGen/X86/vec_no-common-bits.ll +++ llvm/test/CodeGen/X86/vec_no-common-bits.ll @@ -7,12 +7,7 @@ define <2 x i32> @or_and_and_rhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) { ; CHECK-LABEL: or_and_and_rhs_neg_vec_i32: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm2 -; CHECK-NEXT: pandn %xmm0, %xmm1 -; CHECK-NEXT: movdqa %xmm2, %xmm0 -; CHECK-NEXT: por %xmm1, %xmm0 -; CHECK-NEXT: paddd %xmm2, %xmm1 -; CHECK-NEXT: psubd %xmm1, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %and1 = and <2 x i32> %z, %y %xor = xor <2 x i32> %y, @@ -26,12 +21,7 @@ define <2 x i32> @or_and_and_lhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) { ; CHECK-LABEL: or_and_and_lhs_neg_vec_i32: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm2 -; CHECK-NEXT: pandn %xmm0, %xmm1 -; CHECK-NEXT: movdqa %xmm2, %xmm0 -; CHECK-NEXT: por %xmm1, %xmm0 -; CHECK-NEXT: paddd %xmm2, %xmm1 -; CHECK-NEXT: psubd %xmm1, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %and1 = and <2 x i32> %z, %y %xor = xor <2 x i32> %y, @@ -45,13 +35,7 @@ define <2 x i32> @or_and_rhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) { ; CHECK-LABEL: or_and_rhs_neg_and_vec_i32: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm0 -; CHECK-NEXT: pandn %xmm2, %xmm1 -; CHECK-NEXT: movdqa %xmm1, %xmm2 -; CHECK-NEXT: por %xmm0, %xmm2 -; CHECK-NEXT: paddd %xmm0, %xmm1 -; CHECK-NEXT: psubd %xmm1, %xmm2 -; CHECK-NEXT: movdqa %xmm2, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %xor = xor <2 x i32> %y, %and1 = and <2 x i32> %z, %xor @@ -65,13 +49,7 @@ define <2 x i32> @or_and_lhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) { ; CHECK-LABEL: or_and_lhs_neg_and_vec_i32: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm0 -; CHECK-NEXT: pandn %xmm2, %xmm1 -; CHECK-NEXT: movdqa %xmm1, %xmm2 -; CHECK-NEXT: por %xmm0, %xmm2 -; CHECK-NEXT: paddd %xmm0, %xmm1 -; CHECK-NEXT: psubd %xmm1, %xmm2 -; CHECK-NEXT: movdqa %xmm2, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %xor = xor <2 x i32> %y, %and1 = and <2 x i32> %xor, %z @@ -85,12 +63,7 @@ define <2 x i64> @or_and_and_rhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) { ; CHECK-LABEL: or_and_and_rhs_neg_vec_i64: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm2 -; CHECK-NEXT: pandn %xmm0, %xmm1 -; CHECK-NEXT: movdqa %xmm2, %xmm0 -; CHECK-NEXT: por %xmm1, %xmm0 -; CHECK-NEXT: paddq %xmm2, %xmm1 -; CHECK-NEXT: psubq %xmm1, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %and1 = and <2 x i64> %z, %y %xor = xor <2 x i64> %y, @@ -104,12 +77,7 @@ define <2 x i64> @or_and_and_lhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) { ; CHECK-LABEL: or_and_and_lhs_neg_vec_i64: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm2 -; CHECK-NEXT: pandn %xmm0, %xmm1 -; CHECK-NEXT: movdqa %xmm2, %xmm0 -; CHECK-NEXT: por %xmm1, %xmm0 -; CHECK-NEXT: paddq %xmm2, %xmm1 -; CHECK-NEXT: psubq %xmm1, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %and1 = and <2 x i64> %z, %y %xor = xor <2 x i64> %y, @@ -123,13 +91,7 @@ define <2 x i64> @or_and_rhs_neg_and_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) { ; CHECK-LABEL: or_and_rhs_neg_and_vec_i64: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm0 -; CHECK-NEXT: pandn %xmm2, %xmm1 -; CHECK-NEXT: movdqa %xmm1, %xmm2 -; CHECK-NEXT: por %xmm0, %xmm2 -; CHECK-NEXT: paddq %xmm0, %xmm1 -; CHECK-NEXT: psubq %xmm1, %xmm2 -; CHECK-NEXT: movdqa %xmm2, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %xor = xor <2 x i64> %y, %and1 = and <2 x i64> %z, %xor @@ -143,13 +105,7 @@ define <2 x i64> @or_and_lhs_neg_and_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) { ; CHECK-LABEL: or_and_lhs_neg_and_vec_i64: ; CHECK: # %bb.0: -; CHECK-NEXT: pand %xmm1, %xmm0 -; CHECK-NEXT: pandn %xmm2, %xmm1 -; CHECK-NEXT: movdqa %xmm1, %xmm2 -; CHECK-NEXT: por %xmm0, %xmm2 -; CHECK-NEXT: paddq %xmm0, %xmm1 -; CHECK-NEXT: psubq %xmm1, %xmm2 -; CHECK-NEXT: movdqa %xmm2, %xmm0 +; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq %xor = xor <2 x i64> %y, %and1 = and <2 x i64> %xor, %z