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 @@ -2907,39 +2907,11 @@ LLVM_FALLTHROUGH; case ISD::SUB: case ISD::SUBC: { - if (ConstantSDNode *CLHS = isConstOrConstSplat(Op.getOperand(0))) { - // We know that the top bits of C-X are clear if X contains less bits - // than C (i.e. no wrap-around can happen). For example, 20-X is - // positive if we can prove that X is >= 0 and < 16. - if (CLHS->getAPIntValue().isNonNegative()) { - unsigned NLZ = (CLHS->getAPIntValue()+1).countLeadingZeros(); - // NLZ can't be BitWidth with no sign bit - APInt MaskV = APInt::getHighBitsSet(BitWidth, NLZ+1); - Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, - Depth + 1); - - // If all of the MaskV bits are known to be zero, then we know the - // output top bits are zero, because we now know that the output is - // from [0-C]. - if ((Known2.Zero & MaskV) == MaskV) { - unsigned NLZ2 = CLHS->getAPIntValue().countLeadingZeros(); - // Top bits known zero. - Known.Zero.setHighBits(NLZ2); - } - } - } - - // If low bits are know to be zero in both operands, then we know they are - // going to be 0 in the result. Both addition and complement operations - // preserve the low zero bits. - Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); - unsigned KnownZeroLow = Known2.countMinTrailingZeros(); - if (KnownZeroLow == 0) - break; - + KnownBits KnownLHS(BitWidth); + KnownLHS = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - KnownZeroLow = std::min(KnownZeroLow, Known2.countMinTrailingZeros()); - Known.Zero.setLowBits(KnownZeroLow); + Known = KnownBits::computeForAddSub(/* IsSub */ false, /* NSW */ false, + KnownLHS, Known2); break; } case ISD::UADDO: @@ -2957,22 +2929,16 @@ case ISD::ADD: case ISD::ADDC: case ISD::ADDE: { - // Output known-0 bits are known if clear or set in both the low clear bits - // common to both LHS & RHS. For example, 8+(X<<3) is known to have the - // low 3 bits clear. - // Output known-0 bits are also known if the top bits of each input are - // known to be clear. For example, if one input has the top 10 bits clear - // and the other has the top 8 bits clear, we know the top 7 bits of the - // output must be clear. - Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); - unsigned KnownZeroHigh = Known2.countMinLeadingZeros(); - unsigned KnownZeroLow = Known2.countMinTrailingZeros(); - + KnownBits KnownLHS(BitWidth); + KnownLHS = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - KnownZeroHigh = std::min(KnownZeroHigh, Known2.countMinLeadingZeros()); - KnownZeroLow = std::min(KnownZeroLow, Known2.countMinTrailingZeros()); if (Opcode == ISD::ADDE || Opcode == ISD::ADDCARRY) { + // Output known-0 bits are known if clear or set in both the low clear + // bits common to both LHS & RHS. For example, 8+(X<<3) is known to have + // the low 3 bits clear. + unsigned KnownZeroLow = std::min(KnownLHS.countMinTrailingZeros(), + Known2.countMinTrailingZeros()); // With ADDE and ADDCARRY, a carry bit may be added in, so we can only // use this information if we know (at least) that the low two bits are // clear. We then return to the caller that the low bit is unknown but @@ -2982,9 +2948,8 @@ break; } - Known.Zero.setLowBits(KnownZeroLow); - if (KnownZeroHigh > 1) - Known.Zero.setHighBits(KnownZeroHigh - 1); + Known = KnownBits::computeForAddSub(/* IsAdd */ true, /* NSW */ false, + KnownLHS, Known2); break; } case ISD::SREM: 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 diff --git a/llvm/test/CodeGen/X86/x32-va_start.ll b/llvm/test/CodeGen/X86/x32-va_start.ll --- a/llvm/test/CodeGen/X86/x32-va_start.ll +++ b/llvm/test/CodeGen/X86/x32-va_start.ll @@ -58,7 +58,12 @@ store i32 %3, i32* %gp_offset_p, align 16 br label %vaarg.end ; CHECK: movl {{[^,]*}}, [[ADDR:.*]] -; CHECK: addl [[COUNT]], [[ADDR]] + +; Nowadays we can do value tracking through CopyFromReg, so we know that +; [[COUNT]] is $8 here (we actually get "cmpl $40, $8" when catching [[COUNT]] +; above), and constant folding is expected in the addl and movl below. +; CHECK: addl $8, [[ADDR]] +; CHECK: movl $16, ; SSE: jmp .[[END:.*]] ; NOSSE: movl ([[ADDR]]), %eax ; NOSSE: retq diff --git a/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp b/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp --- a/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp +++ b/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp @@ -157,4 +157,47 @@ false); } +// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. +TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_ADD) { + if (!TM) + return; + SDLoc Loc; + auto IntVT = EVT::getIntegerVT(Context, 8); + auto UnknownOp = DAG->getRegister(0, IntVT); + auto Mask = DAG->getConstant(0x8A, Loc, IntVT); + auto N0 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp); + auto N1 = DAG->getConstant(0x55, Loc, IntVT); + auto Op = DAG->getNode(ISD::ADD, Loc, IntVT, N0, N1); + // N0 = ?000?0?0 + // N1 = 01010101 + // => + // Known.One = 01010101 (0x55) + // Known.Zero = 00100000 (0x20) + KnownBits Known = DAG->computeKnownBits(Op); + EXPECT_EQ(Known.Zero, APInt(8, 0x20)); + EXPECT_EQ(Known.One, APInt(8, 0x55)); +} + +// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. +TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SUB) { + if (!TM) + return; + SDLoc Loc; + auto IntVT = EVT::getIntegerVT(Context, 8); + auto N0 = DAG->getConstant(0x55, Loc, IntVT); + auto UnknownOp = DAG->getRegister(0, IntVT); + auto Mask = DAG->getConstant(0x2e, Loc, IntVT); + auto N1 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp); + auto Op = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1); + // N0 = 01010101 + // N1 = 00?0???0 + // => + // Known.One = 00000001 (0x1) + // Known.Zero = 10000000 (0x80) + KnownBits Known = DAG->computeKnownBits(Op); + EXPECT_EQ(Known.Zero, APInt(8, 0x80)); + EXPECT_EQ(Known.One, APInt(8, 0x1)); +} + + } // end anonymous namespace