From 22876919c3443a5a2b6977fdc62531097937d2c4 Mon Sep 17 00:00:00 2001 From: Tyler Nowicki Date: Mon, 10 Aug 2015 23:01:55 +0000 Subject: [PATCH] Extend late diagnostics to include late test for runtime pointer checks. This patch moves checking the threshold of runtime pointer checks to the vectorization requirements (late diagnostics) and emits a diagnostic that infroms the user the loop would be vectorized if not for exceeding the pointer-check threshold. Clang will also append the options that can be used to allow vectorization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244523 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/DiagnosticInfo.h | 40 +++++++++++++++++ lib/IR/DiagnosticInfo.cpp | 9 ++++ lib/Transforms/Vectorize/LoopVectorize.cpp | 43 +++++++++++++------ .../Transforms/LoopVectorize/runtime-limit.ll | 7 ++- 4 files changed, 84 insertions(+), 15 deletions(-) diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 0df38133f3d..abd69ff9708 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -57,6 +57,7 @@ enum DiagnosticKind { DK_OptimizationRemarkMissed, DK_OptimizationRemarkAnalysis, DK_OptimizationRemarkAnalysisFPCommute, + DK_OptimizationRemarkAnalysisAliasing, DK_OptimizationFailure, DK_MIRParser, DK_FirstPluginKind @@ -421,6 +422,33 @@ public: } }; +/// 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; @@ -483,6 +511,18 @@ void emitOptimizationRemarkAnalysisFPCommute(LLVMContext &Ctx, 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 { diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 07c6714e913..3acef9048cc 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -205,6 +205,15 @@ void llvm::emitOptimizationRemarkAnalysisFPCommute(LLVMContext &Ctx, 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; diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 9cfd5feca2d..37d6add20a2 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1435,7 +1435,8 @@ static void emitMissedWarning(Function *F, Loop *L, /// 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. @@ -1443,7 +1444,11 @@ public: 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) { @@ -1453,12 +1458,29 @@ public: "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; }; @@ -1714,7 +1736,7 @@ struct LoopVectorize : public FunctionPass { 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); @@ -4297,15 +4319,8 @@ bool LoopVectorizationLegality::canVectorizeMemory() { 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; } diff --git a/test/Transforms/LoopVectorize/runtime-limit.ll b/test/Transforms/LoopVectorize/runtime-limit.ll index 6bc71e160cc..ff8d15576c0 100644 --- a/test/Transforms/LoopVectorize/runtime-limit.ll +++ b/test/Transforms/LoopVectorize/runtime-limit.ll @@ -1,8 +1,13 @@ -; 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> -- 2.34.1