aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/Analysis/ScalarEvolutionTest.cpp')
-rw-r--r--llvm/unittests/Analysis/ScalarEvolutionTest.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 6789604..1a68823 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1768,4 +1768,141 @@ TEST_F(ScalarEvolutionsTest, ComplexityComparatorIsStrictWeakOrdering3) {
SE.getSCEV(Or1);
}
+TEST_F(ScalarEvolutionsTest, SimplifyICmpOperands) {
+ LLVMContext C;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M =
+ parseAssemblyString("define i32 @foo(ptr %loc, i32 %a, i32 %b) {"
+ "entry: "
+ " ret i32 %a "
+ "} ",
+ Err, C);
+
+ ASSERT_TRUE(M && "Could not parse module?");
+ ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
+
+ // Remove common factor when there's no signed wrapping.
+ runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+ const SCEV *A = SE.getSCEV(getArgByName(F, "a"));
+ const SCEV *B = SE.getSCEV(getArgByName(F, "b"));
+ const SCEV *VS = SE.getVScale(A->getType());
+ const SCEV *VSxA = SE.getMulExpr(VS, A, SCEV::FlagNSW);
+ const SCEV *VSxB = SE.getMulExpr(VS, B, SCEV::FlagNSW);
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_SLT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_SLT);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, B);
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_ULT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_ULT);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, B);
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_EQ;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_EQ);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, B);
+ }
+
+ // Verify the common factor's position doesn't impede simplification.
+ {
+ const SCEV *C = SE.getConstant(A->getType(), 100);
+ const SCEV *CxVS = SE.getMulExpr(C, VS, SCEV::FlagNSW);
+
+ // Verify common factor is available at different indices.
+ ASSERT_TRUE(isa<SCEVVScale>(cast<SCEVMulExpr>(VSxA)->getOperand(0)) !=
+ isa<SCEVVScale>(cast<SCEVMulExpr>(CxVS)->getOperand(0)));
+
+ CmpPredicate NewPred = ICmpInst::ICMP_SLT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = CxVS;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_SLT);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, C);
+ }
+ });
+
+ // Remove common factor when there's no unsigned wrapping.
+ runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+ const SCEV *A = SE.getSCEV(getArgByName(F, "a"));
+ const SCEV *B = SE.getSCEV(getArgByName(F, "b"));
+ const SCEV *VS = SE.getVScale(A->getType());
+ const SCEV *VSxA = SE.getMulExpr(VS, A, SCEV::FlagNUW);
+ const SCEV *VSxB = SE.getMulExpr(VS, B, SCEV::FlagNUW);
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_SLT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_FALSE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_ULT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_ULT);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, B);
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_EQ;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_TRUE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ EXPECT_EQ(NewPred, ICmpInst::ICMP_EQ);
+ EXPECT_EQ(NewLHS, A);
+ EXPECT_EQ(NewRHS, B);
+ }
+ });
+
+ // Do not remove common factor due to wrap flag mismatch.
+ runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+ const SCEV *A = SE.getSCEV(getArgByName(F, "a"));
+ const SCEV *B = SE.getSCEV(getArgByName(F, "b"));
+ const SCEV *VS = SE.getVScale(A->getType());
+ const SCEV *VSxA = SE.getMulExpr(VS, A, SCEV::FlagNSW);
+ const SCEV *VSxB = SE.getMulExpr(VS, B, SCEV::FlagNUW);
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_SLT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_FALSE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_ULT;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_FALSE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ }
+
+ {
+ CmpPredicate NewPred = ICmpInst::ICMP_EQ;
+ const SCEV *NewLHS = VSxA;
+ const SCEV *NewRHS = VSxB;
+ EXPECT_FALSE(SE.SimplifyICmpOperands(NewPred, NewLHS, NewRHS));
+ }
+ });
+}
+
} // end namespace llvm