aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2020-10-29 09:30:37 +0000
committerFlorian Hahn <flo@fhahn.com>2020-10-29 10:46:52 +0000
commit88d6421e4c439582ca4ca5e3744f8cc4498bb48e (patch)
treeaf6fa688e2ae3220d9f9182ad10527931941b020 /llvm/unittests/Analysis/ScalarEvolutionTest.cpp
parent79c5b4c546bb528bd51003a10f0a5aecab74ffbe (diff)
downloadllvm-88d6421e4c439582ca4ca5e3744f8cc4498bb48e.zip
llvm-88d6421e4c439582ca4ca5e3744f8cc4498bb48e.tar.gz
llvm-88d6421e4c439582ca4ca5e3744f8cc4498bb48e.tar.bz2
[SCEV] Match 'zext (trunc A to iB) to iY' as URem.
URem operations with constant power-of-2 second operands are modeled as such. This patch on its own has very little impact (e.g. no changes in CodeGen for MultiSource/SPEC2000/SPEC2006 on X86 -O3 -flto), but I'll soon post follow-up patches that make use of it to more accurately determine the trip multiple. Reviewed By: mkazantsev Differential Revision: https://reviews.llvm.org/D89821
Diffstat (limited to 'llvm/unittests/Analysis/ScalarEvolutionTest.cpp')
-rw-r--r--llvm/unittests/Analysis/ScalarEvolutionTest.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 909a140..7fa5885 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -63,6 +63,11 @@ protected:
const SCEV *RHS) {
return SE.computeConstantDifference(LHS, RHS);
}
+
+ static bool matchURem(ScalarEvolution &SE, const SCEV *Expr, const SCEV *&LHS,
+ const SCEV *&RHS) {
+ return SE.matchURem(Expr, LHS, RHS);
+ }
};
TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) {
@@ -1363,4 +1368,57 @@ TEST_F(ScalarEvolutionsTest, ProveImplicationViaNarrowing) {
});
}
+TEST_F(ScalarEvolutionsTest, MatchURem) {
+ LLVMContext C;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(
+ "target datalayout = \"e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128\" "
+ " "
+ "define void @test(i32 %a, i32 %b, i16 %c, i64 %d) {"
+ "entry: "
+ " %rem1 = urem i32 %a, 2"
+ " %rem2 = urem i32 %a, 5"
+ " %rem3 = urem i32 %a, %b"
+ " %c.ext = zext i16 %c to i32"
+ " %rem4 = urem i32 %c.ext, 2"
+ " %ext = zext i32 %rem4 to i64"
+ " %rem5 = urem i64 %d, 17179869184"
+ " ret void "
+ "} ",
+ Err, C);
+
+ assert(M && "Could not parse module?");
+ assert(!verifyModule(*M) && "Must have been well formed!");
+
+ runWithSE(*M, "test", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+ for (auto *N : {"rem1", "rem2", "rem3", "rem5"}) {
+ auto *URemI = getInstructionByName(F, N);
+ auto *S = SE.getSCEV(URemI);
+ const SCEV *LHS, *RHS;
+ EXPECT_TRUE(matchURem(SE, S, LHS, RHS));
+ EXPECT_EQ(LHS, SE.getSCEV(URemI->getOperand(0)));
+ EXPECT_EQ(RHS, SE.getSCEV(URemI->getOperand(1)));
+ EXPECT_EQ(LHS->getType(), S->getType());
+ EXPECT_EQ(RHS->getType(), S->getType());
+ }
+
+ // Check the case where the urem operand is zero-extended. Make sure the
+ // match results are extended to the size of the input expression.
+ auto *Ext = getInstructionByName(F, "ext");
+ auto *URem1 = getInstructionByName(F, "rem4");
+ auto *S = SE.getSCEV(Ext);
+ const SCEV *LHS, *RHS;
+ EXPECT_TRUE(matchURem(SE, S, LHS, RHS));
+ EXPECT_NE(LHS, SE.getSCEV(URem1->getOperand(0)));
+ // RHS and URem1->getOperand(1) have different widths, so compare the
+ // integer values.
+ EXPECT_EQ(cast<SCEVConstant>(RHS)->getValue()->getZExtValue(),
+ cast<SCEVConstant>(SE.getSCEV(URem1->getOperand(1)))
+ ->getValue()
+ ->getZExtValue());
+ EXPECT_EQ(LHS->getType(), S->getType());
+ EXPECT_EQ(RHS->getType(), S->getType());
+ });
+}
+
} // end namespace llvm