Index: lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- lib/Transforms/Scalar/IndVarSimplify.cpp +++ lib/Transforms/Scalar/IndVarSimplify.cpp @@ -85,6 +85,24 @@ namespace { struct RewritePhi; +struct OriginalIVInfo { + bool HasNUW; + bool HasNSW; + bool IsSigned; + Type *OriginalType; + + OriginalIVInfo(bool HasNUW, bool HasNSW, + bool IsSigned, Type *OriginalType) : + HasNUW(HasNUW), HasNSW(HasNSW), + IsSigned(IsSigned), + OriginalType(OriginalType){}; + + OriginalIVInfo() {}; + +}; + +typedef ValueMap> WidenedIVMapType; + class IndVarSimplify { LoopInfo *LI; ScalarEvolution *SE; @@ -93,6 +111,8 @@ TargetLibraryInfo *TLI; const TargetTransformInfo *TTI; + WidenedIVMapType WidenedIVMap; + SmallVector DeadInsts; bool Changed = false; @@ -907,7 +927,7 @@ assert(L->getHeader() == OrigPhi->getParent() && "Phi must be an IV"); } - PHINode *createWideIV(SCEVExpander &Rewriter); + PHINode *createWideIV(SCEVExpander &Rewriter, WidenedIVMapType &WIMap); protected: Value *createExtendInst(Value *NarrowOper, Type *WideType, bool IsSigned, @@ -1393,7 +1413,7 @@ /// It would be simpler to delete uses as they are processed, but we must avoid /// invalidating SCEV expressions. /// -PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter) { +PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter, WidenedIVMapType &WIMap) { // Is this phi an induction variable? const SCEVAddRecExpr *AddRec = dyn_cast(SE->getSCEV(OrigPhi)); if (!AddRec) @@ -1407,6 +1427,11 @@ assert(SE->getEffectiveSCEVType(WideIVExpr->getType()) == WideType && "Expect the new IV expression to preserve its type"); + std::unique_ptr OriginalIV( + new OriginalIVInfo(AddRec->hasNoUnsignedWrap(), + AddRec->hasNoSignedWrap(), + IsSigned, + AddRec->getType())); // Can the IV be extended outside the loop without overflow? AddRec = dyn_cast(WideIVExpr); if (!AddRec || AddRec->getLoop() != L) @@ -1427,6 +1452,8 @@ Instruction *InsertPt = &L->getHeader()->front(); WidePhi = cast(Rewriter.expandCodeFor(AddRec, WideType, InsertPt)); + WIMap[WidePhi] = std::move(OriginalIV); + // Remembering the WideIV increment generated by SCEVExpander allows // widenIVUse to reuse it when widening the narrow IV's increment. We don't // employ a general reuse mechanism because the call above is the only call to @@ -1536,7 +1563,7 @@ for (; !WideIVs.empty(); WideIVs.pop_back()) { WidenIV Widener(WideIVs.back(), LI, SE, DT, DeadInsts); - if (PHINode *WidePhi = Widener.createWideIV(Rewriter)) { + if (PHINode *WidePhi = Widener.createWideIV(Rewriter, WidenedIVMap)) { Changed = true; LoopPhis.push_back(WidePhi); } @@ -1984,8 +2011,25 @@ DEBUG(dbgs() << " Widen RHS:\t" << *ExitCnt << "\n"); } else { - CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(), - "lftr.wideiv"); + bool extended = false; + const auto Iter = WidenedIVMap.find(IndVar); + if (Iter != WidenedIVMap.end() && + ((Iter->second)->OriginalType == ExitCnt->getType())) { + if (Iter->second->HasNSW && Iter->second->IsSigned) { + extended = true; + ExitCnt = Builder.CreateSExt(ExitCnt, IndVar->getType(), + "wide.trip.count"); + } + if (Iter->second->HasNUW && !Iter->second->IsSigned) { + extended = true; + ExitCnt = Builder.CreateZExt(ExitCnt, IndVar->getType(), + "wide.trip.count"); + } + } + if (!extended) { + CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(), + "lftr.wideiv"); + } } } Value *Cond = Builder.CreateICmp(P, CmpIndVar, ExitCnt, "exitcond"); @@ -2164,6 +2208,7 @@ Rewriter); } } + WidenedIVMap.clear(); // Clear the rewriter cache, because values that are in the rewriter's cache // can be deleted in the loop below, causing the AssertingVH in the cache to // trigger. Index: test/Transforms/IndVarSimplify/elim-extend.ll =================================================================== --- test/Transforms/IndVarSimplify/elim-extend.ll +++ test/Transforms/IndVarSimplify/elim-extend.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -S | FileCheck %s +; RUN: opt < %s -indvars -S | grep -v wide.trip.count| FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" Index: test/Transforms/IndVarSimplify/preserve-signed-wrap.ll =================================================================== --- test/Transforms/IndVarSimplify/preserve-signed-wrap.ll +++ test/Transforms/IndVarSimplify/preserve-signed-wrap.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -S | FileCheck %s +; RUN: opt < %s -indvars -S | grep -v wide.trip.count | FileCheck %s ; Indvars should insert a 64-bit induction variable to eliminate the ; sext for the addressing, however it shouldn't eliminate the sext Index: test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll =================================================================== --- test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll +++ test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -S | not grep sext +; RUN: opt < %s -indvars -S | grep -v wide.trip.count | not grep sext ; Provide legal integer types. target datalayout = "n8:16:32:64" Index: test/Transforms/IndVarSimplify/signed-trip-count.ll =================================================================== --- test/Transforms/IndVarSimplify/signed-trip-count.ll +++ test/Transforms/IndVarSimplify/signed-trip-count.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -indvars -S > %t +; RUN: opt < %s -indvars -S | grep -v wide.trip.count > %t ; RUN: not grep sext %t ; RUN: grep phi %t | count 1