diff options
author | Sanjay Patel <spatel@rotateright.com> | 2019-11-13 15:41:26 -0500 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2019-11-13 15:57:35 -0500 |
commit | a3e61946c5bd7bdfab15af76b292e52d6ffa27f7 (patch) | |
tree | e774948420156e303bbf01091ce5984b38dec136 /llvm/lib/Transforms/Vectorize | |
parent | 52980576ee4a5683aa9a428b76335ed617f142ab (diff) | |
download | bcm5719-llvm-a3e61946c5bd7bdfab15af76b292e52d6ffa27f7.tar.gz bcm5719-llvm-a3e61946c5bd7bdfab15af76b292e52d6ffa27f7.zip |
[SLP] fix miscompile on min/max reductions with extra uses (PR43948)
The bug manifests as replacing a reduction operand with an undef
value.
The problem appears to be limited to cases where a min/max reduction
has extra uses of the compare operand to the select.
In the general case, we are tracking "ExternallyUsedValues" and
an "IgnoreList" of the reduction operations, but those may not apply
to the final compare+select in a min/max reduction.
For that, we use replaceAllUsesWith (RAUW) to ensure that the new
vectorized reduction values are transferred to all subsequent users.
Differential Revision: https://reviews.llvm.org/D70148
Diffstat (limited to 'llvm/lib/Transforms/Vectorize')
-rw-r--r-- | llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 60c76657a87..a8ba03dafff 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -6690,8 +6690,21 @@ public: VectorizedTree = VectReductionData.createOp(Builder, "op.extra", I); } } - // Update users. + + // Update users. For a min/max reduction that ends with a compare and + // select, we also have to RAUW for the compare instruction feeding the + // reduction root. That's because the original compare may have extra uses + // besides the final select of the reduction. + if (ReductionData.isMinMax() && isa<SelectInst>(VectorizedTree)) { + assert(isa<SelectInst>(ReductionRoot) && + "Expected min/max reduction to have select root instruction"); + + Value *ScalarCond = cast<SelectInst>(ReductionRoot)->getCondition(); + Value *VectorCond = cast<SelectInst>(VectorizedTree)->getCondition(); + ScalarCond->replaceAllUsesWith(VectorCond); + } ReductionRoot->replaceAllUsesWith(VectorizedTree); + // Mark all scalar reduction ops for deletion, they are replaced by the // vector reductions. V.eraseInstructions(IgnoreList); |