diff options
author | Daniel Neilson <dneilson@azul.com> | 2017-09-05 19:54:03 +0000 |
---|---|---|
committer | Daniel Neilson <dneilson@azul.com> | 2017-09-05 19:54:03 +0000 |
commit | 3f0e4ad833e0f367255522b4b3dd3e625a1c40c1 (patch) | |
tree | dc69edb69d3c11f67a933da457d887772c783170 /llvm/unittests/Analysis/ScalarEvolutionTest.cpp | |
parent | d0e9c167d8a6ab934bfa20ec0b774488176777a8 (diff) | |
download | bcm5719-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.cpp | 55 |
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 |