From: Nick Lewycky Date: Tue, 6 Sep 2011 21:42:18 +0000 (+0000) Subject: This transform only handles two-operand AddRec's. Prevent it from trying to X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c103a08a1115249548d6bb57a74a16de4f0864e3;p=oota-llvm.git This transform only handles two-operand AddRec's. Prevent it from trying to handle anything more complex. Fixes PR10383 again! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139186 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index b4c4da60ee5..57c42656481 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1974,7 +1974,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // multiplied together. If so, we can fold them. for (unsigned OtherIdx = Idx+1; OtherIdx < Ops.size() && isa(Ops[OtherIdx]); - ++OtherIdx) + ++OtherIdx) { + bool Retry = false; if (AddRecLoop == cast(Ops[OtherIdx])->getLoop()) { // {A,+,B} * {C,+,D} --> {A*C,+,A*D + B*C + B*D,+,2*B*D} // @@ -1985,7 +1986,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // Rearranging, X = x, Y = y+z, Z = 2z. // // x = A*C, y = (A*D + B*C), z = B*D. - // Therefore X = A*C, Y = (A*D + B*C) + B*D and Z = 2*B*D. + // Therefore X = A*C, Y = A*D + B*C + B*D and Z = 2*B*D. for (; OtherIdx != Ops.size() && isa(Ops[OtherIdx]); ++OtherIdx) if (const SCEVAddRecExpr *OtherAddRec = @@ -2002,19 +2003,28 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, const SCEV *NewSecondOrderStep = getMulExpr(BD, getConstant(BD->getType(), 2)); - SmallVector AddRecOps; - AddRecOps.push_back(NewStart); - AddRecOps.push_back(NewStep); - AddRecOps.push_back(NewSecondOrderStep); - const SCEV *NewAddRec = getAddRecExpr(AddRecOps, - AddRec->getLoop(), - SCEV::FlagAnyWrap); - if (Ops.size() == 2) return NewAddRec; - Ops[Idx] = AddRec = cast(NewAddRec); - Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + // This can happen when AddRec or OtherAddRec have >3 operands. + // TODO: support these add-recs. + if (isLoopInvariant(NewStart, AddRecLoop) && + isLoopInvariant(NewStep, AddRecLoop) && + isLoopInvariant(NewSecondOrderStep, AddRecLoop)) { + SmallVector AddRecOps; + AddRecOps.push_back(NewStart); + AddRecOps.push_back(NewStep); + AddRecOps.push_back(NewSecondOrderStep); + const SCEV *NewAddRec = getAddRecExpr(AddRecOps, + AddRec->getLoop(), + SCEV::FlagAnyWrap); + if (Ops.size() == 2) return NewAddRec; + Ops[Idx] = AddRec = cast(NewAddRec); + Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + Retry = true; + } } - return getMulExpr(Ops); + if (Retry) + return getMulExpr(Ops); } + } // Otherwise couldn't fold anything into this recurrence. Move onto the // next one. diff --git a/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll b/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll index 2c4ef16d2e3..06f1b6fe33a 100644 --- a/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll +++ b/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll @@ -35,7 +35,7 @@ return: ; preds = %bb5 ; PR10383 -; This used to crash. +; These next two used to crash. define void @test2(i1 %cmp, i64 %n) { entry: @@ -61,3 +61,22 @@ end: ret void } ; CHECK: Determining loop execution counts for: @test2 + +define i32 @test3() { +if.then466: + br i1 undef, label %for.cond539.preheader, label %for.inc479 + +for.inc479: + %a2.07 = phi i32 [ %add495, %for.inc479 ], [ 0, %if.then466 ] + %j.36 = phi i32 [ %inc497, %for.inc479 ], [ undef, %if.then466 ] + %mul484 = mul nsw i32 %j.36, %j.36 + %mul491 = mul i32 %j.36, %j.36 + %mul493 = mul i32 %mul491, %mul484 + %add495 = add nsw i32 %mul493, %a2.07 + %inc497 = add nsw i32 %j.36, 1 + br i1 undef, label %for.cond539.preheader, label %for.inc479 + +for.cond539.preheader: + unreachable +} +; CHECK: Determining loop execution counts for: @test3