diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 83c4ede2e454..2dafbd720538 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -997,8 +997,11 @@ bool LoopStrengthReduce::ValidStride(bool HasBaseReg, AccessTy = SI->getOperand(0)->getType(); else if (LoadInst *LI = dyn_cast(UsersToProcess[i].Inst)) AccessTy = LI->getType(); - else if (PHINode *PN = dyn_cast(UsersToProcess[i].Inst)) - AccessTy = PN->getType(); + else if (isa(UsersToProcess[i].Inst)) { + if (AllowPHIIVReuse) + continue; + return false; + } TargetLowering::AddrMode AM; if (SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) @@ -1126,34 +1129,6 @@ static bool isAddressUse(Instruction *Inst, Value *OperandVal) { return isAddress; } -/// isAddressUsePHI - Returns if all uses of the specified PHI node are using -/// the PHI node value as an address. -static void isAddressUsePHI(Instruction *Inst, - SmallPtrSet &Processed, - bool &Result) { - if (!Result || !Processed.insert(Inst)) - return; - - for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); - UI != E; ++UI) { - Instruction *User = cast(*UI); - if (isa(User) && !Processed.count(User)) { - bool ThisResult = true; - isAddressUsePHI(User, Processed, ThisResult); - if (!ThisResult) { - Result = false; - return; - } - continue; - } - - if (!isAddressUse(User, cast(Inst))) { - Result = false; - return; - } - } -} - // CollectIVUsers - Transform our list of users and offsets to a bit more // complex table. In this new vector, each 'BasedUser' contains 'Base' the base // of the strided accessas well as the old information from Uses. We @@ -1191,6 +1166,7 @@ SCEVHandle LoopStrengthReduce::CollectIVUsers(const SCEVHandle &Stride, // instructions. If we can represent anything there, move it to the imm // fields of the BasedUsers. We do this so that it increases the commonality // of the remaining uses. + unsigned NumPHI = 0; for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { // If the user is not in the current loop, this means it is using the exit // value of the IV. Do not put anything in the base, make sure it's all in @@ -1204,17 +1180,16 @@ SCEVHandle LoopStrengthReduce::CollectIVUsers(const SCEVHandle &Stride, // Addressing modes can be folded into loads and stores. Be careful that // the store is through the expression, not of the expression though. - bool isPtrPHI = false; + bool isPHI = false; bool isAddress = isAddressUse(UsersToProcess[i].Inst, UsersToProcess[i].OperandValToReplace); if (isa(UsersToProcess[i].Inst)) { - SmallPtrSet Processed; - isPtrPHI = true; - isAddressUsePHI(UsersToProcess[i].Inst, Processed, isPtrPHI); + isPHI = true; + ++NumPHI; } // If this use isn't an address, then not all uses are addresses. - if (!isAddress && !(AllowPHIIVReuse && isPtrPHI)) + if (!isAddress && !(AllowPHIIVReuse && isPHI)) AllUsesAreAddresses = false; MoveImmediateValues(TLI, UsersToProcess[i].Inst, UsersToProcess[i].Base, @@ -1222,6 +1197,12 @@ SCEVHandle LoopStrengthReduce::CollectIVUsers(const SCEVHandle &Stride, } } + // If one of the use if a PHI node and all other uses are addresses, still + // allow iv reuse. Essentially we are trading one constant multiplication + // for one fewer iv. + if (NumPHI > 1) + AllUsesAreAddresses = false; + return CommonExprs; }