[PowerPC] Check if the pre-increment PHI Node already exists

Preparations to use the per-increment are sometimes done in the target
independent pass Loop Strength Reduction. We try to detect them in the PowerPC
specific pass so that they are not done twice and so that we do not add PHIs
that are not required.

Differential Revision: https://reviews.llvm.org/D36736

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311332 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Stefan Pintilie 2017-08-21 13:36:18 +00:00
parent 041b4a8eaf
commit 32d044fcf5
2 changed files with 95 additions and 0 deletions

View File

@ -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());

View File

@ -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
}