diff options
author | Andrew Trick <atrick@apple.com> | 2013-07-12 22:08:48 +0000 |
---|---|---|
committer | Andrew Trick <atrick@apple.com> | 2013-07-12 22:08:48 +0000 |
commit | 16404cc817e8b8d3fbfbc9051394eb59d7c5ffb4 (patch) | |
tree | c38db272b7095a3c70a84d9d8e5ca205b93c08e4 /lib/Transforms/Scalar | |
parent | 807e6c71a8d13531ec359006e3b6526ae70064a8 (diff) | |
download | llvm-16404cc817e8b8d3fbfbc9051394eb59d7c5ffb4.tar.gz llvm-16404cc817e8b8d3fbfbc9051394eb59d7c5ffb4.tar.bz2 llvm-16404cc817e8b8d3fbfbc9051394eb59d7c5ffb4.tar.xz |
LFTR improvement to avoid truncation.
This is a reimplemntation of the patch originally in r186107.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186215 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r-- | lib/Transforms/Scalar/IndVarSimplify.cpp | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index f0ac637968..d51e034861 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1590,15 +1590,41 @@ LinearFunctionTestReplace(Loop *L, << " RHS:\t" << *ExitCnt << "\n" << " IVCount:\t" << *IVCount << "\n"); + IRBuilder<> Builder(BI); + // LFTR can ignore IV overflow and truncate to the width of // BECount. This avoids materializing the add(zext(add)) expression. - IRBuilder<> Builder(BI); - if (SE->getTypeSizeInBits(CmpIndVar->getType()) - > SE->getTypeSizeInBits(ExitCnt->getType())) { - CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(), - "lftr.wideiv"); + unsigned CmpIndVarSize = SE->getTypeSizeInBits(CmpIndVar->getType()); + unsigned ExitCntSize = SE->getTypeSizeInBits(ExitCnt->getType()); + if (CmpIndVarSize > ExitCntSize) { + const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV(IndVar)); + const SCEV *ARStart = AR->getStart(); + const SCEV *ARStep = AR->getStepRecurrence(*SE); + // For constant IVCount, avoid truncation. + if (isa<SCEVConstant>(ARStart) && isa<SCEVConstant>(IVCount)) { + const APInt &Start = cast<SCEVConstant>(ARStart)->getValue()->getValue(); + APInt Count = cast<SCEVConstant>(IVCount)->getValue()->getValue(); + // Note that the post-inc value of BackedgeTakenCount may have overflowed + // above such that IVCount is now zero. + if (IVCount != BackedgeTakenCount && Count == 0) { + Count = APInt::getMaxValue(Count.getBitWidth()).zext(CmpIndVarSize); + ++Count; + } + else + Count = Count.zext(CmpIndVarSize); + APInt NewLimit; + if (cast<SCEVConstant>(ARStep)->getValue()->isNegative()) + NewLimit = Start - Count; + else + NewLimit = Start + Count; + ExitCnt = ConstantInt::get(CmpIndVar->getType(), NewLimit); + + DEBUG(dbgs() << " Widen RHS:\t" << *ExitCnt << "\n"); + } else { + CmpIndVar = Builder.CreateTrunc(CmpIndVar, ExitCnt->getType(), + "lftr.wideiv"); + } } - Value *Cond = Builder.CreateICmp(P, CmpIndVar, ExitCnt, "exitcond"); Value *OrigCond = BI->getCondition(); // It's tempting to use replaceAllUsesWith here to fully replace the old |