mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 23:48:56 +00:00
[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:
parent
041b4a8eaf
commit
32d044fcf5
@ -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());
|
||||
|
30
test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll
Normal file
30
test/CodeGen/PowerPC/ppc64-pre-inc-no-extra-phi.ll
Normal 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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user