[ValueTracking] Fix computeConstantRange to use "may" instead of "always" semantics for llvm.assume

ValueTracking should allow for value ranges that may satisfy
llvm.assume, instead of restricting the ranges only to values that
will always satisfy the condition.

Differential Revision: https://reviews.llvm.org/D107298
This commit is contained in:
Chang-Sun Lin, Jr 2021-08-02 22:18:13 +02:00 committed by Nikita Popov
parent 739efad3f6
commit b58eda39eb
2 changed files with 37 additions and 9 deletions

View File

@ -7037,7 +7037,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
ConstantRange RHS = computeConstantRange(Cmp->getOperand(1), UseInstrInfo,
AC, I, Depth + 1);
CR = CR.intersectWith(
ConstantRange::makeSatisfyingICmpRegion(Cmp->getPredicate(), RHS));
ConstantRange::makeAllowedICmpRegion(Cmp->getPredicate(), RHS));
}
}

View File

@ -2073,7 +2073,7 @@ TEST_F(ValueTrackingTest, ComputeConstantRange) {
// * x.1 >= 5
// * x.2 < x.1
//
// stride = [0, 5)
// stride = [0, -1)
auto M = parseModule(R"(
declare void @llvm.assume(i1)
@ -2087,18 +2087,46 @@ TEST_F(ValueTrackingTest, ComputeConstantRange) {
})");
Function *F = M->getFunction("test");
AssumptionCache AC(*F);
Value *X1 = &*(F->arg_begin());
Value *X2 = &*std::next(F->arg_begin());
Instruction *I = &findInstructionByName(F, "stride.plus.one");
ConstantRange CR1 = computeConstantRange(X1, true, &AC, I);
ConstantRange CR2 = computeConstantRange(X2, true, &AC, I);
EXPECT_EQ(5, CR1.getLower());
EXPECT_EQ(0, CR1.getUpper());
EXPECT_EQ(0, CR2.getLower());
EXPECT_EQ(0xffffffff, CR2.getUpper());
// Check the depth cutoff results in a conservative result (full set) by
// passing Depth == MaxDepth == 6.
ConstantRange CR3 = computeConstantRange(X2, true, &AC, I, 6);
EXPECT_TRUE(CR3.isFullSet());
}
{
// Assumptions:
// * x.2 <= x.1
auto M = parseModule(R"(
declare void @llvm.assume(i1)
define i32 @test(i32 %x.1, i32 %x.2) {
%lt = icmp ule i32 %x.2, %x.1
call void @llvm.assume(i1 %lt)
%stride.plus.one = add nsw nuw i32 %x.1, 1
ret i32 %stride.plus.one
})");
Function *F = M->getFunction("test");
AssumptionCache AC(*F);
Value *X2 = &*std::next(F->arg_begin());
Instruction *I = &findInstructionByName(F, "stride.plus.one");
ConstantRange CR1 = computeConstantRange(X2, true, &AC, I);
EXPECT_EQ(0, CR1.getLower());
EXPECT_EQ(5, CR1.getUpper());
// Check the depth cutoff results in a conservative result (full set) by
// passing Depth == MaxDepth == 6.
ConstantRange CR2 = computeConstantRange(X2, true, &AC, I, 6);
EXPECT_TRUE(CR2.isFullSet());
// If we don't know the value of x.2, we don't know the value of x.1.
EXPECT_TRUE(CR1.isFullSet());
}
}