[llvm] r358372 - [SelectionDAG] Use KnownBits::computeForAddSub/computeForAddCarry
Bjorn Pettersson via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 15 00:19:11 PDT 2019
Author: bjope
Date: Mon Apr 15 00:19:11 2019
New Revision: 358372
URL: http://llvm.org/viewvc/llvm-project?rev=358372&view=rev
Log:
[SelectionDAG] Use KnownBits::computeForAddSub/computeForAddCarry
Summary:
Use KnownBits::computeForAddSub/computeForAddCarry
in SelectionDAG::computeKnownBits when doing value
tracking for addition/subtraction.
This should improve the precision of the known bits,
as we only used to make a simple estimate of known
zeroes. The KnownBits support functions are also
able to deduce bits that are known to be one in the
result.
Reviewers: spatel, RKSimon, nikic, lebedev.ri
Reviewed By: nikic
Subscribers: nikic, javed.absar, lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60460
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/trunk/test/CodeGen/X86/pr32282.ll
llvm/trunk/unittests/CodeGen/AArch64SelectionDAGTest.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=358372&r1=358371&r2=358372&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 15 00:19:11 2019
@@ -2906,39 +2906,10 @@ KnownBits SelectionDAG::computeKnownBits
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;
-
+ Known = 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(/* Add */ false, /* NSW */ false,
+ Known, Known2);
break;
}
case ISD::UADDO:
@@ -2956,34 +2927,26 @@ KnownBits SelectionDAG::computeKnownBits
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();
+ assert(Op.getResNo() == 0 && "We only compute knownbits for the sum here.");
- Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
- KnownZeroHigh = std::min(KnownZeroHigh, Known2.countMinLeadingZeros());
- KnownZeroLow = std::min(KnownZeroLow, Known2.countMinTrailingZeros());
+ // With ADDE and ADDCARRY, a carry bit may be added in.
+ KnownBits Carry(1);
+ if (Opcode == ISD::ADDE)
+ // Can't track carry from glue, set carry to unknown.
+ Carry.resetAll();
+ else if (Opcode == ISD::ADDCARRY)
+ // TODO: Compute known bits for the carry operand. Not sure if it is worth
+ // the trouble (how often will we find a known carry bit). And I haven't
+ // tested this very much yet, but something like this might work:
+ // Carry = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);
+ // Carry = Carry.zextOrTrunc(1, false);
+ Carry.resetAll();
+ else
+ Carry.setAllZero();
- if (Opcode == ISD::ADDE || Opcode == ISD::ADDCARRY) {
- // 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
- // that other bits are known zero.
- if (KnownZeroLow >= 2)
- Known.Zero.setBits(1, KnownZeroLow);
- break;
- }
-
- Known.Zero.setLowBits(KnownZeroLow);
- if (KnownZeroHigh > 1)
- Known.Zero.setHighBits(KnownZeroHigh - 1);
+ Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
+ Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
+ Known = KnownBits::computeForAddCarry(Known, Known2, Carry);
break;
}
case ISD::SREM:
Modified: llvm/trunk/test/CodeGen/X86/pr32282.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr32282.ll?rev=358372&r1=358371&r2=358372&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/pr32282.ll (original)
+++ llvm/trunk/test/CodeGen/X86/pr32282.ll Mon Apr 15 00:19:11 2019
@@ -13,19 +13,18 @@ define void @foo(i64 %x) nounwind {
; 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
Modified: llvm/trunk/unittests/CodeGen/AArch64SelectionDAGTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/AArch64SelectionDAGTest.cpp?rev=358372&r1=358371&r2=358372&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/AArch64SelectionDAGTest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/AArch64SelectionDAGTest.cpp Mon Apr 15 00:19:11 2019
@@ -157,4 +157,46 @@ TEST_F(AArch64SelectionDAGTest, Simplify
false);
}
+// Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits.
+TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_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, ComputeKnownBits_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
More information about the llvm-commits
mailing list