diff options
author | Max Kazantsev <max.kazantsev@azul.com> | 2017-11-16 05:10:56 +0000 |
---|---|---|
committer | Max Kazantsev <max.kazantsev@azul.com> | 2017-11-16 05:10:56 +0000 |
commit | cb0def446ff5cce133b3ec706156d881b8691864 (patch) | |
tree | c31aeab402b20029c0b33229987dcd5cf8aed2ef | |
parent | 74e1e117455ae827d1c1f1921c7832bc7f8548ef (diff) |
[SCEV][NFC] Introduce isSafeToExpandAt function to SCEVExpander
This function checks that:
1) It is safe to expand a SCEV;
2) It is OK to materialize it at the specified location.
For example, attempt to expand a loop's AddRec to the same loop's preheader should fail.
Differential Revision: https://reviews.llvm.org/D39236
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318377 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Analysis/ScalarEvolutionExpander.h | 9 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolutionExpander.cpp | 5 | ||||
-rw-r--r-- | unittests/Analysis/ScalarEvolutionTest.cpp | 71 |
3 files changed, 84 insertions, 1 deletions
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 7d16f34e54c..4578e0da8ab 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -27,9 +27,16 @@ namespace llvm { class TargetTransformInfo; /// Return true if the given expression is safe to expand in the sense that - /// all materialized values are safe to speculate. + /// all materialized values are safe to speculate anywhere their operands are + /// defined. bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); + /// Return true if the given expression is safe to expand in the sense that + /// all materialized values are defined and safe to speculate at the specified + /// location and their operands are defined at this location. + bool isSafeToExpandAt(const SCEV *S, const Instruction *InsertionPoint, + ScalarEvolution &SE); + /// This class uses information about analyze scalars to rewrite expressions /// in canonical form. /// diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index 47bdac00ae1..ee0bc37e3dc 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -2293,4 +2293,9 @@ bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE) { visitAll(S, Search); return !Search.IsUnsafe; } + +bool isSafeToExpandAt(const SCEV *S, const Instruction *InsertionPoint, + ScalarEvolution &SE) { + return isSafeToExpand(S, SE) && SE.dominates(S, InsertionPoint->getParent()); +} } diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp index 1f51c1c91a5..e438e8af7aa 100644 --- a/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/unittests/Analysis/ScalarEvolutionTest.cpp @@ -1113,5 +1113,76 @@ TEST_F(ScalarEvolutionsTest, SCEVFoldSumOfTruncs) { EXPECT_EQ(Expr, ZeroConst); } +// Check that we can correctly identify the points at which the SCEV of the +// AddRec can be expanded. +TEST_F(ScalarEvolutionsTest, SCEVExpanderIsSafeToExpandAt) { + /* + * 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)); + + 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")); + 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); + const SCEV *S = SE.getSCEV(Phi); + EXPECT_TRUE(isa<SCEVAddRecExpr>(S)); + const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S); + EXPECT_TRUE(AR->isAffine()); + EXPECT_FALSE(isSafeToExpandAt(AR, Top->getTerminator(), SE)); + EXPECT_FALSE(isSafeToExpandAt(AR, LPh->getTerminator(), SE)); + EXPECT_TRUE(isSafeToExpandAt(AR, L->getTerminator(), SE)); + EXPECT_TRUE(isSafeToExpandAt(AR, Post->getTerminator(), SE)); +} + } // end anonymous namespace } // end namespace llvm |