diff options
Diffstat (limited to 'llvm/unittests/Analysis/ScalarEvolutionTest.cpp')
-rw-r--r-- | llvm/unittests/Analysis/ScalarEvolutionTest.cpp | 137 |
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 |