summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCLoopPreIncPrep.cpp')
-rw-r--r--lib/Target/PowerPC/PPCLoopPreIncPrep.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp b/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp
index a349fa1b4090..cdf544bdfac3 100644
--- a/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp
+++ b/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp
@@ -28,6 +28,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpander.h"
@@ -61,6 +62,8 @@ static cl::opt<unsigned> MaxVars("ppc-preinc-prep-max-vars",
cl::Hidden, cl::init(16),
cl::desc("Potential PHI threshold for PPC preinc loop prep"));
+STATISTIC(PHINodeAlreadyExists, "PHI node already in pre-increment form");
+
namespace llvm {
void initializePPCLoopPreIncPrepPass(PassRegistry&);
@@ -88,6 +91,9 @@ namespace {
AU.addRequired<ScalarEvolutionWrapperPass>();
}
+ bool alreadyPrepared(Loop *L, Instruction* MemI,
+ const SCEV *BasePtrStartSCEV,
+ const SCEVConstant *BasePtrIncSCEV);
bool runOnFunction(Function &F) override;
bool runOnLoop(Loop *L);
@@ -177,6 +183,62 @@ bool PPCLoopPreIncPrep::runOnFunction(Function &F) {
return MadeChange;
}
+// In order to prepare for the pre-increment a PHI is added.
+// This function will check to see if that PHI already exists and will return
+// true if it found an existing PHI with the same start and increment as the
+// one we wanted to create.
+bool PPCLoopPreIncPrep::alreadyPrepared(Loop *L, Instruction* MemI,
+ const SCEV *BasePtrStartSCEV,
+ const SCEVConstant *BasePtrIncSCEV) {
+ BasicBlock *BB = MemI->getParent();
+ if (!BB)
+ return false;
+
+ BasicBlock *PredBB = L->getLoopPredecessor();
+ BasicBlock *LatchBB = L->getLoopLatch();
+
+ if (!PredBB || !LatchBB)
+ return false;
+
+ // Run through the PHIs and see if we have some that looks like a preparation
+ iterator_range<BasicBlock::phi_iterator> PHIIter = BB->phis();
+ for (auto & CurrentPHI : PHIIter) {
+ PHINode *CurrentPHINode = dyn_cast<PHINode>(&CurrentPHI);
+ if (!CurrentPHINode)
+ continue;
+
+ if (!SE->isSCEVable(CurrentPHINode->getType()))
+ continue;
+
+ const SCEV *PHISCEV = SE->getSCEVAtScope(CurrentPHINode, L);
+
+ const SCEVAddRecExpr *PHIBasePtrSCEV = dyn_cast<SCEVAddRecExpr>(PHISCEV);
+ if (!PHIBasePtrSCEV)
+ continue;
+
+ const SCEVConstant *PHIBasePtrIncSCEV =
+ dyn_cast<SCEVConstant>(PHIBasePtrSCEV->getStepRecurrence(*SE));
+ if (!PHIBasePtrIncSCEV)
+ continue;
+
+ if (CurrentPHINode->getNumIncomingValues() == 2) {
+ if ( (CurrentPHINode->getIncomingBlock(0) == LatchBB &&
+ CurrentPHINode->getIncomingBlock(1) == PredBB) ||
+ (CurrentPHINode->getIncomingBlock(1) == LatchBB &&
+ CurrentPHINode->getIncomingBlock(0) == PredBB) ) {
+ if (PHIBasePtrSCEV->getStart() == BasePtrStartSCEV &&
+ PHIBasePtrIncSCEV == BasePtrIncSCEV) {
+ // The existing PHI (CurrentPHINode) has the same start and increment
+ // as the PHI that we wanted to create.
+ ++PHINodeAlreadyExists;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
bool PPCLoopPreIncPrep::runOnLoop(Loop *L) {
bool MadeChange = false;
@@ -347,6 +409,9 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) {
DEBUG(dbgs() << "PIP: New start is: " << *BasePtrStartSCEV << "\n");
+ if (alreadyPrepared(L, MemI, BasePtrStartSCEV, BasePtrIncSCEV))
+ continue;
+
PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount,
MemI->hasName() ? MemI->getName() + ".phi" : "",
Header->getFirstNonPHI());