1; RUN: opt < %s -loop-vectorize -transform-warning -S -pass-remarks-missed='loop-vectorize' -pass-remarks-analysis='loop-vectorize' -enable-new-pm=0 2>&1 | FileCheck %s 2; RUN: opt < %s -loop-vectorize -transform-warning -o /dev/null -pass-remarks-output=%t.yaml -enable-new-pm=0 3; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s 4 5; RUN: opt < %s -passes=loop-vectorize,transform-warning -S -pass-remarks-missed='loop-vectorize' -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s 6; RUN: opt < %s -passes=loop-vectorize,transform-warning -o /dev/null -pass-remarks-output=%t.yaml 7; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s 8 9; C/C++ code for tests 10; void test(int *A, int Length) { 11; #pragma clang loop vectorize(enable) interleave(enable) 12; for (int i = 0; i < Length; i++) { 13; A[i] = i; 14; if (A[i] > Length) 15; break; 16; } 17; } 18; File, line, and column should match those specified in the metadata 19; CHECK: remark: source.cpp:5:9: loop not vectorized: could not determine number of loop iterations 20; CHECK: remark: source.cpp:5:9: loop not vectorized 21 22; void test_disabled(int *A, int Length) { 23; #pragma clang loop vectorize(disable) interleave(disable) 24; for (int i = 0; i < Length; i++) 25; A[i] = i; 26; } 27; CHECK: remark: source.cpp:12:8: loop not vectorized: vectorization and interleaving are explicitly disabled, or the loop has already been vectorized 28 29; void test_array_bounds(int *A, int *B, int Length) { 30; #pragma clang loop vectorize(enable) 31; for (int i = 0; i < Length; i++) 32; A[i] = A[B[i]]; 33; } 34; CHECK: remark: source.cpp:19:5: loop not vectorized: cannot identify array bounds 35; CHECK: remark: source.cpp:19:5: loop not vectorized 36; CHECK: warning: source.cpp:19:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering 37 38; int foo(); 39; void test_multiple_failures(int *A) { 40; int k = 0; 41; #pragma clang loop vectorize(enable) interleave(enable) 42; for (int i = 0; i < 1000; i+=A[i]) { 43; if (A[i]) 44; k = foo(); 45; } 46; return k; 47; } 48; CHECK: remark: source.cpp:29:7: loop not vectorized: control flow cannot be substituted for a select 49; CHECK: remark: source.cpp:27:3: loop not vectorized 50 51; YAML: --- !Analysis 52; YAML-NEXT: Pass: loop-vectorize 53; YAML-NEXT: Name: CantComputeNumberOfIterations 54; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 5, Column: 9 } 55; YAML-NEXT: Function: _Z4testPii 56; YAML-NEXT: Args: 57; YAML-NEXT: - String: 'loop not vectorized: ' 58; YAML-NEXT: - String: could not determine number of loop iterations 59; YAML-NEXT: ... 60; YAML-NEXT: --- !Missed 61; YAML-NEXT: Pass: loop-vectorize 62; YAML-NEXT: Name: MissedDetails 63; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 5, Column: 9 } 64; YAML-NEXT: Function: _Z4testPii 65; YAML-NEXT: Args: 66; YAML-NEXT: - String: loop not vectorized 67; YAML-NEXT: ... 68; YAML-NEXT: --- !Analysis 69; YAML-NEXT: Pass: loop-vectorize 70; YAML-NEXT: Name: AllDisabled 71; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 12, Column: 8 } 72; YAML-NEXT: Function: _Z13test_disabledPii 73; YAML-NEXT: Args: 74; YAML-NEXT: - String: 'loop not vectorized: vectorization and interleaving are explicitly disabled, or the loop has already been vectorized 75; YAML-NEXT: ... 76; YAML-NEXT: --- !Analysis 77; YAML-NEXT: Pass: '' 78; YAML-NEXT: Name: CantIdentifyArrayBounds 79; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 19, Column: 5 } 80; YAML-NEXT: Function: _Z17test_array_boundsPiS_i 81; YAML-NEXT: Args: 82; YAML-NEXT: - String: 'loop not vectorized: ' 83; YAML-NEXT: - String: cannot identify array bounds 84; YAML-NEXT: ... 85; YAML-NEXT: --- !Missed 86; YAML-NEXT: Pass: loop-vectorize 87; YAML-NEXT: Name: MissedDetails 88; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 19, Column: 5 } 89; YAML-NEXT: Function: _Z17test_array_boundsPiS_i 90; YAML-NEXT: Args: 91; YAML-NEXT: - String: loop not vectorized 92; YAML-NEXT: - String: ' (Force=' 93; YAML-NEXT: - Force: 'true' 94; YAML-NEXT: - String: ')' 95; YAML-NEXT: ... 96; YAML-NEXT: --- !Failure 97; YAML-NEXT: Pass: transform-warning 98; YAML-NEXT: Name: FailedRequestedVectorization 99; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 19, Column: 5 } 100; YAML-NEXT: Function: _Z17test_array_boundsPiS_i 101; YAML-NEXT: Args: 102; YAML-NEXT: - String: 'loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering' 103; YAML-NEXT: ... 104; YAML-NEXT: --- !Analysis 105; YAML-NEXT: Pass: loop-vectorize 106; YAML-NEXT: Name: NoCFGForSelect 107; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 29, Column: 7 } 108; YAML-NEXT: Function: test_multiple_failures 109; YAML-NEXT: Args: 110; YAML-NEXT: - String: 'loop not vectorized: ' 111; YAML-NEXT: - String: control flow cannot be substituted for a select 112; YAML-NEXT: ... 113; YAML-NEXT: --- !Analysis 114; YAML-NEXT: Pass: loop-vectorize 115; YAML-NEXT: Name: NonReductionValueUsedOutsideLoop 116; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 27, Column: 3 } 117; YAML-NEXT: Function: test_multiple_failures 118; YAML-NEXT: Args: 119; YAML-NEXT: - String: 'loop not vectorized: ' 120; YAML-NEXT: - String: value that could not be identified as reduction is used outside the loop 121; YAML-NEXT: ... 122; YAML-NEXT: --- !Analysis 123; YAML-NEXT: Pass: loop-vectorize 124; YAML-NEXT: Name: CantComputeNumberOfIterations 125; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 27, Column: 3 } 126; YAML-NEXT: Function: test_multiple_failures 127; YAML-NEXT: Args: 128; YAML-NEXT: - String: 'loop not vectorized: ' 129; YAML-NEXT: - String: could not determine number of loop iterations 130; YAML-NEXT: ... 131; YAML-NEXT: --- !Missed 132; YAML-NEXT: Pass: loop-vectorize 133; YAML-NEXT: Name: MissedDetails 134; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 27, Column: 3 } 135; YAML-NEXT: Function: test_multiple_failures 136; YAML-NEXT: Args: 137; YAML-NEXT: - String: loop not vectorized 138; YAML-NEXT: ... 139 140target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 141 142; Function Attrs: nounwind optsize ssp uwtable 143define void @_Z4testPii(i32* nocapture %A, i32 %Length) #0 !dbg !4 { 144entry: 145 %cmp10 = icmp sgt i32 %Length, 0, !dbg !12 146 br i1 %cmp10, label %for.body, label %for.end, !dbg !12, !llvm.loop !14 147 148for.body: ; preds = %entry, %for.body 149 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] 150 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv, !dbg !16 151 %0 = trunc i64 %indvars.iv to i32, !dbg !16 152 %ld = load i32, i32* %arrayidx, align 4 153 store i32 %0, i32* %arrayidx, align 4, !dbg !16, !tbaa !18 154 %cmp3 = icmp sle i32 %ld, %Length, !dbg !22 155 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !12 156 %1 = trunc i64 %indvars.iv.next to i32 157 %cmp = icmp slt i32 %1, %Length, !dbg !12 158 %or.cond = and i1 %cmp3, %cmp, !dbg !22 159 br i1 %or.cond, label %for.body, label %for.end, !dbg !22 160 161for.end: ; preds = %for.body, %entry 162 ret void, !dbg !24 163} 164 165; CHECK: _Z4testPii 166; CHECK-NOT: x i32> 167; CHECK: ret 168 169; Function Attrs: nounwind optsize ssp uwtable 170define void @_Z13test_disabledPii(i32* nocapture %A, i32 %Length) #0 !dbg !7 { 171entry: 172 %cmp4 = icmp sgt i32 %Length, 0, !dbg !25 173 br i1 %cmp4, label %for.body, label %for.end, !dbg !25, !llvm.loop !27 174 175for.body: ; preds = %entry, %for.body 176 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] 177 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv, !dbg !30 178 %0 = trunc i64 %indvars.iv to i32, !dbg !30 179 store i32 %0, i32* %arrayidx, align 4, !dbg !30, !tbaa !18 180 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !25 181 %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !25 182 %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !25 183 br i1 %exitcond, label %for.end, label %for.body, !dbg !25, !llvm.loop !27 184 185for.end: ; preds = %for.body, %entry 186 ret void, !dbg !31 187} 188 189; CHECK: _Z13test_disabledPii 190; CHECK-NOT: x i32> 191; CHECK: ret 192 193; Function Attrs: nounwind optsize ssp uwtable 194define void @_Z17test_array_boundsPiS_i(i32* nocapture %A, i32* nocapture readonly %B, i32 %Length) #0 !dbg !8 { 195entry: 196 %cmp9 = icmp sgt i32 %Length, 0, !dbg !32 197 br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32, !llvm.loop !34 198 199for.body.preheader: ; preds = %entry 200 br label %for.body, !dbg !35 201 202for.body: ; preds = %for.body.preheader, %for.body 203 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ] 204 %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv, !dbg !35 205 %0 = load i32, i32* %arrayidx, align 4, !dbg !35, !tbaa !18 206 %idxprom1 = sext i32 %0 to i64, !dbg !35 207 %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1, !dbg !35 208 %1 = load i32, i32* %arrayidx2, align 4, !dbg !35, !tbaa !18 209 %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv, !dbg !35 210 store i32 %1, i32* %arrayidx4, align 4, !dbg !35, !tbaa !18 211 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !32 212 %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !32 213 %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !32 214 br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !32, !llvm.loop !34 215 216for.end.loopexit: ; preds = %for.body 217 br label %for.end 218 219for.end: ; preds = %for.end.loopexit, %entry 220 ret void, !dbg !36 221} 222 223; CHECK: _Z17test_array_boundsPiS_i 224; CHECK-NOT: x i32> 225; CHECK: ret 226 227; Function Attrs: nounwind uwtable 228define i32 @test_multiple_failures(i32* nocapture readonly %A) #0 !dbg !46 { 229entry: 230 br label %for.body, !dbg !38 231 232for.body: ; preds = %entry, %for.inc 233 %i.09 = phi i32 [ 0, %entry ], [ %add, %for.inc ] 234 %k.09 = phi i32 [ 0, %entry ], [ %k.1, %for.inc ] 235 %arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.09, !dbg !40 236 %0 = load i32, i32* %arrayidx, align 4, !dbg !40 237 %tobool = icmp eq i32 %0, 0, !dbg !40 238 br i1 %tobool, label %for.inc, label %if.then, !dbg !40 239 240if.then: ; preds = %for.body 241 %call = tail call i32 (...) @foo(), !dbg !41 242 %.pre = load i32, i32* %arrayidx, align 4 243 br label %for.inc, !dbg !42 244 245for.inc: ; preds = %for.body, %if.then 246 %1 = phi i32 [ %.pre, %if.then ], [ 0, %for.body ], !dbg !43 247 %k.1 = phi i32 [ %call, %if.then ], [ %k.09, %for.body ] 248 %add = add nsw i32 %1, %i.09, !dbg !44 249 %cmp = icmp slt i32 %add, 1000, !dbg !45 250 br i1 %cmp, label %for.body, label %for.cond.cleanup, !dbg !38 251 252for.cond.cleanup: ; preds = %for.inc 253 ret i32 %k.1, !dbg !39 254} 255 256declare i32 @foo(...) 257 258; CHECK: test_multiple_failure 259; CHECK-NOT: x i32> 260; CHECK: ret 261 262attributes #0 = { nounwind } 263 264!llvm.dbg.cu = !{!0} 265!llvm.module.flags = !{!9, !10} 266!llvm.ident = !{!11} 267 268!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) 269!1 = !DIFile(filename: "source.cpp", directory: ".") 270!2 = !{} 271!4 = distinct !DISubprogram(name: "test", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) 272!5 = !DIFile(filename: "source.cpp", directory: ".") 273!6 = !DISubroutineType(types: !2) 274!7 = distinct !DISubprogram(name: "test_disabled", line: 10, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6, retainedNodes: !2) 275!8 = distinct !DISubprogram(name: "test_array_bounds", line: 16, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 16, file: !1, scope: !5, type: !6, retainedNodes: !2) 276!9 = !{i32 2, !"Dwarf Version", i32 2} 277!10 = !{i32 2, !"Debug Info Version", i32 3} 278!11 = !{!"clang version 3.5.0"} 279!12 = !DILocation(line: 3, column: 8, scope: !13) 280!13 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope: !4) 281!14 = !{!14, !15, !15} 282!15 = !{!"llvm.loop.vectorize.enable", i1 true} 283!16 = !DILocation(line: 4, column: 5, scope: !17) 284!17 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope: !13) 285!18 = !{!19, !19, i64 0} 286!19 = !{!"int", !20, i64 0} 287!20 = !{!"omnipotent char", !21, i64 0} 288!21 = !{!"Simple C/C++ TBAA"} 289!22 = !DILocation(line: 5, column: 9, scope: !23) 290!23 = distinct !DILexicalBlock(line: 5, column: 9, file: !1, scope: !17) 291!24 = !DILocation(line: 8, column: 1, scope: !4) 292!25 = !DILocation(line: 12, column: 8, scope: !26) 293!26 = distinct !DILexicalBlock(line: 12, column: 3, file: !1, scope: !7) 294!27 = !{!27, !28, !29} 295!28 = !{!"llvm.loop.interleave.count", i32 1} 296!29 = !{!"llvm.loop.vectorize.width", i32 1} 297!30 = !DILocation(line: 13, column: 5, scope: !26) 298!31 = !DILocation(line: 14, column: 1, scope: !7) 299!32 = !DILocation(line: 18, column: 8, scope: !33) 300!33 = distinct !DILexicalBlock(line: 18, column: 3, file: !1, scope: !8) 301!34 = !{!34, !15} 302!35 = !DILocation(line: 19, column: 5, scope: !33) 303!36 = !DILocation(line: 20, column: 1, scope: !8) 304!37 = distinct !DILexicalBlock(line: 24, column: 3, file: !1, scope: !46) 305!38 = !DILocation(line: 27, column: 3, scope: !37) 306!39 = !DILocation(line: 31, column: 3, scope: !37) 307!40 = !DILocation(line: 28, column: 9, scope: !37) 308!41 = !DILocation(line: 29, column: 11, scope: !37) 309!42 = !DILocation(line: 29, column: 7, scope: !37) 310!43 = !DILocation(line: 27, column: 32, scope: !37) 311!44 = !DILocation(line: 27, column: 30, scope: !37) 312!45 = !DILocation(line: 27, column: 21, scope: !37) 313!46 = distinct !DISubprogram(name: "test_multiple_failures", line: 26, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 26, file: !1, scope: !5, type: !6, retainedNodes: !2) 314