diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -567,6 +567,8 @@ const SCEV *getZeroExtendExprImpl(const SCEV *Op, Type *Ty, unsigned Depth = 0); const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0); + const SCEV *getSignExtendExprImpl(const SCEV *Op, Type *Ty, + unsigned Depth = 0); const SCEV *getCastExpr(SCEVTypes Kind, const SCEV *Op, Type *Ty); const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty); const SCEV *getAddExpr(SmallVectorImpl &Ops, diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -1934,6 +1934,31 @@ assert(!Op->getType()->isPointerTy() && "Can't extend pointer!"); Ty = getEffectiveSCEVType(Ty); + FoldID ID; + ID.addInteger(scSignExtend); + ID.addPointer(Op); + ID.addPointer(Ty); + auto Iter = FoldCache.find(ID); + if (Iter != FoldCache.end()) + return Iter->second; + + const SCEV *S = getSignExtendExprImpl(Op, Ty, Depth); + if (!isa(S)) { + FoldCache.insert({ID, S}); + auto R = FoldCacheUser.insert({S, {}}); + R.first->second.push_back(ID); + } + return S; +} + +const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty, + unsigned Depth) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && "This is not a conversion to a SCEVable type!"); + assert(!Op->getType()->isPointerTy() && "Can't extend pointer!"); + Ty = getEffectiveSCEVType(Ty); + // Fold if the operand is constant. if (const SCEVConstant *SC = dyn_cast(Op)) return getConstant( diff --git a/llvm/test/Transforms/IndVarSimplify/range-iter-threshold.ll b/llvm/test/Transforms/IndVarSimplify/range-iter-threshold.ll --- a/llvm/test/Transforms/IndVarSimplify/range-iter-threshold.ll +++ b/llvm/test/Transforms/IndVarSimplify/range-iter-threshold.ll @@ -8,13 +8,13 @@ ; COMMON-NEXT: entry: ; COMMON-NEXT: br label [[OUTER_HEADER:%.*]] ; COMMON: outer.header: -; DEFAULT-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 2, [[ENTRY:%.*]] ] -; COMMON-NEXT: [[IV_1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[OUTER_LATCH:%.*]] ] +; COMMON-NEXT: [[INDVARS_IV1:%.*]] = phi i64 [ [[INDVARS_IV_NEXT2:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; DEFAULT-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[OUTER_LATCH]] ], [ 2, [[ENTRY]] ] +; COMMON-NEXT: [[IV_1:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_1_NEXT:%.*]], [[OUTER_LATCH]] ] ; COMMON-NEXT: [[MAX_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[MAX_1:%.*]], [[OUTER_LATCH]] ] -; COMMON-NEXT: [[TMP0:%.*]] = sext i32 [[IV_1]] to i64 ; COMMON-NEXT: br label [[INNER_1:%.*]] ; COMMON: inner.1: -; COMMON-NEXT: [[C_1:%.*]] = icmp slt i64 0, [[TMP0]] +; COMMON-NEXT: [[C_1:%.*]] = icmp ult i64 0, [[INDVARS_IV1]] ; COMMON-NEXT: br i1 [[C_1]], label [[INNER_1]], label [[INNER_2_HEADER_PREHEADER:%.*]] ; COMMON: inner.2.header.preheader: ; COMMON-NEXT: br label [[INNER_2_HEADER:%.*]] @@ -28,6 +28,7 @@ ; COMMON-NEXT: br i1 [[EXITCOND]], label [[OUTER_LATCH]], label [[INNER_2_HEADER]] ; COMMON: outer.latch: ; COMMON-NEXT: [[MAX_1]] = phi i32 [ [[M:%.*]], [[INNER_2_LATCH]] ], [ 0, [[INNER_2_HEADER]] ] +; COMMON-NEXT: [[INDVARS_IV_NEXT2]] = add nuw nsw i64 [[INDVARS_IV1]], 1 ; COMMON-NEXT: [[IV_1_NEXT]] = add nuw i32 [[IV_1]], 1 ; COMMON-NEXT: [[C_3:%.*]] = icmp ugt i32 [[IV_1]], [[MAX_0]] ; DEFAULT-NEXT: [[INDVARS_IV_NEXT]] = add i32 [[INDVARS_IV]], 1