summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/LoopVectorize.cpp')
-rw-r--r--llvm/lib/Transforms/Vectorize/LoopVectorize.cpp54
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)) {
OpenPOWER on IntegriCloud