From 22920b59864cac3b62d158fd4111cfda3c09c67a Mon Sep 17 00:00:00 2001 From: Chris Lattner <sabre@nondot.org> Date: Sun, 26 Dec 2010 20:45:45 +0000 Subject: [PATCH] sketch more of this out. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122567 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 84 +++++++++++++++----- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 270c4afcc1d..eb7d4930edf 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -17,6 +17,8 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -26,6 +28,9 @@ using namespace llvm; namespace { class LoopIdiomRecognize : public LoopPass { + Loop *CurLoop; + const TargetData *TD; + ScalarEvolution *SE; public: static char ID; explicit LoopIdiomRecognize() : LoopPass(ID) { @@ -34,7 +39,7 @@ namespace { bool runOnLoop(Loop *L, LPPassManager &LPM); - bool scanBlock(BasicBlock *BB, Loop *L); + bool processLoopStore(StoreInst *SI, const SCEV *BECount); /// This transformation requires natural loop information & requires that /// loop preheaders be inserted into the CFG. @@ -66,38 +71,77 @@ INITIALIZE_PASS_END(LoopIdiomRecognize, "loop-idiom", "Recognize loop idioms", Pass *llvm::createLoopIdiomPass() { return new LoopIdiomRecognize(); } bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) { + CurLoop = L; + // We only look at trivial single basic block loops. // TODO: eventually support more complex loops, scanning the header. if (L->getBlocks().size() != 1) return false; + // The trip count of the loop must be analyzable. + SE = &getAnalysis<ScalarEvolution>(); + if (!SE->hasLoopInvariantBackedgeTakenCount(L)) + return false; + const SCEV *BECount = SE->getBackedgeTakenCount(L); + if (isa<SCEVCouldNotCompute>(BECount)) return false; + + // We require target data for now. + TD = getAnalysisIfAvailable<TargetData>(); + if (TD == 0) return false; + BasicBlock *BB = L->getHeader(); - DEBUG(dbgs() << "Loop Idiom Recognize: F[" << BB->getParent()->getName() + DEBUG(dbgs() << "loop-idiom Scanning: F[" << BB->getParent()->getName() << "] Loop %" << BB->getName() << "\n"); - return scanBlock(BB, L); + bool MadeChange = false; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { + // Look for store instructions, which may be memsets. + if (StoreInst *SI = dyn_cast<StoreInst>(I++)) + MadeChange |= processLoopStore(SI, BECount); + } + + return MadeChange; } /// scanBlock - Look over a block to see if we can promote anything out of it. -bool LoopIdiomRecognize::scanBlock(BasicBlock *BB, Loop *L) { - ScalarEvolution &SE = getAnalysis<ScalarEvolution>(); +bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) { + Value *StoredVal = SI->getValueOperand(); - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { - // Look for store instructions, which may be memsets. - StoreInst *SI = dyn_cast<StoreInst>(I++); - if (SI == 0) continue; - - // See if the pointer expression is an AddRec like {base,+,1} on the current - // loop, which indicates a strided store. If we have something else, it's a - // random store we can't handle. - const SCEVAddRecExpr *Ev = - dyn_cast<SCEVAddRecExpr>(SE.getSCEV(SI->getPointerOperand())); - if (Ev == 0 || Ev->getLoop() != L) - continue; - - errs() << "Found strided store: " << *Ev << "\n"; - } + // Check to see if the store updates all bits in memory. We don't want to + // process things like a store of i3. We also require that the store be a + // multiple of a byte. + uint64_t SizeInBits = TD->getTypeSizeInBits(StoredVal->getType()); + if ((SizeInBits & 7) || (SizeInBits >> 32) != 0 || + SizeInBits != TD->getTypeStoreSizeInBits(StoredVal->getType())) + return false; + // See if the pointer expression is an AddRec like {base,+,1} on the current + // loop, which indicates a strided store. If we have something else, it's a + // random store we can't handle. + const SCEVAddRecExpr *Ev = + dyn_cast<SCEVAddRecExpr>(SE->getSCEV(SI->getPointerOperand())); + if (Ev == 0 || Ev->getLoop() != CurLoop || !Ev->isAffine()) + return false; + + // Check to see if the stride matches the size of the store. If so, then we + // know that every byte is touched in the loop. + unsigned StoreSize = (unsigned)SizeInBits >> 3; + const SCEVConstant *Stride = dyn_cast<SCEVConstant>(Ev->getOperand(1)); + if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) + return false; + + errs() << "Found strided store: " << *Ev << "\n"; + + // Check for memcpy here. + + + // If the stored value is a byte-wise value (like i32 -1), then it may be + // turned into a memset of i8 -1, assuming that all the consequtive bytes + // are stored. A store of i32 0x01020304 can never be turned into a memset. + Value *SplatValue = isBytewiseValue(StoredVal); + if (SplatValue == 0) return false; + + return false; }