#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"
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&);
AU.addRequired<ScalarEvolutionWrapperPass>();
}
+ bool alreadyPrepared(Loop *L, Instruction* MemI,
+ const SCEV *BasePtrStartSCEV,
+ const SCEVConstant *BasePtrIncSCEV);
bool runOnFunction(Function &F) override;
bool runOnLoop(Loop *L);
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;
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());
--- /dev/null
+; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -verify-machineinstrs | FileCheck %s
+
+@perm = common local_unnamed_addr global [100 x i64] zeroinitializer, align 8
+
+define void @sort_basket() local_unnamed_addr {
+entry:
+ br label %while.cond
+
+while.cond:
+ %l.0 = phi i64 [ 0, %entry ], [ %inc, %while.cond ]
+ %arrayidx = getelementptr inbounds [100 x i64], [100 x i64]* @perm, i64 0, i64 %l.0
+ %0 = load i64, i64* %arrayidx, align 8
+ %cmp = icmp sgt i64 %0, 0
+ %inc = add nuw nsw i64 %l.0, 1
+ br i1 %cmp, label %while.cond, label %while.end
+
+while.end:
+ store i64 0, i64* %arrayidx, align 8
+ ret void
+; CHECK-LABEL: sort_basket
+; CHECK: addi {{[0-9]+}}, {{[0-9]+}}, -8
+; CHECK-NOT: addi {{[0-9]+}}, {{[0-9]+}}, 8
+; CHECK: ldu {{[0-9]+}}, 8({{[0-9]+}})
+; CHECK-NOT: addi {{[0-9]+}}, {{[0-9]+}}, 8
+; CHECK: blr
+}
+