diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2968,9 +2968,10 @@ unsigned KnownZeroHigh = Known2.countMinLeadingZeros(); unsigned KnownZeroLow = Known2.countMinTrailingZeros(); - Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - KnownZeroHigh = std::min(KnownZeroHigh, Known2.countMinLeadingZeros()); - KnownZeroLow = std::min(KnownZeroLow, Known2.countMinTrailingZeros()); + KnownBits Known3; + Known3 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + KnownZeroHigh = std::min(KnownZeroHigh, Known3.countMinLeadingZeros()); + KnownZeroLow = std::min(KnownZeroLow, Known3.countMinTrailingZeros()); if (Opcode == ISD::ADDE || Opcode == ISD::ADDCARRY) { // With ADDE and ADDCARRY, a carry bit may be added in, so we can only @@ -2982,6 +2983,17 @@ break; } + if (Opcode == ISD::ADD && (Known2.Zero | Known3.Zero).isAllOnesValue()) { + // This ADD can be treated just like an OR (no common bits set in the + // operands).. + Known = Known3; + // Output known-0 bits are only known if clear in both the LHS & RHS. + Known.Zero &= Known2.Zero; + // Output known-1 are known to be set if set in either the LHS | RHS. + Known.One |= Known2.One; + break; + } + Known.Zero.setLowBits(KnownZeroLow); if (KnownZeroHigh > 1) Known.Zero.setHighBits(KnownZeroHigh - 1); diff --git a/llvm/test/CodeGen/X86/pr32282.ll b/llvm/test/CodeGen/X86/pr32282.ll --- a/llvm/test/CodeGen/X86/pr32282.ll +++ b/llvm/test/CodeGen/X86/pr32282.ll @@ -13,19 +13,18 @@ ; X86-LABEL: foo: ; X86: # %bb.0: ; X86-NEXT: pushl %eax -; X86-NEXT: movl d, %eax +; X86-NEXT: movl d+4, %eax ; X86-NEXT: notl %eax -; X86-NEXT: movl d+4, %ecx +; X86-NEXT: movl d, %ecx ; X86-NEXT: notl %ecx -; X86-NEXT: andl $701685459, %ecx # imm = 0x29D2DED3 -; X86-NEXT: andl $-564453154, %eax # imm = 0xDE5B20DE -; X86-NEXT: shrdl $21, %ecx, %eax -; X86-NEXT: shrl $21, %ecx -; X86-NEXT: andl $-2, %eax -; X86-NEXT: addl $7, %eax -; X86-NEXT: adcl $0, %ecx -; X86-NEXT: pushl %ecx +; X86-NEXT: andl $-566231040, %ecx # imm = 0xDE400000 +; X86-NEXT: andl $701685459, %eax # imm = 0x29D2DED3 +; X86-NEXT: shrdl $21, %eax, %ecx +; X86-NEXT: shrl $21, %eax +; X86-NEXT: addl $7, %ecx +; X86-NEXT: adcl $0, %eax ; X86-NEXT: pushl %eax +; X86-NEXT: pushl %ecx ; X86-NEXT: pushl {{[0-9]+}}(%esp) ; X86-NEXT: pushl {{[0-9]+}}(%esp) ; X86-NEXT: calll __divdi3