diff options
author | Justin Lebar <jlebar@google.com> | 2016-07-20 00:55:12 +0000 |
---|---|---|
committer | Justin Lebar <jlebar@google.com> | 2016-07-20 00:55:12 +0000 |
commit | 6114b378380904423cf7dd5abc94b11dfe5f59f9 (patch) | |
tree | 0ebc3ccf63f12bf04a13c979bdc230699b6f9a08 /llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp | |
parent | 58dda5a7169a8f1921f179842febd21fba48d624 (diff) | |
download | bcm5719-llvm-6114b378380904423cf7dd5abc94b11dfe5f59f9.tar.gz bcm5719-llvm-6114b378380904423cf7dd5abc94b11dfe5f59f9.zip |
[LSV] Don't assume that loads/stores appear in address order in the BB.
Summary:
getVectorizablePrefix previously didn't work properly in the face of
aliasing loads/stores. It unwittingly assumed that the loads/stores
appeared in the BB in address order. If they didn't, it would do the
wrong thing.
Reviewers: asbirlea, tstellarAMD
Subscribers: arsenm, llvm-commits, mzolotukhin
Differential Revision: https://reviews.llvm.org/D22535
llvm-svn: 276072
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp index 1027eacb3ad..ec3e734184a 100644 --- a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp @@ -108,7 +108,8 @@ private: /// intervening instructions which may affect the memory accessed by the /// instructions within Chain. /// - /// The elements of \p Chain must be all loads or all stores. + /// The elements of \p Chain must be all loads or all stores and must be in + /// address order. ArrayRef<Value *> getVectorizablePrefix(ArrayRef<Value *> Chain); /// Collects load and store instructions to vectorize. @@ -424,6 +425,7 @@ Vectorizer::splitOddVectorElts(ArrayRef<Value *> Chain, } ArrayRef<Value *> Vectorizer::getVectorizablePrefix(ArrayRef<Value *> Chain) { + // These are in BB order, unlike Chain, which is in address order. SmallVector<std::pair<Value *, unsigned>, 16> MemoryInstrs; SmallVector<std::pair<Value *, unsigned>, 16> ChainInstrs; @@ -444,31 +446,34 @@ ArrayRef<Value *> Vectorizer::getVectorizablePrefix(ArrayRef<Value *> Chain) { assert(Chain.size() == ChainInstrs.size() && "All instrs in Chain must be within range getBoundaryInstrs(Chain)."); - unsigned ChainIdx = 0; - for (auto EntryChain : ChainInstrs) { - Value *ChainInstrValue = EntryChain.first; - unsigned ChainInstrIdx = EntryChain.second; + // Loop until we find an instruction in ChainInstrs that we can't vectorize. + unsigned ChainInstrIdx, ChainInstrsLen; + for (ChainInstrIdx = 0, ChainInstrsLen = ChainInstrs.size(); + ChainInstrIdx < ChainInstrsLen; ++ChainInstrIdx) { + Value *ChainInstr = ChainInstrs[ChainInstrIdx].first; + unsigned ChainInstrLoc = ChainInstrs[ChainInstrIdx].second; + bool AliasFound = false; for (auto EntryMem : MemoryInstrs) { - Value *MemInstrValue = EntryMem.first; - unsigned MemInstrIdx = EntryMem.second; - if (isa<LoadInst>(MemInstrValue) && isa<LoadInst>(ChainInstrValue)) + Value *MemInstr = EntryMem.first; + unsigned MemInstrLoc = EntryMem.second; + if (isa<LoadInst>(MemInstr) && isa<LoadInst>(ChainInstr)) continue; // We can ignore the alias as long as the load comes before the store, // because that means we won't be moving the load past the store to // vectorize it (the vectorized load is inserted at the location of the // first load in the chain). - if (isa<StoreInst>(MemInstrValue) && isa<LoadInst>(ChainInstrValue) && - ChainInstrIdx < MemInstrIdx) + if (isa<StoreInst>(MemInstr) && isa<LoadInst>(ChainInstr) && + ChainInstrLoc < MemInstrLoc) continue; // Same case, but in reverse. - if (isa<LoadInst>(MemInstrValue) && isa<StoreInst>(ChainInstrValue) && - ChainInstrIdx > MemInstrIdx) + if (isa<LoadInst>(MemInstr) && isa<StoreInst>(ChainInstr) && + ChainInstrLoc > MemInstrLoc) continue; - Instruction *M0 = cast<Instruction>(MemInstrValue); - Instruction *M1 = cast<Instruction>(ChainInstrValue); + Instruction *M0 = cast<Instruction>(MemInstr); + Instruction *M1 = cast<Instruction>(ChainInstr); if (!AA.isNoAlias(MemoryLocation::get(M0), MemoryLocation::get(M1))) { DEBUG({ @@ -477,19 +482,34 @@ ArrayRef<Value *> Vectorizer::getVectorizablePrefix(ArrayRef<Value *> Chain) { dbgs() << "LSV: Found alias:\n" " Aliasing instruction and pointer:\n" - << " " << *MemInstrValue << '\n' + << " " << *MemInstr << '\n' << " " << *Ptr0 << '\n' << " Aliased instruction and pointer:\n" - << " " << *ChainInstrValue << '\n' + << " " << *ChainInstr << '\n' << " " << *Ptr1 << '\n'; }); - - return Chain.slice(0, ChainIdx); + AliasFound = true; + break; } } - ChainIdx++; + if (AliasFound) + break; + } + + // Find the largest prefix of Chain whose elements are all in + // ChainInstrs[0, ChainInstrIdx). This is the largest vectorizable prefix of + // Chain. (Recall that Chain is in address order, but ChainInstrs is in BB + // order.) + auto VectorizableChainInstrs = + makeArrayRef(ChainInstrs.data(), ChainInstrIdx); + unsigned ChainIdx, ChainLen; + for (ChainIdx = 0, ChainLen = Chain.size(); ChainIdx < ChainLen; ++ChainIdx) { + Value *V = Chain[ChainIdx]; + if (!any_of(VectorizableChainInstrs, + [V](std::pair<Value *, unsigned> CI) { return V == CI.first; })) + break; } - return Chain; + return Chain.slice(0, ChainIdx); } std::pair<ValueListMap, ValueListMap> |