Skip to content

Commit 5777d5d

Browse files
nikictstellar
authored andcommitted
[ValueTracking] Fix bit width handling in computeKnownBits() for GEPs (#125532)
For GEPs, we have three bit widths involved: The pointer bit width, the index bit width, and the bit width of the GEP operands. The correct behavior here is: * We need to sextOrTrunc the GEP operand to the index width *before* multiplying by the scale. * If the index width and pointer width differ, GEP only ever modifies the low bits. Adds should not overflow into the high bits. I'm testing this via unit tests because it's a bit tricky to test in IR with InstCombine canonicalization getting in the way. (cherry picked from commit 3bd11b5)
1 parent a89e04e commit 5777d5d

File tree

2 files changed

+42
-36
lines changed

2 files changed

+42
-36
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,22 @@ static void computeKnownBitsFromOperator(const Operator *I,
14451445
computeKnownBits(I->getOperand(0), Known, Depth + 1, Q);
14461446
// Accumulate the constant indices in a separate variable
14471447
// to minimize the number of calls to computeForAddSub.
1448-
APInt AccConstIndices(BitWidth, 0, /*IsSigned*/ true);
1448+
unsigned IndexWidth = Q.DL.getIndexTypeSizeInBits(I->getType());
1449+
APInt AccConstIndices(IndexWidth, 0);
1450+
1451+
auto AddIndexToKnown = [&](KnownBits IndexBits) {
1452+
if (IndexWidth == BitWidth) {
1453+
// Note that inbounds does *not* guarantee nsw for the addition, as only
1454+
// the offset is signed, while the base address is unsigned.
1455+
Known = KnownBits::add(Known, IndexBits);
1456+
} else {
1457+
// If the index width is smaller than the pointer width, only add the
1458+
// value to the low bits.
1459+
assert(IndexWidth < BitWidth &&
1460+
"Index width can't be larger than pointer width");
1461+
Known.insertBits(KnownBits::add(Known.trunc(IndexWidth), IndexBits), 0);
1462+
}
1463+
};
14491464

14501465
gep_type_iterator GTI = gep_type_begin(I);
14511466
for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i, ++GTI) {
@@ -1483,43 +1498,34 @@ static void computeKnownBitsFromOperator(const Operator *I,
14831498
break;
14841499
}
14851500

1486-
unsigned IndexBitWidth = Index->getType()->getScalarSizeInBits();
1487-
KnownBits IndexBits(IndexBitWidth);
1488-
computeKnownBits(Index, IndexBits, Depth + 1, Q);
1489-
TypeSize IndexTypeSize = GTI.getSequentialElementStride(Q.DL);
1490-
uint64_t TypeSizeInBytes = IndexTypeSize.getKnownMinValue();
1491-
KnownBits ScalingFactor(IndexBitWidth);
1501+
TypeSize Stride = GTI.getSequentialElementStride(Q.DL);
1502+
uint64_t StrideInBytes = Stride.getKnownMinValue();
1503+
if (!Stride.isScalable()) {
1504+
// Fast path for constant offset.
1505+
if (auto *CI = dyn_cast(Index)) {
1506+
AccConstIndices +=
1507+
CI->getValue().sextOrTrunc(IndexWidth) * StrideInBytes;
1508+
continue;
1509+
}
1510+
}
1511+
1512+
KnownBits IndexBits =
1513+
computeKnownBits(Index, Depth + 1, Q).sextOrTrunc(IndexWidth);
1514+
KnownBits ScalingFactor(IndexWidth);
14921515
// Multiply by current sizeof type.
14931516
// &A[i] == A + i * sizeof(*A[i]).
1494-
if (IndexTypeSize.isScalable()) {
1517+
if (Stride.isScalable()) {
14951518
// For scalable types the only thing we know about sizeof is
14961519
// that this is a multiple of the minimum size.
1497-
ScalingFactor.Zero.setLowBits(llvm::countr_zero(TypeSizeInBytes));
1498-
} else if (IndexBits.isConstant()) {
1499-
APInt IndexConst = IndexBits.getConstant();
1500-
APInt ScalingFactor(IndexBitWidth, TypeSizeInBytes);
1501-
IndexConst *= ScalingFactor;
1502-
AccConstIndices += IndexConst.sextOrTrunc(BitWidth);
1503-
continue;
1520+
ScalingFactor.Zero.setLowBits(llvm::countr_zero(StrideInBytes));
15041521
} else {
15051522
ScalingFactor =
1506-
KnownBits::makeConstant(APInt(IndexBitWidth, TypeSizeInBytes));
1523+
KnownBits::makeConstant(APInt(IndexWidth, StrideInBytes));
15071524
}
1508-
IndexBits = KnownBits::mul(IndexBits, ScalingFactor);
1509-
1510-
// If the offsets have a different width from the pointer, according
1511-
// to the language reference we need to sign-extend or truncate them
1512-
// to the width of the pointer.
1513-
IndexBits = IndexBits.sextOrTrunc(BitWidth);
1514-
1515-
// Note that inbounds does *not* guarantee nsw for the addition, as only
1516-
// the offset is signed, while the base address is unsigned.
1517-
Known = KnownBits::add(Known, IndexBits);
1518-
}
1519-
if (!Known.isUnknown() && !AccConstIndices.isZero()) {
1520-
KnownBits Index = KnownBits::makeConstant(AccConstIndices);
1521-
Known = KnownBits::add(Known, Index);
1525+
AddIndexToKnown(KnownBits::mul(IndexBits, ScalingFactor));
15221526
}
1527+
if (!Known.isUnknown() && !AccConstIndices.isZero())
1528+
AddIndexToKnown(KnownBits::makeConstant(AccConstIndices));
15231529
break;
15241530
}
15251531
case Instruction::PHI: {

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,7 +2680,7 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownBitsAbsoluteSymbol) {
26802680
}
26812681

26822682
TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPExtendBeforeMul) {
2683-
// FIXME: The index should be extended before multiplying with the scale.
2683+
// The index should be extended before multiplying with the scale.
26842684
parseAssembly(R"(
26852685
target datalayout = "p:16:16:16"
26862686
@@ -2692,12 +2692,12 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPExtendBeforeMul) {
26922692
}
26932693
)");
26942694
KnownBits Known = computeKnownBits(A, M->getDataLayout());
2695-
EXPECT_EQ(~64 & 0x7fff, Known.Zero);
2696-
EXPECT_EQ(64, Known.One);
2695+
EXPECT_EQ(~320 & 0x7fff, Known.Zero);
2696+
EXPECT_EQ(320, Known.One);
26972697
}
26982698

26992699
TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPOnlyIndexBits) {
2700-
// FIXME: GEP should only affect the index width.
2700+
// GEP should only affect the index width.
27012701
parseAssembly(R"(
27022702
target datalayout = "p:16:16:16:8"
27032703
@@ -2710,8 +2710,8 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownBitsGEPOnlyIndexBits) {
27102710
}
27112711
)");
27122712
KnownBits Known = computeKnownBits(A, M->getDataLayout());
2713-
EXPECT_EQ(0x7eff, Known.Zero);
2714-
EXPECT_EQ(0x100, Known.One);
2713+
EXPECT_EQ(0x7fff, Known.Zero);
2714+
EXPECT_EQ(0, Known.One);
27152715
}
27162716

27172717
TEST_F(ValueTrackingTest, HaveNoCommonBitsSet) {

0 commit comments

Comments
 (0)