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; } +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 > phi_iter = BB->phis(); + for ( auto & currentPhi : phi_iter ) { + PHINode *phiNode = dyn_cast(¤tPhi); + if (!phiNode) + continue; + + if (!SE->isSCEVable(phiNode->getType())) + continue; + + const SCEV *phiSCEV = SE->getSCEVAtScope(phiNode, L); + if (!phiSCEV) + continue; + + const SCEVAddRecExpr *phiBasePtrSCEV = dyn_cast(phiSCEV); + if (!phiBasePtrSCEV) + continue; + + if (!phiBasePtrSCEV->getStart()) + 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) { + // Both the start and the increment are identical. + 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 +} +