summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
diff options
context:
space:
mode:
authorDaniel Neilson <dneilson@azul.com>2017-09-05 19:54:03 +0000
committerDaniel Neilson <dneilson@azul.com>2017-09-05 19:54:03 +0000
commit3f0e4ad833e0f367255522b4b3dd3e625a1c40c1 (patch)
treedc69edb69d3c11f67a933da457d887772c783170 /llvm/unittests/Analysis/ScalarEvolutionTest.cpp
parentd0e9c167d8a6ab934bfa20ec0b774488176777a8 (diff)
downloadbcm5719-llvm-3f0e4ad833e0f367255522b4b3dd3e625a1c40c1.tar.gz
bcm5719-llvm-3f0e4ad833e0f367255522b4b3dd3e625a1c40c1.zip
[SCEV] Ensure ScalarEvolution::createAddRecFromPHIWithCastsImpl properly handles out of range truncations of the start and accum values
Summary: When constructing the predicate P1 in ScalarEvolution::createAddRecFromPHIWithCastsImpl() it is possible for the PHISCEV from which the predicate is constructed to be a SCEVConstant instead of a SCEVAddRec. If this happens, then the cast<SCEVAddRec>(PHISCEV) in the code will assert. Such a PHISCEV is possible if either the start value or the accumulator value is a constant value that not equal to its truncated value, and if the truncated value is zero. This patch adds tests that demonstrate the cast<> assertion, and fixes this problem by checking whether the PHISCEV is a constant before constructing the P1 predicate; if it is, then P1 is equivalent to one of P2 or P3. Additionally, if we know that the start value or accumulator value are constants then we check whether the P2 and/or P3 predicates are known false at compile time; if either is, then we bail out of constructing the AddRec. Reviewers: sanjoy, mkazantsev, silviu.baranga Reviewed By: mkazantsev Subscribers: mkazantsev, llvm-commits Differential Revision: https://reviews.llvm.org/D37265 llvm-svn: 312568
Diffstat (limited to 'llvm/unittests/Analysis/ScalarEvolutionTest.cpp')
-rw-r--r--llvm/unittests/Analysis/ScalarEvolutionTest.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index 0fd33aac838..6f689fad4b5 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1095,5 +1095,60 @@ TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetValue) {
EXPECT_EQ(cast<SCEVConstant>(NewEC)->getAPInt().getLimitedValue(), 1999u);
}
+TEST_F(ScalarEvolutionsTest, SCEVAddRecFromPHIwithLargeConstants) {
+ // Reference: https://reviews.llvm.org/D37265
+ // Make sure that SCEV does not blow up when constructing an AddRec
+ // with predicates for a phi with the update pattern:
+ // (SExt/ZExt ix (Trunc iy (%SymbolicPHI) to ix) to iy) + InvariantAccum
+ // when either the initial value of the Phi or the InvariantAccum are
+ // constants that are too large to fit in an ix but are zero when truncated to
+ // ix.
+ FunctionType *FTy =
+ FunctionType::get(Type::getVoidTy(Context), std::vector<Type *>(), false);
+ Function *F = cast<Function>(M.getOrInsertFunction("addrecphitest", FTy));
+
+ /*
+ Create IR:
+ entry:
+ br label %loop
+ loop:
+ %0 = phi i64 [-9223372036854775808, %entry], [%3, %loop]
+ %1 = shl i64 %0, 32
+ %2 = ashr exact i64 %1, 32
+ %3 = add i64 %2, -9223372036854775808
+ br i1 undef, label %exit, label %loop
+ exit:
+ ret void
+ */
+ BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", F);
+ BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", F);
+ BasicBlock *ExitBB = BasicBlock::Create(Context, "exit", F);
+
+ // entry:
+ BranchInst::Create(LoopBB, EntryBB);
+ // loop:
+ auto *MinInt64 =
+ ConstantInt::get(Context, APInt(64, 0x8000000000000000U, true));
+ auto *Int64_32 = ConstantInt::get(Context, APInt(64, 32));
+ auto *Br = BranchInst::Create(
+ LoopBB, ExitBB, UndefValue::get(Type::getInt1Ty(Context)), LoopBB);
+ auto *Phi = PHINode::Create(Type::getInt64Ty(Context), 2, "", Br);
+ auto *Shl = BinaryOperator::CreateShl(Phi, Int64_32, "", Br);
+ auto *AShr = BinaryOperator::CreateExactAShr(Shl, Int64_32, "", Br);
+ auto *Add = BinaryOperator::CreateAdd(AShr, MinInt64, "", Br);
+ Phi->addIncoming(MinInt64, EntryBB);
+ Phi->addIncoming(Add, LoopBB);
+ // exit:
+ ReturnInst::Create(Context, nullptr, ExitBB);
+
+ // Make sure that SCEV doesn't blow up
+ ScalarEvolution SE = buildSE(*F);
+ SCEVUnionPredicate Preds;
+ const SCEV *Expr = SE.getSCEV(Phi);
+ EXPECT_NE(nullptr, Expr);
+ EXPECT_TRUE(isa<SCEVUnknown>(Expr));
+ auto Result = SE.createAddRecFromPHIWithCasts(cast<SCEVUnknown>(Expr));
+}
+
} // end anonymous namespace
} // end namespace llvm
OpenPOWER on IntegriCloud