diff options
author | Nadav Rotem <nrotem@apple.com> | 2013-07-12 06:09:24 +0000 |
---|---|---|
committer | Nadav Rotem <nrotem@apple.com> | 2013-07-12 06:09:24 +0000 |
commit | 523cd85b50c3081d9859fe41afadce13c43e1bc9 (patch) | |
tree | 0d98a3e35e5c9b5903263ba6878b2d519e78a280 /lib/Transforms | |
parent | ac226bbf457f6b5e5210a4a82b1ce678298b2d89 (diff) |
SLPVectorizer: Sink and enable CSE for ExtractElements.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186145 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Vectorize/SLPVectorizer.cpp | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/lib/Transforms/Vectorize/SLPVectorizer.cpp b/lib/Transforms/Vectorize/SLPVectorizer.cpp index 2cf843da5df..12316b4e597 100644 --- a/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1320,6 +1320,9 @@ void BoUpSLP::vectorizeTree() { it != e; ++it) { Value *Scalar = it->Scalar; llvm::User *User = it->User; + + // Skip users that we already RAUW. This happens when one instruction + // has multiple uses of the same value. if (std::find(Scalar->use_begin(), Scalar->use_end(), User) == Scalar->use_end()) continue; @@ -1337,8 +1340,18 @@ void BoUpSLP::vectorizeTree() { Instruction *Loc = 0; if (PHINode *PN = dyn_cast<PHINode>(Vec)) { Loc = PN->getParent()->getFirstInsertionPt(); - } else if (Instruction *Iv = dyn_cast<Instruction>(Vec)){ - Loc = ++((BasicBlock::iterator)*Iv); + } else if (isa<Instruction>(Vec)){ + if (PHINode *PH = dyn_cast<PHINode>(User)) { + for (int i = 0, e = PH->getNumIncomingValues(); i != e; ++i) { + if (PH->getIncomingValue(i) == Scalar) { + Loc = PH->getIncomingBlock(i)->getTerminator(); + break; + } + } + assert(Loc && "Unable to find incoming value for the PHI"); + } else { + Loc = cast<Instruction>(User); + } } else { Loc = F->getEntryBlock().begin(); } @@ -1433,24 +1446,25 @@ void BoUpSLP::optimizeGatherSequence() { BasicBlock *BB = *I; // For all instructions in the function: for (BasicBlock::iterator it = BB->begin(), e = BB->end(); it != e; ++it) { - InsertElementInst *Insert = dyn_cast<InsertElementInst>(it); - if (!Insert || !GatherSeq.count(Insert)) + Instruction *In = it; + if ((!isa<InsertElementInst>(In) && !isa<ExtractElementInst>(In)) || + !GatherSeq.count(In)) continue; // Check if we can replace this instruction with any of the // visited instructions. for (SmallPtrSet<Instruction*, 16>::iterator v = Visited.begin(), ve = Visited.end(); v != ve; ++v) { - if (Insert->isIdenticalTo(*v) && - DT->dominates((*v)->getParent(), Insert->getParent())) { - Insert->replaceAllUsesWith(*v); - ToRemove.push_back(Insert); - Insert = 0; + if (In->isIdenticalTo(*v) && + DT->dominates((*v)->getParent(), In->getParent())) { + In->replaceAllUsesWith(*v); + ToRemove.push_back(In); + In = 0; break; } } - if (Insert) - Visited.insert(Insert); + if (In) + Visited.insert(In); } } |