DK_OptimizationRemarkMissed,
DK_OptimizationRemarkAnalysis,
DK_OptimizationRemarkAnalysisFPCommute,
+ DK_OptimizationRemarkAnalysisAliasing,
DK_OptimizationFailure,
DK_MIRParser,
DK_FirstPluginKind
}
};
+/// Diagnostic information for optimization analysis remarks related to
+/// pointer aliasing.
+class DiagnosticInfoOptimizationRemarkAnalysisAliasing
+ : public DiagnosticInfoOptimizationRemarkAnalysis {
+public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If
+ /// this name matches the regular expression given in -Rpass-analysis=, then
+ /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
+ /// is being emitted. \p DLoc is the location information to use in the
+ /// diagnostic. If line table information is available, the diagnostic will
+ /// include the source code location. \p Msg is the message to show. The
+ /// front-end will append its own message related to options that address
+ /// pointer aliasing legality. Note that this class does not copy this
+ /// message, so this reference must be valid for the whole life time of the
+ /// diagnostic.
+ DiagnosticInfoOptimizationRemarkAnalysisAliasing(const char *PassName,
+ const Function &Fn,
+ const DebugLoc &DLoc,
+ const Twine &Msg)
+ : DiagnosticInfoOptimizationRemarkAnalysis(
+ DK_OptimizationRemarkAnalysisAliasing, PassName, Fn, DLoc, Msg) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
+ }
+};
+
/// Diagnostic information for machine IR parser.
class DiagnosticInfoMIRParser : public DiagnosticInfo {
const SMDiagnostic &Diagnostic;
const DebugLoc &DLoc,
const Twine &Msg);
+/// Emit an optimization analysis remark related to messages about
+/// pointer aliasing. \p PassName is the name of the pass emitting the message.
+/// If -Rpass-analysis= is given and \p PassName matches the regular expression
+/// in -Rpass, then the remark will be emitted. \p Fn is the function triggering
+/// the remark, \p DLoc is the debug location where the diagnostic is generated.
+/// \p Msg is the message string to use.
+void emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DebugLoc &DLoc,
+ const Twine &Msg);
+
/// Diagnostic information for optimization failures.
class DiagnosticInfoOptimizationFailure
: public DiagnosticInfoOptimizationBase {
DLoc, Msg));
}
+void llvm::emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DebugLoc &DLoc,
+ const Twine &Msg) {
+ Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysisAliasing(PassName, Fn,
+ DLoc, Msg));
+}
+
bool DiagnosticInfoOptimizationFailure::isEnabled() const {
// Only print warnings.
return getSeverity() == DS_Warning;
/// followed by a non-expert user.
class LoopVectorizationRequirements {
public:
- LoopVectorizationRequirements() : UnsafeAlgebraInst(nullptr) {}
+ LoopVectorizationRequirements()
+ : NumRuntimePointerChecks(0), UnsafeAlgebraInst(nullptr) {}
void addUnsafeAlgebraInst(Instruction *I) {
// First unsafe algebra instruction.
UnsafeAlgebraInst = I;
}
- bool doesNotMeet(Function *F, const LoopVectorizeHints &Hints) {
+ void addRuntimePointerChecks(unsigned Num) { NumRuntimePointerChecks = Num; }
+
+ bool doesNotMeet(Function *F, Loop *L, const LoopVectorizeHints &Hints) {
+ bool failed = false;
+
if (UnsafeAlgebraInst &&
Hints.getForce() == LoopVectorizeHints::FK_Undefined &&
Hints.getWidth() == 0) {
"order of operations, however IEEE 754 "
"floating-point operations are not "
"commutative");
- return true;
+ failed = true;
}
- return false;
+
+ if (NumRuntimePointerChecks >
+ VectorizerParams::RuntimeMemoryCheckThreshold) {
+ emitOptimizationRemarkAnalysisAliasing(
+ F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(),
+ VectorizationReport()
+ << "cannot prove pointers refer to independent arrays in memory. "
+ "The loop requires "
+ << NumRuntimePointerChecks
+ << " runtime independence checks to vectorize the loop, but that "
+ "would exceed the limit of "
+ << VectorizerParams::RuntimeMemoryCheckThreshold << " checks");
+ DEBUG(dbgs() << "LV: Too many memory checks needed.\n");
+ failed = true;
+ }
+
+ return failed;
}
private:
+ unsigned NumRuntimePointerChecks;
Instruction *UnsafeAlgebraInst;
};
std::string VecDiagMsg, IntDiagMsg;
bool VectorizeLoop = true, InterleaveLoop = true;
- if (Requirements.doesNotMeet(F, Hints)) {
+ if (Requirements.doesNotMeet(F, L, Hints)) {
DEBUG(dbgs() << "LV: Not vectorizing: loop did not meet vectorization "
"requirements.\n");
emitMissedWarning(F, L, Hints);
return false;
}
- if (LAI->getNumRuntimePointerChecks() >
- VectorizerParams::RuntimeMemoryCheckThreshold) {
- emitAnalysis(VectorizationReport()
- << LAI->getNumRuntimePointerChecks() << " exceeds limit of "
- << VectorizerParams::RuntimeMemoryCheckThreshold
- << " dependent memory operations checked at runtime");
- DEBUG(dbgs() << "LV: Too many memory checks needed.\n");
- return false;
- }
+ Requirements->addRuntimePointerChecks(LAI->getNumRuntimePointerChecks());
+
return true;
}
-; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s
+; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -pass-remarks=loop-vectorize -pass-remarks-missed=loop-vectorize -S 2>&1 | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"
+; First loop produced diagnostic pass remark.
+;CHECK: remark: {{.*}}:0:0: vectorized loop (vectorization width: 4, interleaved count: 1)
+; Second loop produces diagnostic analysis remark.
+;CHECK: remark: {{.*}}:0:0: loop not vectorized: cannot prove pointers refer to independent arrays in memory. The loop requires 11 runtime independence checks to vectorize the loop, but that would exceed the limit of 8 checks
+
; We are vectorizing with 6 runtime checks.
;CHECK-LABEL: func1x6(
;CHECK: <4 x i32>