summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorMax Kazantsev <max.kazantsev@azul.com>2018-11-01 06:47:01 +0000
committerMax Kazantsev <max.kazantsev@azul.com>2018-11-01 06:47:01 +0000
commit3d347bf545d51156b3c1bf6ed93100369568a550 (patch)
tree6345424779cffca969eda3fe6f73518cd2a26fc8 /llvm/lib/Transforms
parente0a2613aeaae93bf75ccc6c616fec3c45147a3df (diff)
downloadbcm5719-llvm-3d347bf545d51156b3c1bf6ed93100369568a550.tar.gz
bcm5719-llvm-3d347bf545d51156b3c1bf6ed93100369568a550.zip
[IndVars] Smart hard uses detection
When rewriting loop exit values, IndVars considers this transform not profitable if the loop instruction has a loop user which it believes cannot be optimized away. In current implementation only calls that immediately use the instruction are considered as such. This patch extends the definition of "hard" users to any side-effecting instructions (which usually cannot be optimized away from the loop) and also allows handling of not just immediate users, but use chains. Differentlai Revision: https://reviews.llvm.org/D51584 Reviewed By: etherzhhb llvm-svn: 345814
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp39
1 files changed, 26 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index ec51ad71abc..3e4e0f46ca3 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -145,6 +145,7 @@ class IndVarSimplify {
bool canLoopBeDeleted(Loop *L, SmallVector<RewritePhi, 8> &RewritePhiSet);
bool rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);
bool rewriteFirstIterationLoopExitValues(Loop *L);
+ bool hasHardUserWithinLoop(const Loop *L, const Instruction *I) const;
bool linearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
PHINode *IndVar, SCEVExpander &Rewriter);
@@ -524,6 +525,29 @@ struct RewritePhi {
// As a side effect, reduces the amount of IV processing within the loop.
//===----------------------------------------------------------------------===//
+bool IndVarSimplify::hasHardUserWithinLoop(const Loop *L, const Instruction *I) const {
+ SmallPtrSet<const Instruction *, 8> Visited;
+ SmallVector<const Instruction *, 8> WorkList;
+ Visited.insert(I);
+ WorkList.push_back(I);
+ while (!WorkList.empty()) {
+ const Instruction *Curr = WorkList.pop_back_val();
+ // This use is outside the loop, nothing to do.
+ if (!L->contains(Curr))
+ continue;
+ // Do we assume it is a "hard" use which will not be eliminated easily?
+ if (Curr->mayHaveSideEffects())
+ return true;
+ // Otherwise, add all its users to worklist.
+ for (auto U : Curr->users()) {
+ auto *UI = cast<Instruction>(U);
+ if (Visited.insert(UI).second)
+ WorkList.push_back(UI);
+ }
+ }
+ return false;
+}
+
/// Check to see if this loop has a computable loop-invariant execution count.
/// If so, this means that we can compute the final value of any expressions
/// that are recurrent in the loop, and substitute the exit values from the loop
@@ -598,19 +622,8 @@ bool IndVarSimplify::rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
// Computing the value outside of the loop brings no benefit if it is
// definitely used inside the loop in a way which can not be optimized
// away.
- if (ExitValue->getSCEVType()>=scMulExpr) {
- bool HasHardInternalUses = false;
- for (auto *IB : Inst->users()) {
- Instruction *UseInstr = cast<Instruction>(IB);
- unsigned Opc = UseInstr->getOpcode();
- if (L->contains(UseInstr) && Opc == Instruction::Call) {
- HasHardInternalUses = true;
- break;
- }
- }
- if (HasHardInternalUses)
- continue;
- }
+ if (hasHardUserWithinLoop(L, Inst))
+ continue;
bool HighCost = Rewriter.isHighCostExpansion(ExitValue, L, Inst);
Value *ExitVal = Rewriter.expandCodeFor(ExitValue, PN->getType(), Inst);
OpenPOWER on IntegriCloud