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 A, SDValue B) { + if (isBitwiseNot(A, true)) { + SDValue NotOperand = A->getOperand(0); + return (NotOperand == B->getOperand(0) || + NotOperand == B->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 @@ -137,20 +137,20 @@ define i32 @or_and_and_rhs_neg_i32(i32 %x, i32 %y, i32 %z) { ; NOBMI-LABEL: or_and_and_rhs_neg_i32: ; NOBMI: # %bb.0: # %entry +; NOBMI-NEXT: # kill: def $edx killed $edx def $rdx ; NOBMI-NEXT: # kill: def $esi killed $esi def $rsi ; NOBMI-NEXT: andl %esi, %edx ; NOBMI-NEXT: notl %esi ; NOBMI-NEXT: andl %edi, %esi -; NOBMI-NEXT: orl %edx, %esi -; NOBMI-NEXT: leal 1(%rsi), %eax +; NOBMI-NEXT: leal 1(%rdx,%rsi), %eax ; NOBMI-NEXT: retq ; ; 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 @@ -164,20 +164,20 @@ define i32 @or_and_and_lhs_neg_i32(i32 %x, i32 %y, i32 %z) { ; NOBMI-LABEL: or_and_and_lhs_neg_i32: ; NOBMI: # %bb.0: # %entry +; NOBMI-NEXT: # kill: def $edx killed $edx def $rdx ; NOBMI-NEXT: # kill: def $esi killed $esi def $rsi ; NOBMI-NEXT: andl %esi, %edx ; NOBMI-NEXT: notl %esi ; NOBMI-NEXT: andl %edi, %esi -; NOBMI-NEXT: orl %edx, %esi -; NOBMI-NEXT: leal 1(%rsi), %eax +; NOBMI-NEXT: leal 1(%rdx,%rsi), %eax ; NOBMI-NEXT: retq ; ; 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 @@ -192,19 +192,19 @@ ; NOBMI-LABEL: or_and_rhs_neg_and_i32: ; NOBMI: # %bb.0: # %entry ; NOBMI-NEXT: # kill: def $esi killed $esi def $rsi +; NOBMI-NEXT: # kill: def $edi killed $edi def $rdi ; NOBMI-NEXT: andl %esi, %edi ; NOBMI-NEXT: notl %esi ; NOBMI-NEXT: andl %edx, %esi -; NOBMI-NEXT: orl %edi, %esi -; NOBMI-NEXT: leal 1(%rsi), %eax +; NOBMI-NEXT: leal 1(%rsi,%rdi), %eax ; NOBMI-NEXT: retq ; ; 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 @@ -219,19 +219,19 @@ ; NOBMI-LABEL: or_and_lhs_neg_and_i32: ; NOBMI: # %bb.0: # %entry ; NOBMI-NEXT: # kill: def $esi killed $esi def $rsi +; NOBMI-NEXT: # kill: def $edi killed $edi def $rdi ; NOBMI-NEXT: andl %esi, %edi ; NOBMI-NEXT: notl %esi ; NOBMI-NEXT: andl %edx, %esi -; NOBMI-NEXT: orl %edi, %esi -; NOBMI-NEXT: leal 1(%rsi), %eax +; NOBMI-NEXT: leal 1(%rsi,%rdi), %eax ; NOBMI-NEXT: retq ; ; 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 @@ -248,16 +248,14 @@ ; NOBMI-NEXT: andq %rsi, %rdx ; NOBMI-NEXT: notq %rsi ; NOBMI-NEXT: andq %rdi, %rsi -; NOBMI-NEXT: orq %rdx, %rsi -; NOBMI-NEXT: leaq 1(%rsi), %rax +; NOBMI-NEXT: leaq 1(%rdx,%rsi), %rax ; NOBMI-NEXT: retq ; ; BMI-LABEL: or_and_and_rhs_neg_i64: ; 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 @@ -274,16 +272,14 @@ ; NOBMI-NEXT: andq %rsi, %rdx ; NOBMI-NEXT: notq %rsi ; NOBMI-NEXT: andq %rdi, %rsi -; NOBMI-NEXT: orq %rdx, %rsi -; NOBMI-NEXT: leaq 1(%rsi), %rax +; NOBMI-NEXT: leaq 1(%rdx,%rsi), %rax ; NOBMI-NEXT: retq ; ; BMI-LABEL: or_and_and_lhs_neg_i64: ; 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 @@ -300,16 +296,14 @@ ; NOBMI-NEXT: andq %rsi, %rdi ; NOBMI-NEXT: notq %rsi ; NOBMI-NEXT: andq %rdx, %rsi -; NOBMI-NEXT: orq %rdi, %rsi -; NOBMI-NEXT: leaq 1(%rsi), %rax +; NOBMI-NEXT: leaq 1(%rsi,%rdi), %rax ; NOBMI-NEXT: retq ; ; BMI-LABEL: or_and_rhs_neg_and_i64: ; 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,16 +320,14 @@ ; NOBMI-NEXT: andq %rsi, %rdi ; NOBMI-NEXT: notq %rsi ; NOBMI-NEXT: andq %rdx, %rsi -; NOBMI-NEXT: orq %rdi, %rsi -; NOBMI-NEXT: leaq 1(%rsi), %rax +; NOBMI-NEXT: leaq 1(%rsi,%rdi), %rax ; NOBMI-NEXT: retq ; ; BMI-LABEL: or_and_lhs_neg_and_i64: ; 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: paddd %xmm2, %xmm1 -; CHECK-NEXT: psubd %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: paddd %xmm2, %xmm1 -; CHECK-NEXT: psubd %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: 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 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: 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 i64> %y, %and1 = and <2 x i64> %xor, %z