diff options
author | Chad Rosier <mcrosier@codeaurora.org> | 2014-09-17 14:10:33 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@codeaurora.org> | 2014-09-17 14:10:33 +0000 |
commit | bb99f40530be9eee3f461c62436b2b5f723e515b (patch) | |
tree | 08f41bb3f2055ddfbc3dbca1a89d110ee3bdfec1 /llvm/lib/Transforms | |
parent | ebdf90ca009b6ae97980ee6b43acba3b1638546e (diff) | |
download | bcm5719-llvm-bb99f40530be9eee3f461c62436b2b5f723e515b.tar.gz bcm5719-llvm-bb99f40530be9eee3f461c62436b2b5f723e515b.zip |
[IndVarSimplify] Widen loop compare instructions.
This improves other optimizations such as LSR. A sext may be added to the
compare's other operand, but this can often be hoisted outside of the loop.
llvm-svn: 217953
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 27e5ec8cf40..532666ea7c1 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -762,6 +762,8 @@ protected: Instruction *WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter); + bool WidenLoopCompare(NarrowIVDefUse DU); + void pushNarrowIVUsers(Instruction *NarrowDef, Instruction *WideDef); }; } // anonymous namespace @@ -926,6 +928,32 @@ static void truncateIVUse(NarrowIVDefUse DU, DominatorTree *DT) { DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc); } +/// If the narrow use is a compare instruction, then widen the compare +// (and possibly the other operand). The extend operation is hoisted into the +// loop preheader as far as possible. +bool WidenIV::WidenLoopCompare(NarrowIVDefUse DU) { + ICmpInst *Cmp = dyn_cast<ICmpInst>(DU.NarrowUse); + if (!Cmp) + return false; + + Value *Op = Cmp->getOperand(Cmp->getOperand(0) == DU.NarrowDef ? 1 : 0); + unsigned CastWidth = SE->getTypeSizeInBits(Op->getType()); + unsigned IVWidth = SE->getTypeSizeInBits(WideType); + assert (CastWidth <= IVWidth && "Unexpected width while widening compare."); + + // Widen the compare instruction. + IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT)); + DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, DU.WideDef); + + // Widen the other operand of the compare, if necessary. + if (CastWidth < IVWidth) { + bool IsSigned = CmpInst::isSigned(Cmp->getPredicate()); + Value *ExtOp = getExtend(Op, WideType, IsSigned, Cmp); + DU.NarrowUse->replaceUsesOfWith(Op, ExtOp); + } + return true; +} + /// WidenIVUse - Determine whether an individual user of the narrow IV can be /// widened. If so, return the wide clone of the user. Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) { @@ -993,10 +1021,15 @@ Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) { // Does this user itself evaluate to a recurrence after widening? const SCEVAddRecExpr *WideAddRec = GetWideRecurrence(DU.NarrowUse); + if (!WideAddRec) + WideAddRec = GetExtendedOperandRecurrence(DU); + if (!WideAddRec) { - WideAddRec = GetExtendedOperandRecurrence(DU); - } - if (!WideAddRec) { + // If use is a loop condition, try to promote the condition instead of + // truncating the IV first. + if (WidenLoopCompare(DU)) + return nullptr; + // This user does not evaluate to a recurence after widening, so don't // follow it. Instead insert a Trunc to kill off the original use, // eventually isolating the original narrow IV so it can be removed. |