Index: lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- lib/Transforms/Scalar/IndVarSimplify.cpp +++ lib/Transforms/Scalar/IndVarSimplify.cpp @@ -35,6 +35,7 @@ #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" @@ -1304,7 +1305,8 @@ } } // Our raison d'etre! Eliminate sign and zero extension. - if (IsSigned ? isa(DU.NarrowUse) : isa(DU.NarrowUse)) { + if ((IsSigned ? isa(DU.NarrowUse) : isa(DU.NarrowUse)) || + (isa(DU.NarrowUse) && DU.NeverNegative)) { Value *NewDef = DU.WideDef; if (DU.NarrowUse->getType() != WideType) { unsigned CastWidth = SE->getTypeSizeInBits(DU.NarrowUse->getType()); @@ -1396,7 +1398,8 @@ const SCEV *NarrowSCEV = SE->getSCEV(NarrowDef); bool NeverNegative = SE->isKnownPredicate(ICmpInst::ICMP_SGE, NarrowSCEV, - SE->getConstant(NarrowSCEV->getType(), 0)); + SE->getConstant(NarrowSCEV->getType(), 0)) || + isKnownNonNegative(NarrowDef, NarrowDef->getModule()->getDataLayout()); for (User *U : NarrowDef->users()) { Instruction *NarrowUser = cast(U); Index: test/Transforms/IndVarSimplify/iv-zext.ll =================================================================== --- test/Transforms/IndVarSimplify/iv-zext.ll +++ test/Transforms/IndVarSimplify/iv-zext.ll @@ -1,10 +1,11 @@ ; RUN: opt < %s -indvars -S | FileCheck %s -; CHECK-NOT: and -; CHECK-NOT: zext target datalayout = "p:64:64:64-n32:64" define void @foo(double* %d, i64 %n) nounwind { +; CHECK-LABEL: @foo( +; CHECK-NOT: and +; CHECK-NOT: zext entry: br label %loop @@ -31,3 +32,40 @@ return: ret void } + +; When widening IV, trunc and zext are not needed if the +; original 32-bit integer is known to be non-negative +define void @foo1(i32* %A, i32* %B, i32* %C, i32 %N) { +; CHECK-LABEL: @foo1( +; CHECK-NOT: trunc +; CHECK-NOT: zext +entry: + br label %for.cond + +for.cond: + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %cmp = icmp slt i32 %i.0, %N + br i1 %cmp, label %for.body, label %for.end + +for.body: + %idxprom = sext i32 %i.0 to i64 + %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom + %0 = load i32, i32* %arrayidx, align 4 + %add = add nsw i32 %i.0, 1 + %idxprom1 = zext i32 %add to i64 + %arrayidx2 = getelementptr inbounds i32, i32* %C, i64 %idxprom1 + %1 = load i32, i32* %arrayidx2, align 4 + %add3 = add nsw i32 %0, %1 + %idxprom4 = sext i32 %i.0 to i64 + %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %idxprom4 + store i32 %add3, i32* %arrayidx5, align 4 + br label %for.inc + +for.inc: + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: + ret void +} +