summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
diff options
context:
space:
mode:
authorJustin Lebar <jlebar@google.com>2016-07-20 00:55:12 +0000
committerJustin Lebar <jlebar@google.com>2016-07-20 00:55:12 +0000
commit6114b378380904423cf7dd5abc94b11dfe5f59f9 (patch)
tree0ebc3ccf63f12bf04a13c979bdc230699b6f9a08 /llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
parent58dda5a7169a8f1921f179842febd21fba48d624 (diff)
downloadbcm5719-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.cpp60
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>
OpenPOWER on IntegriCloud