Index: llvm/trunk/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp +++ llvm/trunk/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, "PHI node already in pre-increment form"); + 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,62 @@ 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 PHIIter = BB->phis(); + for (auto & CurrentPHI : PHIIter) { + PHINode *CurrentPHINode = dyn_cast(&CurrentPHI); + if (!CurrentPHINode) + continue; + + if (!SE->isSCEVable(CurrentPHINode->getType())) + continue; + + const SCEV *PHISCEV = SE->getSCEVAtScope(CurrentPHINode, L); + + const SCEVAddRecExpr *PHIBasePtrSCEV = dyn_cast(PHISCEV); + if (!PHIBasePtrSCEV) + continue; + + const SCEVConstant *PHIBasePtrIncSCEV = + dyn_cast(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 @@ 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: llvm/trunk/test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll +++ llvm/trunk/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 +} +