///
/// \returns A candidate reduction value if possible, or \code nullptr \endcode
/// if not possible.
-static Value *getReductionValue(PHINode *P, BasicBlock *ParentBB,
- LoopInfo *LI) {
+static Value *getReductionValue(const DominatorTree *DT, PHINode *P,
+ BasicBlock *ParentBB, LoopInfo *LI) {
+ // There are situations where the reduction value is not dominated by the
+ // reduction phi. Vectorizing such cases has been reported to cause
+ // miscompiles. See PR25787.
+ auto DominatedReduxValue = [&](Value *R) {
+ return (
+ dyn_cast<Instruction>(R) &&
+ DT->dominates(P->getParent(), dyn_cast<Instruction>(R)->getParent()));
+ };
+
Value *Rdx = nullptr;
// Return the incoming value if it comes from the same BB as the phi node.
Rdx = P->getIncomingValue(1);
}
- if (Rdx)
+ if (Rdx && DominatedReduxValue(Rdx))
return Rdx;
// Otherwise, check whether we have a loop latch to look at.
Loop *BBL = LI->getLoopFor(ParentBB);
if (!BBL)
- return Rdx;
+ return nullptr;
BasicBlock *BBLatch = BBL->getLoopLatch();
if (!BBLatch)
- return Rdx;
+ return nullptr;
// There is a loop latch, return the incoming value if it comes from
// that. This reduction pattern occassionaly turns up.
Rdx = P->getIncomingValue(1);
}
- return Rdx;
+ if (Rdx && DominatedReduxValue(Rdx))
+ return Rdx;
+
+ return nullptr;
}
/// \brief Attempt to reduce a horizontal reduction.
if (P->getNumIncomingValues() != 2)
return Changed;
- Value *Rdx = getReductionValue(P, BB, LI);
+ Value *Rdx = getReductionValue(DT, P, BB, LI);
// Check if this is a Binary Operator.
BinaryOperator *BI = dyn_cast_or_null<BinaryOperator>(Rdx);