diff options
| author | Wei Mi <wmi@google.com> | 2016-07-18 20:59:53 +0000 |
|---|---|---|
| committer | Wei Mi <wmi@google.com> | 2016-07-18 20:59:53 +0000 |
| commit | 1fd25726afcec5de0143022f6a742ff33a6bd080 (patch) | |
| tree | 3f1d2a6c908fc4abd5d061044559d8f55bd80bd9 /llvm/lib/Transforms | |
| parent | 5f5eb58eb5c19620d669608c25a505f0f45d35d7 (diff) | |
| download | bcm5719-llvm-1fd25726afcec5de0143022f6a742ff33a6bd080.tar.gz bcm5719-llvm-1fd25726afcec5de0143022f6a742ff33a6bd080.zip | |
Use uniforms set to populate VecValuesToIgnore.
For instructions in uniform set, they will not have vector versions so
add them to VecValuesToIgnore.
For induction vars, those only used in uniform instructions or consecutive
ptrs instructions have already been added to VecValuesToIgnore above. For
those induction vars which are only used in uniform instructions or
non-consecutive/non-gather scatter ptr instructions, the related phi and
update will also be added into VecValuesToIgnore set.
The change will make the vector RegUsages estimation less conservative.
Differential Revision: https://reviews.llvm.org/D20474
llvm-svn: 275912
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 89 |
1 files changed, 40 insertions, 49 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 8b85e320d3b..d42c9cb6e84 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -6156,6 +6156,16 @@ bool LoopVectorizationCostModel::isConsecutiveLoadOrStore(Instruction *Inst) { return false; } +/// Take the pointer operand from the Load/Store instruction. +/// Returns NULL if this is not a valid Load/Store instruction. +static Value *getPointerOperand(Value *I) { + if (LoadInst *LI = dyn_cast<LoadInst>(I)) + return LI->getPointerOperand(); + if (StoreInst *SI = dyn_cast<StoreInst>(I)) + return SI->getPointerOperand(); + return nullptr; +} + void LoopVectorizationCostModel::collectValuesToIgnore() { // Ignore ephemeral values. CodeMetrics::collectEphemeralValues(TheLoop, AC, ValuesToIgnore); @@ -6168,63 +6178,44 @@ void LoopVectorizationCostModel::collectValuesToIgnore() { VecValuesToIgnore.insert(Casts.begin(), Casts.end()); } - // Ignore induction phis that are only used in either GetElementPtr or ICmp - // instruction to exit loop. Induction variables usually have large types and - // can have big impact when estimating register usage. - // This is for when VF > 1. + // Insert uniform instruction into VecValuesToIgnore. + // Collect non-gather/scatter and non-consecutive ptr in NonConsecutivePtr. + SmallPtrSet<Instruction *, 8> NonConsecutivePtr; + for (auto *BB : TheLoop->getBlocks()) { + for (auto &I : *BB) { + if (Legal->isUniformAfterVectorization(&I)) + VecValuesToIgnore.insert(&I); + Instruction *PI = dyn_cast_or_null<Instruction>(getPointerOperand(&I)); + if (PI && !Legal->isConsecutivePtr(PI) && + !isGatherOrScatterLegal(&I, PI, Legal)) + NonConsecutivePtr.insert(PI); + } + } + + // Ignore induction phis that are either used in uniform instructions or + // NonConsecutivePtr. for (auto &Induction : *Legal->getInductionVars()) { auto *PN = Induction.first; auto *UpdateV = PN->getIncomingValueForBlock(TheLoop->getLoopLatch()); - // Check that the PHI is only used by the induction increment (UpdateV) or - // by GEPs. Then check that UpdateV is only used by a compare instruction, - // the loop header PHI, or by GEPs. - // FIXME: Need precise def-use analysis to determine if this instruction - // variable will be vectorized. - if (all_of(PN->users(), - [&](const User *U) -> bool { - return U == UpdateV || isa<GetElementPtrInst>(U); - }) && - all_of(UpdateV->users(), [&](const User *U) -> bool { - return U == PN || isa<ICmpInst>(U) || isa<GetElementPtrInst>(U); - })) { + if (std::all_of(PN->user_begin(), PN->user_end(), + [&](User *U) -> bool { + Instruction *UI = dyn_cast<Instruction>(U); + return U == UpdateV || !TheLoop->contains(UI) || + Legal->isUniformAfterVectorization(UI) || + NonConsecutivePtr.count(UI); + }) && + std::all_of(UpdateV->user_begin(), UpdateV->user_end(), + [&](User *U) -> bool { + Instruction *UI = dyn_cast<Instruction>(U); + return U == PN || !TheLoop->contains(UI) || + Legal->isUniformAfterVectorization(UI) || + NonConsecutivePtr.count(UI); + })) { VecValuesToIgnore.insert(PN); VecValuesToIgnore.insert(UpdateV); } } - - // Ignore instructions that will not be vectorized. - // This is for when VF > 1. - for (BasicBlock *BB : TheLoop->blocks()) { - for (auto &Inst : *BB) { - switch (Inst.getOpcode()) - case Instruction::GetElementPtr: { - // Ignore GEP if its last operand is an induction variable so that it is - // a consecutive load/store and won't be vectorized as scatter/gather - // pattern. - - GetElementPtrInst *Gep = cast<GetElementPtrInst>(&Inst); - unsigned NumOperands = Gep->getNumOperands(); - unsigned InductionOperand = getGEPInductionOperand(Gep); - bool GepToIgnore = true; - - // Check that all of the gep indices are uniform except for the - // induction operand. - for (unsigned i = 0; i != NumOperands; ++i) { - if (i != InductionOperand && - !PSE.getSE()->isLoopInvariant(PSE.getSCEV(Gep->getOperand(i)), - TheLoop)) { - GepToIgnore = false; - break; - } - } - - if (GepToIgnore) - VecValuesToIgnore.insert(&Inst); - break; - } - } - } } void InnerLoopUnroller::scalarizeInstruction(Instruction *Instr, |

