Index: lib/Transforms/Vectorize/LoopVectorize.cpp
===================================================================
--- lib/Transforms/Vectorize/LoopVectorize.cpp	(revision 210586)
+++ lib/Transforms/Vectorize/LoopVectorize.cpp	(working copy)
@@ -209,6 +209,24 @@
 class LoopVectorizationLegality;
 class LoopVectorizationCostModel;
 
+/// Optimization analysis message produced during vectorization. Messages inform
+/// the user why vectorization did not occur including reporting any
+/// unvectorizable variables, types, and function calls.
+class Report {
+  std::string Message;
+  raw_string_ostream Out;
+
+public:
+  Report() : Out(Message) { Out << "loop not vectorized: "; }
+
+  template <typename A> Report &operator<<(A &Value) {
+    Out << Value;
+    return *this;
+  }
+
+  std::string &str() { return Out.str(); }
+};
+
 /// InnerLoopVectorizer vectorizes loops which contain only one basic
 /// block to a specified vectorization factor (VF).
 /// This class performs the widening of scalars into vectors, or multiple
@@ -515,10 +533,12 @@
   unsigned NumPredStores;
 
   LoopVectorizationLegality(Loop *L, ScalarEvolution *SE, const DataLayout *DL,
-                            DominatorTree *DT, TargetLibraryInfo *TLI)
+                            DominatorTree *DT, TargetLibraryInfo *TLI,
+                            Function *F)
       : NumLoads(0), NumStores(0), NumPredStores(0), TheLoop(L), SE(SE), DL(DL),
-        DT(DT), TLI(TLI), Induction(nullptr), WidestIndTy(nullptr),
-        HasFunNoNaNAttr(false), MaxSafeDepDistBytes(-1U) {}
+        DT(DT), TLI(TLI), TheFunction(F), Induction(nullptr),
+        WidestIndTy(nullptr), HasFunNoNaNAttr(false), MaxSafeDepDistBytes(-1U) {
+  }
 
   /// This enum represents the kinds of reductions that we support.
   enum ReductionKind {
@@ -747,6 +767,14 @@
   /// invariant.
   void collectStridedAcccess(Value *LoadOrStoreInst);
 
+  /// Report an analysis message to assist the user in diagnosing loops that are
+  /// not vectorized.
+  void emitAnalysis(Report &Message) {
+    emitOptimizationRemarkAnalysis(TheFunction->getContext(), DEBUG_TYPE,
+                                   *TheFunction, TheLoop->getStartLoc(),
+                                   Message.str());
+  }
+
   /// The loop that we evaluate.
   Loop *TheLoop;
   /// Scev analysis.
@@ -757,6 +785,8 @@
   DominatorTree *DT;
   /// Target Library Info.
   TargetLibraryInfo *TLI;
+  /// Parent function
+  Function *TheFunction;
 
   //  ---  vectorization state --- //
 
@@ -1155,10 +1185,16 @@
       }
     }
 
+    // Function containing loop
+    Function *F = L->getHeader()->getParent();
+
     // Check if it is legal to vectorize the loop.
-    LoopVectorizationLegality LVL(L, SE, DL, DT, TLI);
+    LoopVectorizationLegality LVL(L, SE, DL, DT, TLI, F);
     if (!LVL.canVectorize()) {
       DEBUG(dbgs() << "LV: Not vectorizing: Cannot prove legality.\n");
+      emitOptimizationRemarkMissed(
+          F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(),
+          "loop not vectorized");
       return false;
     }
 
@@ -1167,7 +1203,6 @@
 
     // Check the function attributes to find out if this function should be
     // optimized for size.
-    Function *F = L->getHeader()->getParent();
     bool OptForSize = Hints.getForce() != LoopVectorizeHints::FK_Enabled &&
                       F->hasFnAttribute(Attribute::OptimizeForSize);
 
@@ -1190,6 +1225,12 @@
     if (F->hasFnAttribute(Attribute::NoImplicitFloat)) {
       DEBUG(dbgs() << "LV: Can't vectorize when the NoImplicitFloat"
             "attribute is used.\n");
+      emitOptimizationRemarkAnalysis(
+          F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(),
+          "implicit floating point instructions are disabled due to "
+          "NoImplicitFloat attribute");
+      emitOptimizationRemarkMissed(F->getContext(), DEBUG_TYPE, *F,
+                                   L->getStartLoc(), "loop not vectorized");
       return false;
     }
 
@@ -1209,8 +1250,12 @@
 
     if (VF.Width == 1) {
       DEBUG(dbgs() << "LV: Vectorization is possible but not beneficial.\n");
-      if (UF == 1)
+      if (UF == 1) {
+        emitOptimizationRemarkMissed(
+            F->getContext(), DEBUG_TYPE, *F, L->getStartLoc(),
+            "not beneficial to vectorize and user disabled interleaving.");
         return false;
+      }
       DEBUG(dbgs() << "LV: Trying to at least unroll the loops.\n");
 
       // Report the unrolling decision.
@@ -1220,6 +1265,7 @@
                                    " (vectorization not beneficial)"));
 
       // We decided not to vectorize, but we may want to unroll.
+
       InnerLoopUnroller Unroller(L, SE, LI, DT, DL, TLI, UF);
       Unroller.vectorize(&LVL);
     } else {
@@ -3254,20 +3300,29 @@
 bool LoopVectorizationLegality::canVectorize() {
   // We must have a loop in canonical form. Loops with indirectbr in them cannot
   // be canonicalized.
-  if (!TheLoop->getLoopPreheader())
+  if (!TheLoop->getLoopPreheader()) {
+    emitAnalysis(
+        Report() << "loop is not in canonical form due to indirect branch");
     return false;
+  }
 
   // We can only vectorize innermost loops.
-  if (TheLoop->getSubLoopsVector().size())
+  if (TheLoop->getSubLoopsVector().size()) {
+    emitAnalysis(Report() << "loop is not the innermost loop");
     return false;
+  }
 
   // We must have a single backedge.
-  if (TheLoop->getNumBackEdges() != 1)
+  if (TheLoop->getNumBackEdges() != 1) {
+    emitAnalysis(Report() << "loop does not have a single backedge");
     return false;
+  }
 
   // We must have a single exiting block.
-  if (!TheLoop->getExitingBlock())
+  if (!TheLoop->getExitingBlock()) {
+    emitAnalysis(Report() << "loop does not have a single exit point");
     return false;
+  }
 
   // We need to have a loop header.
   DEBUG(dbgs() << "LV: Found a loop: " <<
@@ -3276,6 +3331,8 @@
   // Check if we can if-convert non-single-bb loops.
   unsigned NumBlocks = TheLoop->getNumBlocks();
   if (NumBlocks != 1 && !canVectorizeWithIfConvert()) {
+    emitAnalysis(Report() << "conditional branches could not be substituted "
+                             "for a select instruction");
     DEBUG(dbgs() << "LV: Can't if-convert the loop.\n");
     return false;
   }
@@ -3283,6 +3340,9 @@
   // ScalarEvolution needs to be able to find the exit count.
   const SCEV *ExitCount = SE->getBackedgeTakenCount(TheLoop);
   if (ExitCount == SE->getCouldNotCompute()) {
+    emitAnalysis(
+        Report()
+        << "scalar evolution could not determine number of loop iterations");
     DEBUG(dbgs() << "LV: SCEV could not compute the loop exit count.\n");
     return false;
   }
@@ -3335,7 +3395,8 @@
 /// \brief Check that the instruction has outside loop users and is not an
 /// identified reduction variable.
 static bool hasOutsideLoopUser(const Loop *TheLoop, Instruction *Inst,
-                               SmallPtrSet<Value *, 4> &Reductions) {
+                               SmallPtrSet<Value *, 4> &Reductions,
+                               Report *Message = nullptr) {
   // Reduction instructions are allowed to have exit users. All other
   // instructions must not have external users.
   if (!Reductions.count(Inst))
@@ -3344,6 +3405,8 @@
       Instruction *UI = cast<Instruction>(U);
       // This user may be a reduction exit value.
       if (!TheLoop->contains(UI)) {
+        if (Message)
+          *Message << "found an outside user for: " << *UI;
         DEBUG(dbgs() << "LV: Found an outside user for : " << *UI << '\n');
         return true;
       }
@@ -3376,6 +3439,7 @@
         if (!PhiTy->isIntegerTy() &&
             !PhiTy->isFloatingPointTy() &&
             !PhiTy->isPointerTy()) {
+          emitAnalysis(Report() << "non-int non-pointer PHI: " << PhiTy);
           DEBUG(dbgs() << "LV: Found an non-int non-pointer PHI.\n");
           return false;
         }
@@ -3386,13 +3450,18 @@
         if (*bb != Header) {
           // Check that this instruction has no outside users or is an
           // identified reduction value with an outside user.
-          if(!hasOutsideLoopUser(TheLoop, it, AllowedExit))
+          Report Message;
+          if (!hasOutsideLoopUser(TheLoop, it, AllowedExit, &Message))
             continue;
+          emitAnalysis(Message);
+          DEBUG(dbgs() << "LV: Found an non-int non-pointer PHI.\n");
           return false;
         }
 
         // We only allow if-converted PHIs with more than two incoming values.
         if (Phi->getNumIncomingValues() != 2) {
+          emitAnalysis(Report() << "conditional branch could not be "
+                                   "substituded for a select instruction");
           DEBUG(dbgs() << "LV: Found an invalid PHI.\n");
           return false;
         }
@@ -3467,6 +3536,7 @@
           continue;
         }
 
+        emitAnalysis(Report() << "unidentified PHI: " << *Phi);
         DEBUG(dbgs() << "LV: Found an unidentified PHI."<< *Phi <<"\n");
         return false;
       }// end of PHI handling
@@ -3475,6 +3545,7 @@
       // calls and we do handle certain intrinsic and libm functions.
       CallInst *CI = dyn_cast<CallInst>(it);
       if (CI && !getIntrinsicIDForCall(CI, TLI) && !isa<DbgInfoIntrinsic>(CI)) {
+        emitAnalysis(Report() << "call cannot be vectorized: " << *CI);
         DEBUG(dbgs() << "LV: Found a call site.\n");
         return false;
       }
@@ -3484,6 +3555,7 @@
       if (CI &&
           hasVectorInstrinsicScalarOpd(getIntrinsicIDForCall(CI, TLI), 1)) {
         if (!SE->isLoopInvariant(SE->getSCEV(CI->getOperand(1)), TheLoop)) {
+          emitAnalysis(Report() << "intrinsic cannot be vectorized: " << *CI);
           DEBUG(dbgs() << "LV: Found unvectorizable intrinsic " << *CI << "\n");
           return false;
         }
@@ -3493,6 +3565,8 @@
       // Also, we can't vectorize extractelement instructions.
       if ((!VectorType::isValidElementType(it->getType()) &&
            !it->getType()->isVoidTy()) || isa<ExtractElementInst>(it)) {
+        emitAnalysis(Report()
+                     << "type cannot be vectorized: " << *it->getType());
         DEBUG(dbgs() << "LV: Found unvectorizable type.\n");
         return false;
       }
@@ -3521,8 +3595,11 @@
 
   if (!Induction) {
     DEBUG(dbgs() << "LV: Did not find one integer induction var.\n");
-    if (Inductions.empty())
+    if (Inductions.empty()) {
+      emitAnalysis(Report()
+                   << "integer-type loop induction variable was not found");
       return false;
+    }
   }
 
   return true;
@@ -4429,8 +4506,8 @@
           continue;
 
         LoadInst *Ld = dyn_cast<LoadInst>(it);
-        if (!Ld) return false;
-        if (!Ld->isSimple() && !IsAnnotatedParallel) {
+        if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) {
+          emitAnalysis(Report() << "non-simple load");
           DEBUG(dbgs() << "LV: Found a non-simple load.\n");
           return false;
         }
@@ -4445,6 +4522,7 @@
         StoreInst *St = dyn_cast<StoreInst>(it);
         if (!St) return false;
         if (!St->isSimple() && !IsAnnotatedParallel) {
+          emitAnalysis(Report() << "non-simple store");
           DEBUG(dbgs() << "LV: Found a non-simple store.\n");
           return false;
         }
@@ -4481,6 +4559,7 @@
     Value* Ptr = ST->getPointerOperand();
 
     if (isUniform(Ptr)) {
+      emitAnalysis(Report() << "store into uniform address");
       DEBUG(dbgs() << "LV: We don't allow storing to uniform addresses\n");
       return false;
     }
@@ -4559,6 +4638,7 @@
   }
 
   if (NeedRTCheck && !CanDoRT) {
+    emitAnalysis(Report() << "cannot identify array bounds");
     DEBUG(dbgs() << "LV: We can't vectorize because we can't find " <<
           "the array bounds.\n");
     PtrRtCheck.reset();
@@ -4589,6 +4669,7 @@
       // Check that we did not collect too many pointers or found an unsizeable
       // pointer.
       if (!CanDoRT || NumComparisons > RuntimeMemoryCheckThreshold) {
+        emitAnalysis(Report() << "memory checks");
         DEBUG(dbgs() << "LV: Can't vectorize with memory checks\n");
         PtrRtCheck.reset();
         return false;
Index: test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll
===================================================================
--- test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll	(revision 0)
+++ test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll	(working copy)
@@ -0,0 +1,125 @@
+; RUN: opt < %s -O3 -mtriple=x86_64-unknown-linux -S -pass-remarks-missed='loop-vectorize' 2>&1 | FileCheck -check-prefix=MARK %s
+
+; MARK: remark: {{.*}}:5:5: loop not vectorized
+; MARK: remark: {{.*}}:10:5: loop not vectorized
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind ssp uwtable
+define void @test_calltest(i32* nocapture readonly %List, i32 %Length) #0 {
+entry:
+  %cmp3 = icmp sgt i32 %Length, 0, !dbg !11
+  br i1 %cmp3, label %for.body.preheader, label %for.end, !dbg !11
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body, !dbg !13
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]
+  %arrayidx = getelementptr inbounds i32* %List, i64 %indvars.iv, !dbg !13
+  %0 = load i32* %arrayidx, align 4, !dbg !13, !tbaa !14
+  %call = tail call i32 @calltest(i32 %0) #2, !dbg !13
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !11
+  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !11
+  %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !11
+  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !11
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void, !dbg !18
+}
+
+declare i32 @calltest(i32) #1
+
+; Function Attrs: nounwind ssp uwtable
+define void @test_array_bounds(i32* nocapture %List, i32 %Length) #0 {
+entry:
+  %cmp10 = icmp sgt i32 %Length, 0, !dbg !19
+  br i1 %cmp10, label %for.body.preheader, label %for.end, !dbg !19
+
+for.body.preheader:                               ; preds = %entry
+  %xtraiter = urem i32 %Length, 2
+  %lcmp = icmp ne i32 %xtraiter, 0
+  br i1 %lcmp, label %for.body.unr, label %for.body.preheader.split
+
+for.body.unr:                                     ; preds = %for.body.preheader
+  %arrayidx.unr = getelementptr inbounds i32* %List, i64 0, !dbg !21
+  %0 = load i32* %arrayidx.unr, align 4, !dbg !21, !tbaa !14
+  %idxprom3.unr = sext i32 %0 to i64, !dbg !21
+  %arrayidx4.unr = getelementptr inbounds i32* %List, i64 %idxprom3.unr, !dbg !21
+  store i32 %0, i32* %arrayidx4.unr, align 4, !dbg !21, !tbaa !14
+  %indvars.iv.next.unr = add nuw nsw i64 0, 1, !dbg !19
+  %lftr.wideiv.unr = trunc i64 %indvars.iv.next.unr to i32, !dbg !19
+  %exitcond.unr = icmp eq i32 %lftr.wideiv.unr, %Length, !dbg !19
+  br label %for.body.preheader.split
+
+for.body.preheader.split:                         ; preds = %for.body.unr, %for.body.preheader
+  %indvars.iv.unr = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next.unr, %for.body.unr ]
+  %1 = icmp ult i32 %Length, 2
+  br i1 %1, label %for.end.loopexit, label %for.body.preheader.split.split
+
+for.body.preheader.split.split:                   ; preds = %for.body.preheader.split
+  br label %for.body, !dbg !21
+
+for.body:                                         ; preds = %for.body, %for.body.preheader.split.split
+  %indvars.iv = phi i64 [ %indvars.iv.unr, %for.body.preheader.split.split ], [ %indvars.iv.next.1, %for.body ]
+  %arrayidx = getelementptr inbounds i32* %List, i64 %indvars.iv, !dbg !21
+  %2 = load i32* %arrayidx, align 4, !dbg !21, !tbaa !14
+  %idxprom3 = sext i32 %2 to i64, !dbg !21
+  %arrayidx4 = getelementptr inbounds i32* %List, i64 %idxprom3, !dbg !21
+  store i32 %2, i32* %arrayidx4, align 4, !dbg !21, !tbaa !14
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !19
+  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !19
+  %arrayidx.1 = getelementptr inbounds i32* %List, i64 %indvars.iv.next, !dbg !21
+  %3 = load i32* %arrayidx.1, align 4, !dbg !21, !tbaa !14
+  %idxprom3.1 = sext i32 %3 to i64, !dbg !21
+  %arrayidx4.1 = getelementptr inbounds i32* %List, i64 %idxprom3.1, !dbg !21
+  store i32 %3, i32* %arrayidx4.1, align 4, !dbg !21, !tbaa !14
+  %indvars.iv.next.1 = add nuw nsw i64 %indvars.iv.next, 1, !dbg !19
+  %lftr.wideiv.1 = trunc i64 %indvars.iv.next.1 to i32, !dbg !19
+  %exitcond.1 = icmp eq i32 %lftr.wideiv.1, %Length, !dbg !19
+  br i1 %exitcond.1, label %for.end.loopexit.unr-lcssa, label %for.body, !dbg !19
+
+for.end.loopexit.unr-lcssa:                       ; preds = %for.body
+  br label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body.preheader.split, %for.end.loopexit.unr-lcssa
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void, !dbg !22
+}
+
+attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 (http://llvm.org/git/clang.git 6cb9eb5cd6a98a2fb13ae499aa5cd3a8feaa14e0) (http://llvm.org/git/llvm.git 4887e4317ea978ee5ba25908c0f1cfac1abd095a)", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/Users/tnowicki/Development/feature_pragma_vectorize/vectorize_report3.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"vectorize_report3.c", metadata !"/Users/tnowicki/Development/feature_pragma_vectorize"}
+!2 = metadata !{}
+!3 = metadata !{metadata !4, metadata !7}
+!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_calltest", metadata !"test_calltest", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32)* @test_calltest, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [test_calltest]
+!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ] [/Users/tnowicki/Development/feature_pragma_vectorize/vectorize_report3.c]
+!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_array_bounds", metadata !"test_array_bounds", metadata !"", i32 8, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (i32*, i32)* @test_array_bounds, null, null, metadata !2, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [test_array_bounds]
+!8 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
+!9 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
+!10 = metadata !{metadata !"clang version 3.5.0 (http://llvm.org/git/clang.git 6cb9eb5cd6a98a2fb13ae499aa5cd3a8feaa14e0) (http://llvm.org/git/llvm.git 4887e4317ea978ee5ba25908c0f1cfac1abd095a)"}
+!11 = metadata !{i32 4, i32 8, metadata !12, null}
+!12 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/Users/tnowicki/Development/feature_pragma_vectorize/vectorize_report3.c]
+!13 = metadata !{i32 5, i32 5, metadata !12, null}
+!14 = metadata !{metadata !15, metadata !15, i64 0}
+!15 = metadata !{metadata !"int", metadata !16, i64 0}
+!16 = metadata !{metadata !"omnipotent char", metadata !17, i64 0}
+!17 = metadata !{metadata !"Simple C/C++ TBAA"}
+!18 = metadata !{i32 6, i32 1, metadata !4, null}
+!19 = metadata !{i32 9, i32 8, metadata !20, null}
+!20 = metadata !{i32 786443, metadata !1, metadata !7, i32 9, i32 3, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [/Users/tnowicki/Development/feature_pragma_vectorize/vectorize_report3.c]
+!21 = metadata !{i32 10, i32 5, metadata !20, null}
+!22 = metadata !{i32 11, i32 1, metadata !7, null}
Index: test/Transforms/LoopVectorize/ee-crash.ll
===================================================================
--- test/Transforms/LoopVectorize/ee-crash.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/ee-crash.ll	(working copy)
@@ -1,4 +1,5 @@
 ; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -S | FileCheck %s
+; RUN: opt < %s -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=MARK %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"
@@ -8,6 +9,7 @@
 ; CHECK-LABEL: @_Z4foo1Pii(
 ; CHECK-NOT: <4 x i32>
 ; CHECK: ret
+; MARK: remark: <unknown>:0:0: loop not vectorized: type cannot be vectorized: i32
 define i32 @_Z4foo1Pii(i32* %A, i32 %n, <2 x i32> %q) #0 {
 entry:
   %idx.ext = sext i32 %n to i64
Index: test/Transforms/LoopVectorize/gcc-examples.ll
===================================================================
--- test/Transforms/LoopVectorize/gcc-examples.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/gcc-examples.ll	(working copy)
@@ -1,5 +1,6 @@
 ; RUN: opt < %s  -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 -dce -instcombine -S | FileCheck %s
 ; RUN: opt < %s  -loop-vectorize -force-vector-width=4 -force-vector-unroll=4 -dce -instcombine -S | FileCheck %s -check-prefix=UNROLL
+; RUN: opt < %s  -loop-vectorize -force-vector-width=4 -force-vector-unroll=1 -dce -instcombine -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=MARK %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"
@@ -214,6 +215,7 @@
 ;UNROLL: store <4 x i32>
 ;UNROLL: store <4 x i32>
 ;UNROLL: ret void
+;MARK: remark: <unknown>:0:0: loop not vectorized: unidentified PHI
 define void @example8(i32 %x) nounwind uwtable ssp {
   br label %.preheader
 
Index: test/Transforms/LoopVectorize/hoist-loads.ll
===================================================================
--- test/Transforms/LoopVectorize/hoist-loads.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/hoist-loads.ll	(working copy)
@@ -1,4 +1,5 @@
 ; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S < %s | FileCheck %s
+; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-unroll=1 -S -pass-remarks-analysis='loop-vectorize' < %s 2>&1 | FileCheck -check-prefix=MARK %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"
 
@@ -8,7 +9,6 @@
 ; Make sure we can vectorize in the presence of hoistable conditional loads.
 ; CHECK-LABEL: @hoist_cond_load(
 ; CHECK: load <2 x float>
-
 define void @hoist_cond_load() {
 entry:
   br label %for.body
@@ -40,7 +40,7 @@
 ; accessed.
 ; CHECK-LABEL: @dont_hoist_cond_load(
 ; CHECK-NOT: load <2 x float>
-
+; MARK: remark: <unknown>:0:0: loop not vectorized: conditional branches could not be substituted for a select instruction
 define void @dont_hoist_cond_load() {
 entry:
   br label %for.body
Index: test/Transforms/LoopVectorize/if-conversion-reduction.ll
===================================================================
--- test/Transforms/LoopVectorize/if-conversion-reduction.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/if-conversion-reduction.ll	(working copy)
@@ -1,4 +1,5 @@
 ; RUN: opt < %s  -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s
+; RUN: opt < %s  -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=MARK %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.9.0"
@@ -6,6 +7,7 @@
 ;CHECK-LABEL: @reduction_func(
 ;CHECK-NOT: load <4 x i32>
 ;CHECK: ret i32
+;MARK: remark: <unknown>:0:0: loop not vectorized: unidentified PHI
 define i32 @reduction_func(i32* nocapture %A, i32 %n) nounwind uwtable readonly ssp {
 entry:
   %cmp10 = icmp sgt i32 %n, 0
Index: test/Transforms/LoopVectorize/if-conversion.ll
===================================================================
--- test/Transforms/LoopVectorize/if-conversion.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/if-conversion.ll	(working copy)
@@ -1,4 +1,5 @@
 ; RUN: opt < %s  -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -enable-if-conversion -dce -instcombine -S | FileCheck %s
+; RUN: opt < %s  -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -enable-if-conversion -dce -instcombine -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck -check-prefix=MARK %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.9.0"
@@ -70,6 +71,8 @@
 ;   return sum;
 ; }
 
+;MARK: remark: <unknown>:0:0: loop not vectorized: conditional branches could not be substituted for a select instruction
+
 ;CHECK-LABEL: @reduction_func(
 ;CHECK: load <4 x i32>
 ;CHECK: icmp sgt <4 x i32>
@@ -116,6 +119,8 @@
 ; CHECK-LABEL: trapping_constant_expression
 ; CHECK-NOT: or <4 x i32>
 
+; MARK: remark: <unknown>:0:0: loop not vectorized: conditional branches could not be substituted for a select instruction
+
 define i32 @trapping_constant_expression() {
 entry:
   br label %for.body
Index: test/Transforms/LoopVectorize/no_outside_user.ll
===================================================================
--- test/Transforms/LoopVectorize/no_outside_user.ll	(revision 210586)
+++ test/Transforms/LoopVectorize/no_outside_user.ll	(working copy)
@@ -1,4 +1,5 @@
 ; RUN: opt -S -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 < %s | FileCheck %s
+; RUN: opt -S -loop-vectorize -force-vector-unroll=1 -force-vector-width=2 -pass-remarks-analysis='loop-vectorize' < %s 2>&1 | FileCheck -check-prefix=MARK %s
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
 
@@ -15,6 +16,8 @@
 ; CHECK-LABEL: @main(
 ; CHECK-NOT: <2 x i32>
 
+; MARK: remark: <unknown>:0:0: loop not vectorized: found an outside user for: %.lcssa = phi i32 [ %tmp17, %bb16 ]
+
 define i32 @main()  {
 bb:
   %b.promoted = load i32* @b, align 4
