diff options
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/LoopVectorize.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 2c5fec64c18..8072d06c34b 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -963,6 +963,9 @@ class LoopVectorizeHints { /// Return the loop metadata prefix. static StringRef Prefix() { return "llvm.loop."; } + /// True if there is any unsafe math in the loop. + bool PotentiallyUnsafe; + public: enum ForceKind { FK_Undefined = -1, ///< Not selected. @@ -975,7 +978,7 @@ public: HK_WIDTH), Interleave("interleave.count", DisableInterleaving, HK_UNROLL), Force("vectorize.enable", FK_Undefined, HK_FORCE), - TheLoop(L) { + PotentiallyUnsafe(false), TheLoop(L) { // Populate values with existing loop metadata. getHintsFromMetadata(); @@ -1073,6 +1076,19 @@ public: return getForce() == LoopVectorizeHints::FK_Enabled || getWidth() > 1; } + bool isPotentiallyUnsafe() const { + // Avoid FP vectorization if the target is unsure about proper support. + // This may be related to the SIMD unit in the target not handling + // IEEE 754 FP ops properly, or bad single-to-double promotions. + // Otherwise, a sequence of vectorized loops, even without reduction, + // could lead to different end results on the destination vectors. + return getForce() != LoopVectorizeHints::FK_Enabled && PotentiallyUnsafe; + } + + void setPotentiallyUnsafe() { + PotentiallyUnsafe = true; + } + private: /// Find hints specified in the loop metadata and update local values. void getHintsFromMetadata() { @@ -1234,7 +1250,7 @@ public: const TargetTransformInfo *TTI, LoopAccessAnalysis *LAA, LoopVectorizationRequirements *R, - const LoopVectorizeHints *H) + LoopVectorizeHints *H) : NumPredStores(0), TheLoop(L), PSE(PSE), TLI(TLI), TheFunction(F), TTI(TTI), DT(DT), LAA(LAA), LAI(nullptr), InterleaveInfo(PSE, L, DT), Induction(nullptr), WidestIndTy(nullptr), HasFunNoNaNAttr(false), @@ -1460,7 +1476,7 @@ private: LoopVectorizationRequirements *Requirements; /// Used to emit an analysis of any legality issues. - const LoopVectorizeHints *Hints; + LoopVectorizeHints *Hints; ValueToValueMap Strides; SmallPtrSet<Value *, 8> StrideSet; @@ -1884,6 +1900,21 @@ struct LoopVectorize : public FunctionPass { return false; } + // Check if the target supports potentially unsafe FP vectorization. + // FIXME: Add a check for the type of safety issue (denormal, signaling) + // for the target we're vectorizing for, to make sure none of the + // additional fp-math flags can help. + if (Hints.isPotentiallyUnsafe() && + TTI->isFPVectorizationPotentiallyUnsafe()) { + DEBUG(dbgs() << "LV: Potentially unsafe FP op prevents vectorization.\n"); + emitAnalysisDiag( + F, L, Hints, + VectorizationReport() + << "loop not vectorized due to unsafe FP support."); + emitMissedWarning(F, L, Hints); + return false; + } + // Select the optimal vectorization factor. const LoopVectorizationCostModel::VectorizationFactor VF = CM.selectVectorizationFactor(OptForSize); @@ -4695,12 +4726,23 @@ bool LoopVectorizationLegality::canVectorizeInstrs() { } if (EnableMemAccessVersioning) collectStridedAccess(ST); - } - if (EnableMemAccessVersioning) - if (LoadInst *LI = dyn_cast<LoadInst>(it)) + } else if (LoadInst *LI = dyn_cast<LoadInst>(it)) { + if (EnableMemAccessVersioning) collectStridedAccess(LI); + // FP instructions can allow unsafe algebra, thus vectorizable by + // non-IEEE-754 compliant SIMD units. + // This applies to floating-point math operations and calls, not memory + // operations, shuffles, or casts, as they don't change precision or + // semantics. + } else if (it->getType()->isFloatingPointTy() && + (CI || it->isBinaryOp()) && + !it->hasUnsafeAlgebra()) { + DEBUG(dbgs() << "LV: Found FP op with unsafe algebra.\n"); + Hints->setPotentiallyUnsafe(); + } + // Reduction instructions are allowed to have exit users. // All other instructions must not have external users. if (hasOutsideLoopUser(TheLoop, &*it, AllowedExit)) { |

