Index: llvm/trunk/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp @@ -4523,8 +4523,7 @@ : SCEVWrapPredicate::IncrementNUSW; const SCEVPredicate *AddRecPred = getWrapPredicate(AR, AddedFlags); Predicates.push_back(AddRecPred); - } else - assert(isa(PHISCEV) && "Expected constant SCEV"); + } // Create the Equal Predicates P2,P3: Index: llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp =================================================================== --- llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp +++ llvm/trunk/unittests/Analysis/ScalarEvolutionTest.cpp @@ -1009,6 +1009,63 @@ auto Result = SE.createAddRecFromPHIWithCasts(cast(Expr)); } +TEST_F(ScalarEvolutionsTest, SCEVAddRecFromPHIwithLargeConstantAccum) { + // 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 the InvariantAccum is a constant that is too large to fit in an + // ix but are zero when truncated to ix, and the initial value of the + // phi is not a constant. + Type *Int32Ty = Type::getInt32Ty(Context); + SmallVector Types; + Types.push_back(Int32Ty); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Types, false); + Function *F = cast(M.getOrInsertFunction("addrecphitest", FTy)); + + /* + Create IR: + define @addrecphitest(i32) + entry: + br label %loop + loop: + %1 = phi i32 [%0, %entry], [%4, %loop] + %2 = shl i32 %1, 16 + %3 = ashr exact i32 %2, 16 + %4 = add i32 %3, -2147483648 + 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 *MinInt32 = ConstantInt::get(Context, APInt(32, 0x80000000U, true)); + auto *Int32_16 = ConstantInt::get(Context, APInt(32, 16)); + auto *Br = BranchInst::Create( + LoopBB, ExitBB, UndefValue::get(Type::getInt1Ty(Context)), LoopBB); + auto *Phi = PHINode::Create(Int32Ty, 2, "", Br); + auto *Shl = BinaryOperator::CreateShl(Phi, Int32_16, "", Br); + auto *AShr = BinaryOperator::CreateExactAShr(Shl, Int32_16, "", Br); + auto *Add = BinaryOperator::CreateAdd(AShr, MinInt32, "", Br); + auto *Arg = &*(F->arg_begin()); + Phi->addIncoming(Arg, 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(Expr)); + auto Result = SE.createAddRecFromPHIWithCasts(cast(Expr)); +} + TEST_F(ScalarEvolutionsTest, SCEVFoldSumOfTruncs) { // Verify that the following SCEV gets folded to a zero: // (-1 * (trunc i64 (-1 * %0) to i32)) + (-1 * (trunc i64 %0 to i32) @@ -1035,7 +1092,6 @@ const auto *B = SE.getNegativeSCEV(B0); const auto *Expr = SE.getAddExpr(A, B); - dbgs() << "DDN\nExpr: " << *Expr << "\n"; // Verify that the SCEV was folded to 0 const auto *ZeroConst = SE.getConstant(Int32Ty, 0); EXPECT_EQ(Expr, ZeroConst);