mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-21 18:22:53 +01:00
[unittest] Exercise SCEV's udiv and udiv ceiling routines
The ceiling variant was recently added (due to the work towards D105216), and we're spending a lot of time trying to find optimizations for the expression. This patch brute forces the space of i8 unsigned divides and checks that we get a correct (well consistent with APInt) result for both udiv and udiv ceiling. (This is basically what I've been doing locally in a hand rolled C++ program, and I realized there no good reason not to check it in as a unit test which directly exercises the logic on constants.) Differential Revision: https://reviews.llvm.org/D106083
This commit is contained in:
parent
ff55ad2c7b
commit
a74c4e37ae
@ -643,6 +643,16 @@ public:
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// Compute ceil(N / D). N and D are treated as unsigned values.
|
||||
///
|
||||
/// Since SCEV doesn't have native ceiling division, this generates a
|
||||
/// SCEV expression of the following form:
|
||||
///
|
||||
/// umin(N, 1) + floor((N - umin(N, 1)) / D)
|
||||
///
|
||||
/// A denominator of zero or poison is handled the same way as getUDivExpr().
|
||||
const SCEV *getUDivCeilSCEV(const SCEV *N, const SCEV *D);
|
||||
|
||||
/// Return a SCEV corresponding to a conversion of the input value to the
|
||||
/// specified type. If the type must be extended, it is zero extended.
|
||||
const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
|
||||
@ -2029,16 +2039,6 @@ private:
|
||||
/// that the result is undefined if it does.
|
||||
const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride);
|
||||
|
||||
/// Compute ceil(N / D). N and D are treated as unsigned values.
|
||||
///
|
||||
/// Since SCEV doesn't have native ceiling division, this generates a
|
||||
/// SCEV expression of the following form:
|
||||
///
|
||||
/// umin(N, 1) + floor((N - umin(N, 1)) / D)
|
||||
///
|
||||
/// A denominator of zero or poison is handled the same way as getUDivExpr().
|
||||
const SCEV *getUDivCeilSCEV(const SCEV *N, const SCEV *D);
|
||||
|
||||
/// Compute the maximum backedge count based on the range of values
|
||||
/// permitted by Start, End, and Stride. This is for loops of the form
|
||||
/// {Start, +, Stride} LT End.
|
||||
|
@ -1507,4 +1507,35 @@ TEST_F(ScalarEvolutionsTest, MatchURem) {
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(ScalarEvolutionsTest, SCEVUDivFloorCeiling) {
|
||||
LLVMContext C;
|
||||
SMDiagnostic Err;
|
||||
std::unique_ptr<Module> M = parseAssemblyString("define void @foo() { "
|
||||
" ret void "
|
||||
"} ",
|
||||
Err, C);
|
||||
|
||||
ASSERT_TRUE(M && "Could not parse module?");
|
||||
ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
|
||||
|
||||
runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
|
||||
// Check that SCEV's udiv and uceil handling produce the correct results
|
||||
// for all 8 bit options. Div-by-zero is deliberately excluded.
|
||||
for (unsigned N = 0; N < 256; N++)
|
||||
for (unsigned D = 1; D < 256; D++) {
|
||||
APInt NInt(8, N);
|
||||
APInt DInt(8, D);
|
||||
using namespace llvm::APIntOps;
|
||||
APInt FloorInt = RoundingUDiv(NInt, DInt, APInt::Rounding::DOWN);
|
||||
APInt CeilingInt = RoundingUDiv(NInt, DInt, APInt::Rounding::UP);
|
||||
auto *NS = SE.getConstant(NInt);
|
||||
auto *DS = SE.getConstant(DInt);
|
||||
auto *FloorS = cast<SCEVConstant>(SE.getUDivExpr(NS, DS));
|
||||
auto *CeilingS = cast<SCEVConstant>(SE.getUDivCeilSCEV(NS, DS));
|
||||
ASSERT_TRUE(FloorS->getAPInt() == FloorInt);
|
||||
ASSERT_TRUE(CeilingS->getAPInt() == CeilingInt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
Loading…
Reference in New Issue
Block a user