From a3d2f703a5b3cf531cd8a472454c0f7b4fd87bbc Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Wed, 23 Nov 2016 17:43:15 +0000 Subject: [LoadStoreVectorizer] Enable vectorization of stores in the presence of an aliasing load Summary: The "getVectorizablePrefix" method would give up if it found an aliasing load for a store chain. In practice, the aliasing load can be treated as a memory barrier and all stores that precede it are a valid vectorizable prefix. Issue found by volkan in D26962. Testcase is a pruned version of the one in the original patch. Reviewers: jlebar, arsenm, tstellarAMD Subscribers: mzolotukhin, wdng, nhaehnle, anna, volkan, llvm-commits Differential Revision: https://reviews.llvm.org/D27008 llvm-svn: 287781 --- .../Transforms/Vectorize/LoadStoreVectorizer.cpp | 28 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp') diff --git a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp index ead17d01a96..c44a393cf84 100644 --- a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp @@ -477,10 +477,23 @@ Vectorizer::getVectorizablePrefix(ArrayRef Chain) { // Loop until we find an instruction in ChainInstrs that we can't vectorize. unsigned ChainInstrIdx = 0; + Instruction *BarrierMemoryInstr = nullptr; + for (unsigned E = ChainInstrs.size(); ChainInstrIdx < E; ++ChainInstrIdx) { Instruction *ChainInstr = ChainInstrs[ChainInstrIdx]; - bool AliasFound = false; + + // If a barrier memory instruction was found, chain instructions that follow + // will not be added to the valid prefix. + if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, ChainInstr)) + break; + + // Check (in BB order) if any instruction prevents ChainInstr from being + // vectorized. Find and store the first such "conflicting" instruction. for (Instruction *MemInstr : MemoryInstrs) { + // If a barrier memory instruction was found, do not check past it. + if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, MemInstr)) + break; + if (isa(MemInstr) && isa(ChainInstr)) continue; @@ -508,12 +521,21 @@ Vectorizer::getVectorizablePrefix(ArrayRef Chain) { << " " << *ChainInstr << '\n' << " " << *getPointerOperand(ChainInstr) << '\n'; }); - AliasFound = true; + // Save this aliasing memory instruction as a barrier, but allow other + // instructions that precede the barrier to be vectorized with this one. + BarrierMemoryInstr = MemInstr; break; } } - if (AliasFound) + // Continue the search only for store chains, since vectorizing stores that + // precede an aliasing load is valid. Conversely, vectorizing loads is valid + // up to an aliasing store, but should not pull loads from further down in + // the basic block. + if (IsLoadChain && BarrierMemoryInstr) { + // The BarrierMemoryInstr is a store that precedes ChainInstr. + assert(OBB.dominates(BarrierMemoryInstr, ChainInstr)); break; + } } // Find the largest prefix of Chain whose elements are all in -- cgit v1.2.3