Index: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -134,6 +134,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/InjectTLIMappings.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopSimplify.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include "llvm/Transforms/Utils/LoopVersioning.h" @@ -3691,9 +3692,32 @@ for (Instruction *PI : PredicatedInstructions) sinkScalarOperands(&*PI); + // Remove redundant induction instructions. cse(LoopVectorBody); + // If there is an old induction variable we want it to have a meaningful value + // during the vector operations. + if (llvm::PHINode *OldInduction = Legal->getPrimaryInduction()) { + LLVM_DEBUG(dbgs() << "LV: Inspecting induction PHI node : " << *OldInduction + << "\n"); + // The induction PHINode's debug intrinsics, which will represent the source + // induction variable. + SmallVector DbgUsers; + findDbgUsers(DbgUsers, OldInduction); + // All debug users of the now undef induction variable must also be undef + for(auto &User: DbgUsers) { + LLVM_DEBUG(dbgs() << "LV: Update induction source variable or dependant: " + << User->getVariable()->getName() << "\n "); + Instruction *NewDbgII = User->clone(); + Value *Undef = UndefValue::get(OldInduction->getType()); + NewDbgII->setOperand(0, + MetadataAsValue::get(User->getContext(), + ValueAsMetadata::get(Undef))); + NewDbgII->insertBefore(&*LoopVectorBody->getFirstInsertionPt()); + } + } + // Set/update profile weights for the vector and remainder loops as original // loop iterations are now distributed among them. Note that original loop // represented by LoopScalarBody becomes remainder loop after vectorization. @@ -7079,7 +7103,7 @@ VPlans.front()->execute(&State); // 3. Fix the vectorized code: take care of header phi's, live-outs, - // predication, updating analyses. + // predication, updating analyses, debuginfo. ILV.fixVectorizedLoop(); } Index: llvm/test/DebugInfo/pr39018.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/pr39018.ll @@ -0,0 +1,176 @@ +;; PR39018 +;; Ensure that the loop vectorizer updates the debuginfo +;; for the source induction variable. + +;; Source: +;; #include + +;; #define BUFSZ 192 + +;; int +;; main() +;; { +;; int foo[BUFSZ]; +;; int bar[BUFSZ]; + +;; memset(foo, 0, sizeof(foo)); +;; memset(bar, 1, sizeof(bar)); + +;; for (int i = 0; i < BUFSZ; i++) +;; foo[i] += bar[i]; + +;; unsigned int sum = 0; +;; for (int j; j < BUFSZ; j++) +;; sum += foo[j]; + +;; return sum; +;; } + +; RUN: opt %s -loop-vectorize -S -o - | FileCheck %s + +; CHECK: entry: +; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[i:[0-9]+]] +; CHECK-NEXT: br i1 false, +; CHECK: vector.body: +; CHECK-NEXT: %index = phi i64 +; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 undef, metadata ![[i]], + +; ModuleID = './demo_base.ll' +source_filename = "demo.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: nounwind readnone uwtable +define dso_local i32 @main() local_unnamed_addr !dbg !7 { +entry: + %foo = alloca [192 x i32], align 16 + %bar = alloca [192 x i32], align 16 + %0 = bitcast [192 x i32]* %foo to i8*, !dbg !23 + call void @llvm.lifetime.start.p0i8(i64 768, i8* nonnull %0) #4, !dbg !23 + call void @llvm.dbg.declare(metadata [192 x i32]* %foo, metadata !12, metadata !DIExpression()), !dbg !24 + %1 = bitcast [192 x i32]* %bar to i8*, !dbg !25 + call void @llvm.lifetime.start.p0i8(i64 768, i8* nonnull %1) #4, !dbg !25 + call void @llvm.dbg.declare(metadata [192 x i32]* %bar, metadata !16, metadata !DIExpression()), !dbg !26 + call void @llvm.memset.p0i8.i64(i8* nonnull align 16 dereferenceable(768) %0, i8 0, i64 768, i1 false), !dbg !27 + call void @llvm.memset.p0i8.i64(i8* nonnull align 16 dereferenceable(768) %1, i8 1, i64 768, i1 false), !dbg !28 + call void @llvm.dbg.value(metadata i32 0, metadata !17, metadata !DIExpression()), !dbg !29 + br label %for.body, !dbg !30 + +for.body: ; preds = %entry, %for.body + %indvars.iv13 = phi i64 [ 0, %entry ], [ %indvars.iv.next14, %for.body ] + call void @llvm.dbg.value(metadata i64 %indvars.iv13, metadata !17, metadata !DIExpression()), !dbg !29 + %arrayidx = getelementptr inbounds [192 x i32], [192 x i32]* %bar, i64 0, i64 %indvars.iv13, !dbg !31 + %2 = load i32, i32* %arrayidx, align 4, !dbg !31, !tbaa !33 + %arrayidx3 = getelementptr inbounds [192 x i32], [192 x i32]* %foo, i64 0, i64 %indvars.iv13, !dbg !37 + %3 = load i32, i32* %arrayidx3, align 4, !dbg !38, !tbaa !33 + %add = add nsw i32 %3, %2, !dbg !38 + store i32 %add, i32* %arrayidx3, align 4, !dbg !38, !tbaa !33 + %indvars.iv.next14 = add nuw nsw i64 %indvars.iv13, 1, !dbg !39 + call void @llvm.dbg.value(metadata i64 %indvars.iv.next14, metadata !17, metadata !DIExpression()), !dbg !29 + %exitcond15.not = icmp eq i64 %indvars.iv.next14, 192, !dbg !40 + br i1 %exitcond15.not, label %for.body7.preheader, label %for.body, !dbg !30, !llvm.loop !41 + +for.body7.preheader: ; preds = %for.body + br label %for.body7, !dbg !44 + +for.cond.cleanup6: ; preds = %for.body7 + %add10.lcssa = phi i32 [ %add10, %for.body7 ], !dbg !45 + call void @llvm.dbg.value(metadata i32 %add10.lcssa, metadata !19, metadata !DIExpression()), !dbg !47 + call void @llvm.lifetime.end.p0i8(i64 768, i8* nonnull %1) #4, !dbg !48 + call void @llvm.lifetime.end.p0i8(i64 768, i8* nonnull %0) #4, !dbg !48 + ret i32 %add10.lcssa, !dbg !49 + +for.body7: ; preds = %for.body7.preheader, %for.body7 + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body7 ], [ 0, %for.body7.preheader ] + %sum.010 = phi i32 [ %add10, %for.body7 ], [ 0, %for.body7.preheader ] + call void @llvm.dbg.value(metadata i64 %indvars.iv, metadata !21, metadata !DIExpression()), !dbg !50 + call void @llvm.dbg.value(metadata i32 %sum.010, metadata !19, metadata !DIExpression()), !dbg !47 + %arrayidx9 = getelementptr inbounds [192 x i32], [192 x i32]* %foo, i64 0, i64 %indvars.iv, !dbg !51 + %4 = load i32, i32* %arrayidx9, align 4, !dbg !51, !tbaa !33 + %add10 = add i32 %4, %sum.010, !dbg !45 + call void @llvm.dbg.value(metadata i32 %add10, metadata !19, metadata !DIExpression()), !dbg !47 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !52 + call void @llvm.dbg.value(metadata i64 %indvars.iv.next, metadata !21, metadata !DIExpression()), !dbg !50 + %exitcond.not = icmp eq i64 %indvars.iv.next, 192, !dbg !53 + br i1 %exitcond.not, label %for.cond.cleanup6, label %for.body7, !dbg !44, !llvm.loop !54 +} + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 + +; Function Attrs: argmemonly nounwind willreturn writeonly +declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + + +attributes #0 = { nounwind readnone speculatable willreturn } + + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "demo.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 12.0.0 "} +!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !8, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12, !16, !17, !19, !21} +!12 = !DILocalVariable(name: "foo", scope: !7, file: !1, line: 8, type: !13) +!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 6144, elements: !14) +!14 = !{!15} +!15 = !DISubrange(count: 192) +!16 = !DILocalVariable(name: "bar", scope: !7, file: !1, line: 9, type: !13) +!17 = !DILocalVariable(name: "i", scope: !18, file: !1, line: 14, type: !10) +!18 = distinct !DILexicalBlock(scope: !7, file: !1, line: 14, column: 3) +!19 = !DILocalVariable(name: "sum", scope: !7, file: !1, line: 17, type: !20) +!20 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!21 = !DILocalVariable(name: "j", scope: !22, file: !1, line: 18, type: !10) +!22 = distinct !DILexicalBlock(scope: !7, file: !1, line: 18, column: 3) +!23 = !DILocation(line: 8, column: 3, scope: !7) +!24 = !DILocation(line: 8, column: 7, scope: !7) +!25 = !DILocation(line: 9, column: 3, scope: !7) +!26 = !DILocation(line: 9, column: 7, scope: !7) +!27 = !DILocation(line: 11, column: 3, scope: !7) +!28 = !DILocation(line: 12, column: 3, scope: !7) +!29 = !DILocation(line: 0, scope: !18) +!30 = !DILocation(line: 14, column: 3, scope: !18) +!31 = !DILocation(line: 15, column: 15, scope: !32) +!32 = distinct !DILexicalBlock(scope: !18, file: !1, line: 14, column: 3) +!33 = !{!34, !34, i64 0} +!34 = !{!"int", !35, i64 0} +!35 = !{!"omnipotent char", !36, i64 0} +!36 = !{!"Simple C/C++ TBAA"} +!37 = !DILocation(line: 15, column: 5, scope: !32) +!38 = !DILocation(line: 15, column: 12, scope: !32) +!39 = !DILocation(line: 14, column: 31, scope: !32) +!40 = !DILocation(line: 14, column: 21, scope: !32) +!41 = distinct !{!41, !30, !42, !43} +!42 = !DILocation(line: 15, column: 20, scope: !18) +!43 = !{!"llvm.loop.unroll.disable"} +!44 = !DILocation(line: 18, column: 3, scope: !22) +!45 = !DILocation(line: 19, column: 9, scope: !46) +!46 = distinct !DILexicalBlock(scope: !22, file: !1, line: 18, column: 3) +!47 = !DILocation(line: 0, scope: !7) +!48 = !DILocation(line: 22, column: 1, scope: !7) +!49 = !DILocation(line: 21, column: 3, scope: !7) +!50 = !DILocation(line: 0, scope: !22) +!51 = !DILocation(line: 19, column: 12, scope: !46) +!52 = !DILocation(line: 18, column: 31, scope: !46) +!53 = !DILocation(line: 18, column: 21, scope: !46) +!54 = distinct !{!54, !44, !55, !43} +!55 = !DILocation(line: 19, column: 17, scope: !22)