Index: lib/Target/PowerPC/PPCLoopPreIncPrep.cpp =================================================================== --- lib/Target/PowerPC/PPCLoopPreIncPrep.cpp +++ 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 @@ cl::Hidden, cl::init(16), cl::desc("Potential PHI threshold for PPC preinc loop prep")); +STATISTIC(PHINodeAlreadyExists, "The PHI Node already exists."); + namespace llvm { void initializePPCLoopPreIncPrepPass(PassRegistry&); @@ -88,6 +91,9 @@ AU.addRequired(); } + bool alreadyPrepared(Loop *L, Instruction* MemI, + const SCEV *BasePtrStartSCEV, + const SCEVConstant *BasePtrIncSCEV); bool runOnFunction(Function &F) override; bool runOnLoop(Loop *L); @@ -177,6 +183,67 @@ 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) { + bool FoundPHI = false; + + BasicBlock *BB = MemI->getParent(); + if (!BB) + return FoundPHI; + + BasicBlock *PredBB = L->getLoopPredecessor(); + BasicBlock *LatchBB = L->getLoopLatch(); + + if (!PredBB || !LatchBB) + return FoundPHI; + + // 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 *PhiNode = dyn_cast(&CurrentPhi); + if (!PhiNode) + continue; + + if (!SE->isSCEVable(PhiNode->getType())) + continue; + + const SCEV *PhiSCEV = SE->getSCEVAtScope(PhiNode, L); + + const SCEVAddRecExpr *PhiBasePtrSCEV = dyn_cast(PhiSCEV); + if (!PhiBasePtrSCEV) + continue; + + const SCEVConstant *PhiBasePtrIncSCEV = + dyn_cast(PhiBasePtrSCEV->getStepRecurrence(*SE)); + if (!PhiBasePtrIncSCEV) + continue; + + if (PhiNode->getNumIncomingValues() == 2) { + if ( (PhiNode->getIncomingBlock(0) == LatchBB && + PhiNode->getIncomingBlock(1) == PredBB) || + (PhiNode->getIncomingBlock(1) == LatchBB && + PhiNode->getIncomingBlock(0) == PredBB) ) { + if (PhiBasePtrSCEV->getStart() == BasePtrStartSCEV && + PhiBasePtrIncSCEV == BasePtrIncSCEV) { + // The existing PHI (PhiNode) has the same start and increment as the + // PHI that we wanted to create. + FoundPHI = true; + } + } + } + } + + if (FoundPHI) + PHINodeAlreadyExists++; + + return FoundPHI; +} + bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { bool MadeChange = false; @@ -347,6 +414,9 @@ 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()); Index: test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll @@ -0,0 +1,30 @@ +; 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 +} +