diff options
| author | Max Kazantsev <max.kazantsev@azul.com> | 2017-08-03 08:41:30 +0000 |
|---|---|---|
| committer | Max Kazantsev <max.kazantsev@azul.com> | 2017-08-03 08:41:30 +0000 |
| commit | 2cb3653404f7ae095a6a5c05fa72513be7b078b5 (patch) | |
| tree | d04ad0b0d33b8501f39c2c99d9f3d0917aad6436 /llvm/unittests/Analysis | |
| parent | 820def6fdd465338c852d92fa03a08b154a5a646 (diff) | |
| download | bcm5719-llvm-2cb3653404f7ae095a6a5c05fa72513be7b078b5.tar.gz bcm5719-llvm-2cb3653404f7ae095a6a5c05fa72513be7b078b5.zip | |
[SCEV] Re-enable "Cache results of computeExitLimit"
The patch rL309080 was reverted because it did not clean up the cache on "forgetValue"
method call. This patch re-enables this change, adds the missing check and introduces
two new unit tests that make sure that the cache is cleaned properly.
Differential Revision: https://reviews.llvm.org/D36087
llvm-svn: 309925
Diffstat (limited to 'llvm/unittests/Analysis')
| -rw-r--r-- | llvm/unittests/Analysis/ScalarEvolutionTest.cpp | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp index 91f4c3535b7..c6b66cf9816 100644 --- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp @@ -930,5 +930,165 @@ TEST_F(ScalarEvolutionsTest, SCEVZeroExtendExprNonIntegral) { EXPECT_FALSE(verifyFunction(*F, &errs())); } +// Make sure that SCEV invalidates exit limits after invalidating the values it +// depends on when we forget a loop. +TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetLoop) { + /* + * Create the following code: + * func(i64 addrspace(10)* %arg) + * top: + * br label %L.ph + * L.ph: + * br label %L + * L: + * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ] + * %add = add i64 %phi2, 1 + * %cond = icmp slt i64 %add, 1000; then becomes 2000. + * br i1 %cond, label %post, label %L2 + * post: + * ret void + * + */ + + // Create a module with non-integral pointers in it's datalayout + Module NIM("nonintegral", Context); + std::string DataLayout = M.getDataLayoutStr(); + if (!DataLayout.empty()) + DataLayout += "-"; + DataLayout += "ni:10"; + NIM.setDataLayout(DataLayout); + + Type *T_int64 = Type::getInt64Ty(Context); + Type *T_pint64 = T_int64->getPointerTo(10); + + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false); + Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy)); + + Argument *Arg = &*F->arg_begin(); + + BasicBlock *Top = BasicBlock::Create(Context, "top", F); + BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F); + BasicBlock *L = BasicBlock::Create(Context, "L", F); + BasicBlock *Post = BasicBlock::Create(Context, "post", F); + + IRBuilder<> Builder(Top); + Builder.CreateBr(LPh); + + Builder.SetInsertPoint(LPh); + Builder.CreateBr(L); + + Builder.SetInsertPoint(L); + PHINode *Phi = Builder.CreatePHI(T_int64, 2); + auto *Add = cast<Instruction>( + Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add")); + auto *Limit = ConstantInt::get(T_int64, 1000); + auto *Cond = cast<Instruction>( + Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Limit, "cond")); + auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post)); + Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh); + Phi->addIncoming(Add, L); + + Builder.SetInsertPoint(Post); + Builder.CreateRetVoid(); + + ScalarEvolution SE = buildSE(*F); + auto *Loop = LI->getLoopFor(L); + const SCEV *EC = SE.getBackedgeTakenCount(Loop); + EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC)); + + SE.forgetLoop(Loop); + Br->eraseFromParent(); + Cond->eraseFromParent(); + + Builder.SetInsertPoint(L); + Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000), + "new.cond"); + Builder.CreateCondBr(Cond, L, Post); + const SCEV *NewEC = SE.getBackedgeTakenCount(Loop); + EXPECT_NE(EC, NewEC); +} + +// Make sure that SCEV invalidates exit limits after invalidating the values it +// depends on when we forget a value. +TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetValue) { + /* + * Create the following code: + * func(i64 addrspace(10)* %arg) + * top: + * br label %L.ph + * L.ph: + * %load = load i64 addrspace(10)* %arg + * br label %L + * L: + * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ] + * %add = add i64 %phi2, 1 + * %cond = icmp slt i64 %add, %load ; then becomes 2000. + * br i1 %cond, label %post, label %L2 + * post: + * ret void + * + */ + + // Create a module with non-integral pointers in it's datalayout + Module NIM("nonintegral", Context); + std::string DataLayout = M.getDataLayoutStr(); + if (!DataLayout.empty()) + DataLayout += "-"; + DataLayout += "ni:10"; + NIM.setDataLayout(DataLayout); + + Type *T_int64 = Type::getInt64Ty(Context); + Type *T_pint64 = T_int64->getPointerTo(10); + + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false); + Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy)); + + Argument *Arg = &*F->arg_begin(); + + BasicBlock *Top = BasicBlock::Create(Context, "top", F); + BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F); + BasicBlock *L = BasicBlock::Create(Context, "L", F); + BasicBlock *Post = BasicBlock::Create(Context, "post", F); + + IRBuilder<> Builder(Top); + Builder.CreateBr(LPh); + + Builder.SetInsertPoint(LPh); + auto *Load = cast<Instruction>(Builder.CreateLoad(T_int64, Arg, "load")); + Builder.CreateBr(L); + + Builder.SetInsertPoint(L); + PHINode *Phi = Builder.CreatePHI(T_int64, 2); + auto *Add = cast<Instruction>( + Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add")); + auto *Cond = cast<Instruction>( + Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Load, "cond")); + auto *Br = cast<Instruction>(Builder.CreateCondBr(Cond, L, Post)); + Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh); + Phi->addIncoming(Add, L); + + Builder.SetInsertPoint(Post); + Builder.CreateRetVoid(); + + ScalarEvolution SE = buildSE(*F); + auto *Loop = LI->getLoopFor(L); + const SCEV *EC = SE.getBackedgeTakenCount(Loop); + EXPECT_FALSE(isa<SCEVCouldNotCompute>(EC)); + + SE.forgetValue(Load); + Br->eraseFromParent(); + Cond->eraseFromParent(); + Load->eraseFromParent(); + + Builder.SetInsertPoint(L); + Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000), + "new.cond"); + Builder.CreateCondBr(Cond, L, Post); + const SCEV *NewEC = SE.getBackedgeTakenCount(Loop); + EXPECT_NE(EC, NewEC); +} + } // end anonymous namespace } // end namespace llvm |

