X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FScalarEvolution.cpp;h=b1662a026086e0d1bd9471fbadc22fe2a4a742af;hb=3ca2ad11567f83883ae2719c5fac5afc30c7b3d1;hp=6d28f6912fdbf41b833582c14852693d04e82f56;hpb=fa151a79ed2d0efc8fe1d7378be264b301d8caf1;p=oota-llvm.git diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 6d28f6912fd..b1662a02608 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -652,7 +652,7 @@ static void GroupByComplexity(SmallVectorImpl &Ops, /// Assume, K > 0. static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, ScalarEvolution &SE, - Type* ResultTy) { + Type *ResultTy) { // Handle the simplest case efficiently. if (K == 1) return SE.getTruncateOrZeroExtend(It, ResultTy); @@ -1735,7 +1735,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; - // Otherwise, add the folded AddRec by the non-live parts. + // Otherwise, add the folded AddRec by the non-invariant parts. for (unsigned i = 0;; ++i) if (Ops[i] == AddRec) { Ops[i] = NewRec; @@ -1960,7 +1960,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; - // Otherwise, multiply the folded AddRec by the non-live parts. + // Otherwise, multiply the folded AddRec by the non-invariant parts. for (unsigned i = 0;; ++i) if (Ops[i] == AddRec) { Ops[i] = NewRec; @@ -1974,9 +1974,19 @@ 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} + // + // {A,+,B} * {C,+,D} = A+It*B * C+It*D = A*C + (A*D + B*C)*It + B*D*It^2 + // Given an equation of the form x + y*It + z*It^2 (above), we want to + // express it in terms of {X,+,Y,+,Z}. + // {X,+,Y,+,Z} = X + Y*It + Z*(It^2 - It)/2. + // 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. for (; OtherIdx != Ops.size() && isa(Ops[OtherIdx]); ++OtherIdx) if (const SCEVAddRecExpr *OtherAddRec = @@ -1993,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. @@ -3527,7 +3546,13 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { AddOps.push_back(Op1); } AddOps.push_back(getSCEV(U->getOperand(0))); - return getAddExpr(AddOps); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap; + OverflowingBinaryOperator *OBO = cast(V); + if (OBO->hasNoSignedWrap()) + setFlags(Flags, SCEV::FlagNSW); + if (OBO->hasNoUnsignedWrap()) + setFlags(Flags, SCEV::FlagNUW); + return getAddExpr(AddOps, Flags); } case Instruction::Mul: { // See the Add code above.